@ruvector/ruvllm 4.0.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +446 -160
  2. package/bin/cli.js +1066 -0
  3. package/bin/gpu-delegate.js +67 -0
  4. package/bin/ruvllm-adapters.js +5 -0
  5. package/bin/ruvllm-gpu-loop.js +5 -0
  6. package/bin/serve.js +265 -0
  7. package/dist/cjs/benchmarks/embedding-benchmark.d.ts +102 -0
  8. package/dist/cjs/benchmarks/embedding-benchmark.d.ts.map +1 -0
  9. package/dist/cjs/benchmarks/embedding-benchmark.js +436 -0
  10. package/dist/cjs/benchmarks/index.d.ts +34 -0
  11. package/dist/cjs/benchmarks/index.d.ts.map +1 -0
  12. package/dist/cjs/benchmarks/index.js +132 -0
  13. package/dist/cjs/benchmarks/model-comparison.d.ts +71 -0
  14. package/dist/cjs/benchmarks/model-comparison.d.ts.map +1 -0
  15. package/dist/cjs/benchmarks/model-comparison.js +476 -0
  16. package/dist/cjs/benchmarks/routing-benchmark.d.ts +70 -0
  17. package/dist/cjs/benchmarks/routing-benchmark.d.ts.map +1 -0
  18. package/dist/cjs/benchmarks/routing-benchmark.js +289 -0
  19. package/dist/cjs/contrastive.d.ts +229 -0
  20. package/dist/cjs/contrastive.d.ts.map +1 -0
  21. package/dist/cjs/contrastive.js +589 -0
  22. package/dist/cjs/engine.d.ts +160 -0
  23. package/dist/cjs/engine.d.ts.map +1 -0
  24. package/dist/cjs/engine.js +552 -0
  25. package/dist/cjs/export.d.ts +182 -0
  26. package/dist/cjs/export.d.ts.map +1 -0
  27. package/dist/cjs/export.js +422 -0
  28. package/dist/cjs/federated.d.ts +233 -0
  29. package/dist/cjs/federated.d.ts.map +1 -0
  30. package/dist/cjs/federated.js +525 -0
  31. package/dist/cjs/index.d.ts +68 -0
  32. package/dist/cjs/index.d.ts.map +1 -0
  33. package/dist/cjs/index.js +104 -0
  34. package/dist/cjs/intelligence.d.ts +136 -0
  35. package/dist/cjs/intelligence.d.ts.map +1 -0
  36. package/dist/cjs/intelligence.js +226 -0
  37. package/dist/cjs/lora.d.ts +251 -0
  38. package/dist/cjs/lora.d.ts.map +1 -0
  39. package/dist/cjs/lora.js +509 -0
  40. package/dist/cjs/models.d.ts +129 -0
  41. package/dist/cjs/models.d.ts.map +1 -0
  42. package/dist/cjs/models.js +323 -0
  43. package/dist/cjs/native.d.ts +140 -0
  44. package/dist/cjs/native.d.ts.map +1 -0
  45. package/dist/cjs/native.js +98 -0
  46. package/dist/cjs/session.d.ts +80 -0
  47. package/dist/cjs/session.d.ts.map +1 -0
  48. package/dist/cjs/session.js +203 -0
  49. package/dist/cjs/simd.d.ts +90 -0
  50. package/dist/cjs/simd.d.ts.map +1 -0
  51. package/dist/cjs/simd.js +209 -0
  52. package/dist/cjs/sona.d.ts +223 -0
  53. package/dist/cjs/sona.d.ts.map +1 -0
  54. package/dist/cjs/sona.js +562 -0
  55. package/dist/cjs/streaming.d.ts +55 -0
  56. package/dist/cjs/streaming.d.ts.map +1 -0
  57. package/dist/cjs/streaming.js +131 -0
  58. package/dist/cjs/training.d.ts +312 -0
  59. package/dist/cjs/training.d.ts.map +1 -0
  60. package/dist/cjs/training.js +610 -0
  61. package/dist/cjs/types.d.ts +696 -0
  62. package/dist/cjs/types.d.ts.map +1 -0
  63. package/dist/cjs/types.js +6 -0
  64. package/dist/esm/benchmarks/embedding-benchmark.d.ts +102 -0
  65. package/dist/esm/benchmarks/embedding-benchmark.d.ts.map +1 -0
  66. package/dist/esm/benchmarks/embedding-benchmark.js +427 -0
  67. package/dist/esm/benchmarks/index.d.ts +34 -0
  68. package/dist/esm/benchmarks/index.d.ts.map +1 -0
  69. package/dist/esm/benchmarks/index.js +110 -0
  70. package/dist/esm/benchmarks/model-comparison.d.ts +71 -0
  71. package/dist/esm/benchmarks/model-comparison.d.ts.map +1 -0
  72. package/dist/esm/benchmarks/model-comparison.js +434 -0
  73. package/dist/esm/benchmarks/routing-benchmark.d.ts +70 -0
  74. package/dist/esm/benchmarks/routing-benchmark.d.ts.map +1 -0
  75. package/dist/esm/benchmarks/routing-benchmark.js +283 -0
  76. package/dist/esm/contrastive.d.ts +229 -0
  77. package/dist/esm/contrastive.d.ts.map +1 -0
  78. package/dist/esm/contrastive.js +578 -0
  79. package/dist/esm/engine.d.ts +160 -0
  80. package/dist/esm/engine.d.ts.map +1 -0
  81. package/dist/esm/engine.js +548 -0
  82. package/dist/esm/export.d.ts +182 -0
  83. package/dist/esm/export.d.ts.map +1 -0
  84. package/dist/esm/export.js +414 -0
  85. package/dist/esm/federated.d.ts +233 -0
  86. package/dist/esm/federated.d.ts.map +1 -0
  87. package/dist/esm/federated.js +520 -0
  88. package/dist/esm/index.d.ts +68 -0
  89. package/dist/esm/index.d.ts.map +1 -0
  90. package/dist/esm/index.js +84 -0
  91. package/dist/esm/intelligence.d.ts +136 -0
  92. package/dist/esm/intelligence.d.ts.map +1 -0
  93. package/dist/esm/intelligence.js +188 -0
  94. package/dist/esm/lora.d.ts +251 -0
  95. package/dist/esm/lora.d.ts.map +1 -0
  96. package/dist/esm/lora.js +504 -0
  97. package/dist/esm/models.d.ts +129 -0
  98. package/dist/esm/models.d.ts.map +1 -0
  99. package/dist/esm/models.js +282 -0
  100. package/dist/esm/native.d.ts +140 -0
  101. package/dist/esm/native.d.ts.map +1 -0
  102. package/dist/esm/native.js +100 -0
  103. package/dist/esm/session.d.ts +80 -0
  104. package/dist/esm/session.d.ts.map +1 -0
  105. package/dist/esm/session.js +199 -0
  106. package/dist/esm/simd.d.ts +90 -0
  107. package/dist/esm/simd.d.ts.map +1 -0
  108. package/dist/esm/simd.js +205 -0
  109. package/dist/esm/sona.d.ts +223 -0
  110. package/dist/esm/sona.d.ts.map +1 -0
  111. package/dist/esm/sona.js +556 -0
  112. package/dist/esm/streaming.d.ts +55 -0
  113. package/dist/esm/streaming.d.ts.map +1 -0
  114. package/dist/esm/streaming.js +126 -0
  115. package/dist/esm/training.d.ts +312 -0
  116. package/dist/esm/training.d.ts.map +1 -0
  117. package/dist/esm/training.js +603 -0
  118. package/dist/esm/types.d.ts +696 -0
  119. package/dist/esm/types.d.ts.map +1 -0
  120. package/dist/esm/types.js +5 -0
  121. package/gpu/_load.cjs +38 -0
  122. package/gpu/_load.mjs +33 -0
  123. package/gpu/adapters.cjs +3 -0
  124. package/gpu/adapters.mjs +5 -0
  125. package/gpu/engine.cjs +3 -0
  126. package/gpu/engine.mjs +5 -0
  127. package/gpu/fixture.cjs +3 -0
  128. package/gpu/fixture.mjs +5 -0
  129. package/gpu/gpu-host.cjs +3 -0
  130. package/gpu/gpu-host.mjs +5 -0
  131. package/gpu/gpu-loop.cjs +3 -0
  132. package/gpu/gpu-loop.mjs +5 -0
  133. package/gpu/gpu-spool-adapter.cjs +3 -0
  134. package/gpu/gpu-spool-adapter.mjs +5 -0
  135. package/gpu/vast-host-adapter.cjs +3 -0
  136. package/gpu/vast-host-adapter.mjs +5 -0
  137. package/package.json +159 -49
  138. package/scripts/ensemble-model-compare.js +287 -0
  139. package/scripts/fix-esm-extensions.mjs +220 -0
  140. package/scripts/huggingface/README.md +537 -0
  141. package/scripts/huggingface/publish.sh +112 -0
  142. package/scripts/hybrid-model-compare.js +373 -0
  143. package/scripts/improved-model-compare.js +288 -0
  144. package/scripts/optimized-model-compare.js +364 -0
  145. package/scripts/real-model-compare.js +280 -0
  146. package/scripts/smoke-esm.mjs +82 -0
  147. package/scripts/training/agentic-flow-capabilities.json +329 -0
  148. package/scripts/training/claude-code-synth.js +505 -0
  149. package/scripts/training/claude-flow-capabilities.json +1322 -0
  150. package/scripts/training/claude-hard-negatives.js +222 -0
  151. package/scripts/training/contrastive-finetune.js +517 -0
  152. package/scripts/training/ecosystem-triplets.jsonl +1467 -0
  153. package/scripts/training/generate-ecosystem-triplets.js +1324 -0
  154. package/scripts/training/routing-dataset.js +634 -0
  155. package/scripts/training/ruvector-capabilities.json +798 -0
  156. package/scripts/training/validate-ecosystem.js +381 -0
  157. package/scripts/training/validation-results.json +23 -0
  158. package/GPU-LOOP.md +0 -229
  159. package/LICENSE +0 -201
  160. package/NOTICE +0 -9
  161. package/examples/gpu-loop.example.json +0 -26
  162. package/src/adapters-cli.mjs +0 -23
  163. package/src/adapters.mjs +0 -91
  164. package/src/cli.mjs +0 -30
  165. package/src/engine.mjs +0 -238
  166. package/src/fixture.mjs +0 -38
  167. package/src/gpu-host.mjs +0 -47
  168. package/src/gpu-loop-cli.mjs +0 -67
  169. package/src/gpu-loop.mjs +0 -184
  170. package/src/gpu-spool-adapter.mjs +0 -80
  171. package/src/vast-host-adapter.mjs +0 -274
@@ -0,0 +1,562 @@
1
+ "use strict";
2
+ /**
3
+ * SONA (Self-Optimizing Neural Architecture) Learning System
4
+ *
5
+ * Provides adaptive learning capabilities with trajectory tracking,
6
+ * pattern recognition, and memory protection (EWC++).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.DEFAULT_SONA_CONFIG = exports.SonaCoordinator = exports.EwcManager = exports.ReasoningBank = exports.TrajectoryBuilder = void 0;
10
+ const lora_1 = require("./lora");
11
+ /** Embedding dimension used by the coordinator's hash embedder and micro-LoRA. */
12
+ const MICRO_LORA_DIM = 64;
13
+ /** Micro-LoRA rank: SONA's instant loop uses a tiny adapter (rank 1-2) by design. */
14
+ const MICRO_LORA_RANK = 2;
15
+ /**
16
+ * Default SONA configuration
17
+ */
18
+ const DEFAULT_SONA_CONFIG = {
19
+ instantLoopEnabled: true,
20
+ backgroundLoopEnabled: true,
21
+ loraLearningRate: 0.001,
22
+ loraRank: 8,
23
+ ewcLambda: 2000,
24
+ maxTrajectorySize: 1000,
25
+ patternThreshold: 0.85,
26
+ };
27
+ exports.DEFAULT_SONA_CONFIG = DEFAULT_SONA_CONFIG;
28
+ /**
29
+ * Trajectory Builder for tracking query execution paths
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const builder = new TrajectoryBuilder();
34
+ *
35
+ * builder.startStep('query', 'What is AI?');
36
+ * // ... processing ...
37
+ * builder.endStep('AI is artificial intelligence', 0.95);
38
+ *
39
+ * builder.startStep('memory', 'searching context');
40
+ * builder.endStep('found 3 relevant documents', 0.88);
41
+ *
42
+ * const trajectory = builder.complete('success');
43
+ * ```
44
+ */
45
+ class TrajectoryBuilder {
46
+ constructor() {
47
+ this.steps = [];
48
+ this.currentStep = null;
49
+ this.stepStart = 0;
50
+ this.id = `traj-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
51
+ this.startTime = Date.now();
52
+ }
53
+ /**
54
+ * Start a new step in the trajectory
55
+ */
56
+ startStep(type, input) {
57
+ if (this.currentStep) {
58
+ // Auto-complete previous step
59
+ this.endStep('', 0);
60
+ }
61
+ this.stepStart = Date.now();
62
+ this.currentStep = {
63
+ type,
64
+ input,
65
+ };
66
+ return this;
67
+ }
68
+ /**
69
+ * End current step with output
70
+ */
71
+ endStep(output, confidence) {
72
+ if (!this.currentStep) {
73
+ return this;
74
+ }
75
+ this.steps.push({
76
+ type: this.currentStep.type,
77
+ input: this.currentStep.input,
78
+ output,
79
+ durationMs: Date.now() - this.stepStart,
80
+ confidence,
81
+ });
82
+ this.currentStep = null;
83
+ return this;
84
+ }
85
+ /**
86
+ * Complete trajectory with final outcome
87
+ */
88
+ complete(outcome) {
89
+ // Complete any pending step
90
+ if (this.currentStep) {
91
+ this.endStep('incomplete', 0);
92
+ }
93
+ return {
94
+ id: this.id,
95
+ steps: this.steps,
96
+ outcome,
97
+ durationMs: Date.now() - this.startTime,
98
+ };
99
+ }
100
+ /**
101
+ * Get current trajectory ID
102
+ */
103
+ getId() {
104
+ return this.id;
105
+ }
106
+ }
107
+ exports.TrajectoryBuilder = TrajectoryBuilder;
108
+ /**
109
+ * ReasoningBank - Pattern storage and retrieval
110
+ *
111
+ * Stores learned patterns from successful interactions and
112
+ * enables pattern-based reasoning shortcuts.
113
+ *
114
+ * OPTIMIZED: Uses Float64Array for embeddings and partial sorting
115
+ */
116
+ class ReasoningBank {
117
+ constructor(threshold = 0.85) {
118
+ this.patterns = new Map();
119
+ this.embeddings = new Map();
120
+ this.embeddingNorms = new Map(); // Pre-computed norms
121
+ // Reusable arrays for findSimilar to avoid allocations
122
+ this._similarityResults = [];
123
+ this.threshold = threshold;
124
+ }
125
+ /**
126
+ * Store a new pattern
127
+ */
128
+ store(type, embedding, metadata) {
129
+ const id = `pat-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
130
+ const pattern = {
131
+ id,
132
+ type,
133
+ embedding,
134
+ successRate: 1.0,
135
+ useCount: 0,
136
+ lastUsed: new Date(),
137
+ };
138
+ this.patterns.set(id, pattern);
139
+ // Store as typed array for faster similarity computation
140
+ const typedEmb = new Float64Array(embedding);
141
+ this.embeddings.set(id, typedEmb);
142
+ // Pre-compute and cache the norm
143
+ let norm = 0;
144
+ for (let i = 0; i < typedEmb.length; i++) {
145
+ norm += typedEmb[i] * typedEmb[i];
146
+ }
147
+ this.embeddingNorms.set(id, Math.sqrt(norm));
148
+ return id;
149
+ }
150
+ /**
151
+ * Find similar patterns
152
+ * OPTIMIZED: Uses typed arrays, pre-computed norms, and partial sorting
153
+ */
154
+ findSimilar(embedding, k = 5) {
155
+ // Pre-compute query norm
156
+ let queryNorm = 0;
157
+ const queryLen = embedding.length;
158
+ for (let i = 0; i < queryLen; i++) {
159
+ queryNorm += embedding[i] * embedding[i];
160
+ }
161
+ queryNorm = Math.sqrt(queryNorm);
162
+ if (queryNorm === 0)
163
+ return [];
164
+ // Reuse array to avoid allocations
165
+ this._similarityResults.length = 0;
166
+ for (const [id, patEmb] of this.embeddings) {
167
+ const patNorm = this.embeddingNorms.get(id) || 0;
168
+ if (patNorm === 0)
169
+ continue;
170
+ // Fast dot product
171
+ let dot = 0;
172
+ const minLen = Math.min(queryLen, patEmb.length);
173
+ // Unrolled loop
174
+ let i = 0;
175
+ for (; i + 3 < minLen; i += 4) {
176
+ dot += embedding[i] * patEmb[i] +
177
+ embedding[i + 1] * patEmb[i + 1] +
178
+ embedding[i + 2] * patEmb[i + 2] +
179
+ embedding[i + 3] * patEmb[i + 3];
180
+ }
181
+ for (; i < minLen; i++) {
182
+ dot += embedding[i] * patEmb[i];
183
+ }
184
+ const score = dot / (queryNorm * patNorm);
185
+ if (score >= this.threshold) {
186
+ this._similarityResults.push({ id, score });
187
+ }
188
+ }
189
+ // Partial sort for top-k (faster than full sort for large arrays)
190
+ if (this._similarityResults.length <= k) {
191
+ this._similarityResults.sort((a, b) => b.score - a.score);
192
+ }
193
+ else {
194
+ // Quick partial sort for top k
195
+ this.partialSort(this._similarityResults, k);
196
+ }
197
+ const topK = this._similarityResults.slice(0, k);
198
+ return topK
199
+ .map(s => this.patterns.get(s.id))
200
+ .filter((p) => p !== undefined);
201
+ }
202
+ /**
203
+ * Partial sort to get top k elements (faster than full sort)
204
+ */
205
+ partialSort(arr, k) {
206
+ // Simple selection for small k
207
+ for (let i = 0; i < k && i < arr.length; i++) {
208
+ let maxIdx = i;
209
+ for (let j = i + 1; j < arr.length; j++) {
210
+ if (arr[j].score > arr[maxIdx].score) {
211
+ maxIdx = j;
212
+ }
213
+ }
214
+ if (maxIdx !== i) {
215
+ const temp = arr[i];
216
+ arr[i] = arr[maxIdx];
217
+ arr[maxIdx] = temp;
218
+ }
219
+ }
220
+ }
221
+ /**
222
+ * Record pattern usage (success or failure)
223
+ */
224
+ recordUsage(patternId, success) {
225
+ const pattern = this.patterns.get(patternId);
226
+ if (!pattern)
227
+ return;
228
+ pattern.useCount++;
229
+ pattern.lastUsed = new Date();
230
+ // Update success rate with exponential moving average
231
+ const alpha = 0.1;
232
+ const outcome = success ? 1.0 : 0.0;
233
+ pattern.successRate = alpha * outcome + (1 - alpha) * pattern.successRate;
234
+ }
235
+ /**
236
+ * Get pattern by ID
237
+ */
238
+ get(patternId) {
239
+ return this.patterns.get(patternId);
240
+ }
241
+ /**
242
+ * Get all patterns of a type
243
+ */
244
+ getByType(type) {
245
+ return Array.from(this.patterns.values()).filter(p => p.type === type);
246
+ }
247
+ /**
248
+ * Prune low-performing patterns
249
+ */
250
+ prune(minSuccessRate = 0.3, minUseCount = 5) {
251
+ let pruned = 0;
252
+ for (const [id, pattern] of this.patterns) {
253
+ if (pattern.useCount >= minUseCount && pattern.successRate < minSuccessRate) {
254
+ this.patterns.delete(id);
255
+ this.embeddings.delete(id);
256
+ this.embeddingNorms.delete(id);
257
+ pruned++;
258
+ }
259
+ }
260
+ return pruned;
261
+ }
262
+ /**
263
+ * Get statistics
264
+ */
265
+ stats() {
266
+ const patterns = Array.from(this.patterns.values());
267
+ const byType = {};
268
+ let totalSuccess = 0;
269
+ for (const p of patterns) {
270
+ totalSuccess += p.successRate;
271
+ byType[p.type] = (byType[p.type] || 0) + 1;
272
+ }
273
+ return {
274
+ totalPatterns: patterns.length,
275
+ avgSuccessRate: patterns.length > 0 ? totalSuccess / patterns.length : 0,
276
+ byType,
277
+ };
278
+ }
279
+ cosineSimilarity(a, b) {
280
+ let dot = 0, normA = 0, normB = 0;
281
+ const len = Math.min(a.length, b.length);
282
+ for (let i = 0; i < len; i++) {
283
+ dot += a[i] * b[i];
284
+ normA += a[i] * a[i];
285
+ normB += b[i] * b[i];
286
+ }
287
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
288
+ return denom > 0 ? dot / denom : 0;
289
+ }
290
+ }
291
+ exports.ReasoningBank = ReasoningBank;
292
+ /**
293
+ * EWC++ (Elastic Weight Consolidation) Manager
294
+ *
295
+ * Prevents catastrophic forgetting by protecting important weights.
296
+ * This is a simplified JS implementation of the concept.
297
+ *
298
+ * OPTIMIZED: Uses Float64Array for 5-10x faster penalty computation
299
+ */
300
+ class EwcManager {
301
+ constructor(lambda = 2000) {
302
+ this.tasksLearned = 0;
303
+ this.fisherDiagonal = new Map();
304
+ this.optimalWeights = new Map();
305
+ // Pre-allocated buffer for penalty computation
306
+ this._penaltyBuffer = null;
307
+ this.lambda = lambda;
308
+ }
309
+ /**
310
+ * Register a new task (after successful learning)
311
+ */
312
+ registerTask(taskId, weights) {
313
+ // Store optimal weights for this task using typed arrays
314
+ const optimalArr = new Float64Array(weights.length);
315
+ const fisherArr = new Float64Array(weights.length);
316
+ for (let i = 0; i < weights.length; i++) {
317
+ optimalArr[i] = weights[i];
318
+ fisherArr[i] = Math.abs(weights[i]) * this.lambda;
319
+ }
320
+ this.optimalWeights.set(taskId, optimalArr);
321
+ this.fisherDiagonal.set(taskId, fisherArr);
322
+ this.tasksLearned++;
323
+ }
324
+ /**
325
+ * Compute EWC penalty for weight update
326
+ * OPTIMIZED: Uses typed arrays and minimizes allocations
327
+ */
328
+ computePenalty(currentWeights) {
329
+ let penalty = 0;
330
+ const len = currentWeights.length;
331
+ for (const [taskId, optimal] of this.optimalWeights) {
332
+ const fisher = this.fisherDiagonal.get(taskId);
333
+ if (!fisher)
334
+ continue;
335
+ const minLen = Math.min(len, optimal.length);
336
+ // Unrolled loop for better performance
337
+ let i = 0;
338
+ for (; i + 3 < minLen; i += 4) {
339
+ const diff0 = currentWeights[i] - optimal[i];
340
+ const diff1 = currentWeights[i + 1] - optimal[i + 1];
341
+ const diff2 = currentWeights[i + 2] - optimal[i + 2];
342
+ const diff3 = currentWeights[i + 3] - optimal[i + 3];
343
+ penalty += fisher[i] * diff0 * diff0 +
344
+ fisher[i + 1] * diff1 * diff1 +
345
+ fisher[i + 2] * diff2 * diff2 +
346
+ fisher[i + 3] * diff3 * diff3;
347
+ }
348
+ // Handle remaining elements
349
+ for (; i < minLen; i++) {
350
+ const diff = currentWeights[i] - optimal[i];
351
+ penalty += fisher[i] * diff * diff;
352
+ }
353
+ }
354
+ return penalty * 0.5;
355
+ }
356
+ /**
357
+ * Get EWC statistics
358
+ */
359
+ stats() {
360
+ return {
361
+ tasksLearned: this.tasksLearned,
362
+ fisherComputed: this.fisherDiagonal.size > 0,
363
+ protectionStrength: this.lambda,
364
+ forgettingRate: this.estimateForgettingRate(),
365
+ };
366
+ }
367
+ estimateForgettingRate() {
368
+ // Simplified estimation based on number of tasks
369
+ return Math.max(0, 1 - Math.exp(-this.tasksLearned * 0.1));
370
+ }
371
+ }
372
+ exports.EwcManager = EwcManager;
373
+ /**
374
+ * SONA Learning Coordinator
375
+ *
376
+ * Orchestrates the learning loops and components.
377
+ */
378
+ class SonaCoordinator {
379
+ constructor(config) {
380
+ this.trajectoryBuffer = [];
381
+ this.signalBuffer = [];
382
+ this.microLoraUpdates = 0;
383
+ this.config = { ...DEFAULT_SONA_CONFIG, ...config };
384
+ this.reasoningBank = new ReasoningBank(this.config.patternThreshold);
385
+ this.ewcManager = new EwcManager(this.config.ewcLambda);
386
+ this.microLora = new lora_1.LoraAdapter({ rank: MICRO_LORA_RANK }, MICRO_LORA_DIM, MICRO_LORA_DIM);
387
+ }
388
+ /**
389
+ * Record a learning signal
390
+ *
391
+ * Every signal drives the instant loop: quality above 0.5 reinforces the
392
+ * signal's direction in the micro-LoRA, quality below 0.5 unlearns it
393
+ * (previously only quality >= 0.8 was processed, so negative feedback
394
+ * never adapted anything).
395
+ */
396
+ recordSignal(signal) {
397
+ this.signalBuffer.push(signal);
398
+ // Instant loop - immediate learning
399
+ if (this.config.instantLoopEnabled) {
400
+ this.processInstantLearning(signal);
401
+ }
402
+ }
403
+ /**
404
+ * Record a completed trajectory
405
+ */
406
+ recordTrajectory(trajectory) {
407
+ this.trajectoryBuffer.push(trajectory);
408
+ // Maintain buffer size
409
+ while (this.trajectoryBuffer.length > this.config.maxTrajectorySize) {
410
+ this.trajectoryBuffer.shift();
411
+ }
412
+ // Extract patterns from successful trajectories
413
+ if (trajectory.outcome === 'success') {
414
+ this.extractPatterns(trajectory);
415
+ }
416
+ }
417
+ /**
418
+ * Run background learning loop
419
+ */
420
+ runBackgroundLoop() {
421
+ if (!this.config.backgroundLoopEnabled) {
422
+ return { patternsLearned: 0, trajectoriesProcessed: 0 };
423
+ }
424
+ let patternsLearned = 0;
425
+ const trajectoriesProcessed = this.trajectoryBuffer.length;
426
+ // Process accumulated trajectories
427
+ for (const traj of this.trajectoryBuffer) {
428
+ if (traj.outcome === 'success' || traj.outcome === 'partial') {
429
+ patternsLearned += this.extractPatterns(traj);
430
+ }
431
+ }
432
+ // Prune low-performing patterns
433
+ this.reasoningBank.prune();
434
+ // Clear processed trajectories
435
+ this.trajectoryBuffer = [];
436
+ return { patternsLearned, trajectoriesProcessed };
437
+ }
438
+ /**
439
+ * Get reasoning bank for pattern queries
440
+ */
441
+ getReasoningBank() {
442
+ return this.reasoningBank;
443
+ }
444
+ /**
445
+ * Get EWC manager
446
+ */
447
+ getEwcManager() {
448
+ return this.ewcManager;
449
+ }
450
+ /**
451
+ * Get statistics
452
+ */
453
+ stats() {
454
+ return {
455
+ signalsReceived: this.signalBuffer.length,
456
+ trajectoriesBuffered: this.trajectoryBuffer.length,
457
+ patterns: this.reasoningBank.stats(),
458
+ ewc: this.ewcManager.stats(),
459
+ microLora: {
460
+ updates: this.microLoraUpdates,
461
+ deltaNorm: this.microLoraDeltaNorm(),
462
+ },
463
+ };
464
+ }
465
+ /**
466
+ * Apply the micro-LoRA transformation learned from feedback.
467
+ *
468
+ * Input is truncated/zero-padded to the adapter dimension; the residual
469
+ * connection means an untrained adapter returns the input unchanged.
470
+ */
471
+ applyMicroLora(input) {
472
+ return this.microLora.forward(input.slice(0, MICRO_LORA_DIM));
473
+ }
474
+ /**
475
+ * Frobenius norm of the micro-LoRA weight delta (scaling * A @ B).
476
+ *
477
+ * 0 means no adaptation has occurred (LoRA B is zero-initialized, so the
478
+ * delta is exactly zero until the first feedback update). Consumers can
479
+ * surface this directly (e.g. a statusline "delta LoRA" field) — see #553.
480
+ */
481
+ microLoraDeltaNorm() {
482
+ const { loraA, loraB, scaling } = this.microLora.getWeights();
483
+ const rank = loraB.length;
484
+ let sumSq = 0;
485
+ for (let i = 0; i < loraA.length; i++) {
486
+ for (let j = 0; j < MICRO_LORA_DIM; j++) {
487
+ let d = 0;
488
+ for (let r = 0; r < rank; r++) {
489
+ d += loraA[i][r] * loraB[r][j];
490
+ }
491
+ sumSq += scaling * d * (scaling * d);
492
+ }
493
+ }
494
+ return Math.sqrt(sumSq);
495
+ }
496
+ /**
497
+ * Instant-loop learning: a single feedback signal produces a real
498
+ * micro-LoRA weight update (fixes #553 — this was a no-op stub, so
499
+ * learn-from-feedback never changed any weight).
500
+ *
501
+ * REINFORCE-style with a fixed 0.5 baseline: reward = quality - 0.5.
502
+ * The gradient pushes the adapter output toward the signal's embedding
503
+ * direction for positive reward and away from it for negative reward
504
+ * (backward() applies `weights -= lr * grad`, hence the negated sign).
505
+ */
506
+ processInstantLearning(signal) {
507
+ const reward = signal.quality - 0.5;
508
+ if (reward === 0)
509
+ return;
510
+ const input = this.createEmbedding(signal.correction ?? `${signal.requestId}:${signal.type}`);
511
+ const gradOutput = input.map(x => -reward * x);
512
+ this.microLora.backward(input, gradOutput, this.config.loraLearningRate);
513
+ this.microLoraUpdates++;
514
+ }
515
+ extractPatterns(trajectory) {
516
+ let extracted = 0;
517
+ for (const step of trajectory.steps) {
518
+ if (step.confidence >= this.config.patternThreshold) {
519
+ // Create embedding from step (simplified)
520
+ const embedding = this.createEmbedding(step.input + step.output);
521
+ // Determine pattern type
522
+ const type = this.stepTypeToPatternType(step.type);
523
+ // Store if not too similar to existing
524
+ const similar = this.reasoningBank.findSimilar(embedding, 1);
525
+ if (similar.length === 0) {
526
+ this.reasoningBank.store(type, embedding);
527
+ extracted++;
528
+ }
529
+ }
530
+ }
531
+ return extracted;
532
+ }
533
+ stepTypeToPatternType(stepType) {
534
+ switch (stepType) {
535
+ case 'query':
536
+ case 'generate':
537
+ return 'query_response';
538
+ case 'route':
539
+ return 'routing';
540
+ case 'memory':
541
+ return 'context_retrieval';
542
+ case 'feedback':
543
+ return 'correction';
544
+ default:
545
+ return 'query_response';
546
+ }
547
+ }
548
+ createEmbedding(text) {
549
+ // Simplified hash-based embedding (real impl uses model)
550
+ const dim = 64;
551
+ const embedding = new Array(dim).fill(0);
552
+ for (let i = 0; i < text.length; i++) {
553
+ const idx = (text.charCodeAt(i) * (i + 1)) % dim;
554
+ embedding[idx] += 0.1;
555
+ }
556
+ // Normalize
557
+ const norm = Math.sqrt(embedding.reduce((s, x) => s + x * x, 0)) || 1;
558
+ return embedding.map(x => x / norm);
559
+ }
560
+ }
561
+ exports.SonaCoordinator = SonaCoordinator;
562
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29uYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zb25hLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7R0FLRzs7O0FBY0gsaUNBQXFDO0FBRXJDLGtGQUFrRjtBQUNsRixNQUFNLGNBQWMsR0FBRyxFQUFFLENBQUM7QUFDMUIscUZBQXFGO0FBQ3JGLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQztBQUUxQjs7R0FFRztBQUNILE1BQU0sbUJBQW1CLEdBQXlCO0lBQ2hELGtCQUFrQixFQUFFLElBQUk7SUFDeEIscUJBQXFCLEVBQUUsSUFBSTtJQUMzQixnQkFBZ0IsRUFBRSxLQUFLO0lBQ3ZCLFFBQVEsRUFBRSxDQUFDO0lBQ1gsU0FBUyxFQUFFLElBQUk7SUFDZixpQkFBaUIsRUFBRSxJQUFJO0lBQ3ZCLGdCQUFnQixFQUFFLElBQUk7Q0FDdkIsQ0FBQztBQThuQkEsa0RBQW1CO0FBNW5CckI7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFhLGlCQUFpQjtJQU81QjtRQUxRLFVBQUssR0FBcUIsRUFBRSxDQUFDO1FBQzdCLGdCQUFXLEdBQW1DLElBQUksQ0FBQztRQUNuRCxjQUFTLEdBQVcsQ0FBQyxDQUFDO1FBSTVCLElBQUksQ0FBQyxFQUFFLEdBQUcsUUFBUSxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDekUsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxDQUFDLElBQTRCLEVBQUUsS0FBYTtRQUNuRCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNyQiw4QkFBOEI7WUFDOUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUs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QUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0RSxPQUFPLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDdEMsQ0FBQztDQUNGO0FBak9ELDBDQWlPQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogU09OQSAoU2VsZi1PcHRpbWl6aW5nIE5ldXJhbCBBcmNoaXRlY3R1cmUpIExlYXJuaW5nIFN5c3RlbVxuICpcbiAqIFByb3ZpZGVzIGFkYXB0aXZlIGxlYXJuaW5nIGNhcGFiaWxpdGllcyB3aXRoIHRyYWplY3RvcnkgdHJhY2tpbmcsXG4gKiBwYXR0ZXJuIHJlY29nbml0aW9uLCBhbmQgbWVtb3J5IHByb3RlY3Rpb24gKEVXQysrKS5cbiAqL1xuXG5pbXBvcnQge1xuICBTb25hQ29uZmlnLFxuICBMZWFybmluZ1NpZ25hbCxcbiAgUXVlcnlUcmFqZWN0b3J5LFxuICBUcmFqZWN0b3J5U3RlcCxcbiAgVHJhamVjdG9yeU91dGNvbWUsXG4gIExlYXJuZWRQYXR0ZXJuLFxuICBQYXR0ZXJuVHlwZSxcbiAgRXdjU3RhdHMsXG4gIExvUkFDb25maWcsXG4gIEVtYmVkZGluZyxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBMb3JhQWRhcHRlciB9IGZyb20gJy4vbG9yYSc7XG5cbi8qKiBFbWJlZGRpbmcgZGltZW5zaW9uIHVzZWQgYnkgdGhlIGNvb3JkaW5hdG9yJ3MgaGFzaCBlbWJlZGRlciBhbmQgbWljcm8tTG9SQS4gKi9cbmNvbnN0IE1JQ1JPX0xPUkFfRElNID0gNjQ7XG4vKiogTWljcm8tTG9SQSByYW5rOiBTT05BJ3MgaW5zdGFudCBsb29wIHVzZXMgYSB0aW55IGFkYXB0ZXIgKHJhbmsgMS0yKSBieSBkZXNpZ24uICovXG5jb25zdCBNSUNST19MT1JBX1JBTksgPSAyO1xuXG4vKipcbiAqIERlZmF1bHQgU09OQSBjb25maWd1cmF0aW9uXG4gKi9cbmNvbnN0IERFRkFVTFRfU09OQV9DT05GSUc6IFJlcXVpcmVkPFNvbmFDb25maWc+ID0ge1xuICBpbnN0YW50TG9vcEVuYWJsZWQ6IHRydWUsXG4gIGJhY2tncm91bmRMb29wRW5hYmxlZDogdHJ1ZSxcbiAgbG9yYUxlYXJuaW5nUmF0ZTogMC4wMDEsXG4gIGxvcmFSYW5rOiA4LFxuICBld2NMYW1iZGE6IDIwMDAsXG4gIG1heFRyYWplY3RvcnlTaXplOiAxMDAwLFxuICBwYXR0ZXJuVGhyZXNob2xkOiAwLjg1LFxufTtcblxuLyoqXG4gKiBUcmFqZWN0b3J5IEJ1aWxkZXIgZm9yIHRyYWNraW5nIHF1ZXJ5IGV4ZWN1dGlvbiBwYXRoc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBidWlsZGVyID0gbmV3IFRyYWplY3RvcnlCdWlsZGVyKCk7XG4gKlxuICogYnVpbGRlci5zdGFydFN0ZXAoJ3F1ZXJ5JywgJ1doYXQgaXMgQUk/Jyk7XG4gKiAvLyAuLi4gcHJvY2Vzc2luZyAuLi5cbiAqIGJ1aWxkZXIuZW5kU3RlcCgnQUkgaXMgYXJ0aWZpY2lhbCBpbnRlbGxpZ2VuY2UnLCAwLjk1KTtcbiAqXG4gKiBidWlsZGVyLnN0YXJ0U3RlcCgnbWVtb3J5JywgJ3NlYXJjaGluZyBjb250ZXh0Jyk7XG4gKiBidWlsZGVyLmVuZFN0ZXAoJ2ZvdW5kIDMgcmVsZXZhbnQgZG9jdW1lbnRzJywgMC44OCk7XG4gKlxuICogY29uc3QgdHJhamVjdG9yeSA9IGJ1aWxkZXIuY29tcGxldGUoJ3N1Y2Nlc3MnKTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgVHJhamVjdG9yeUJ1aWxkZXIge1xuICBwcml2YXRlIGlkOiBzdHJpbmc7XG4gIHByaXZhdGUgc3RlcHM6IFRyYWplY3RvcnlTdGVwW10gPSBbXTtcbiAgcHJpdmF0ZSBjdXJyZW50U3RlcDogUGFydGlhbDxUcmFqZWN0b3J5U3RlcD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzdGVwU3RhcnQ6IG51bWJlciA9IDA7XG4gIHByaXZhdGUgc3RhcnRUaW1lOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5pZCA9IGB0cmFqLSR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyLCA4KX1gO1xuICAgIHRoaXMuc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydCBhIG5ldyBzdGVwIGluIHRoZSB0cmFqZWN0b3J5XG4gICAqL1xuICBzdGFydFN0ZXAodHlwZTogVHJhamVjdG9yeVN0ZXBbJ3R5cGUnXSwgaW5wdXQ6IHN0cmluZyk6IHRoaXMge1xuICAgIGlmICh0aGlzLmN1cnJlbnRTdGVwKSB7XG4gICAgICAvLyBBdXRvLWNvbXBsZXRlIHByZXZpb3VzIHN0ZXBcbiAgICAgIHRoaXMuZW5kU3RlcCgnJywgMCk7XG4gICAgfVxuXG4gICAgdGhpcy5zdGVwU3RhcnQgPSBEYXRlLm5vdygpO1xuICAgIHRoaXMuY3VycmVudFN0ZXAgPSB7XG4gICAgICB0eXBlLFxuICAgICAgaW5wdXQsXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuZCBjdXJyZW50IHN0ZXAgd2l0aCBvdXRwdXRcbiAgICovXG4gIGVuZFN0ZXAob3V0cHV0OiBzdHJpbmcsIGNvbmZpZGVuY2U6IG51bWJlcik6IHRoaXMge1xuICAgIGlmICghdGhpcy5jdXJyZW50U3RlcCkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdGhpcy5zdGVwcy5wdXNoKHtcbiAgICAgIHR5cGU6IHRoaXMuY3VycmVudFN0ZXAudHlwZSEsXG4gICAgICBpbnB1dDogdGhpcy5jdXJyZW50U3RlcC5pbnB1dCEsXG4gICAgICBvdXRwdXQsXG4gICAgICBkdXJhdGlvbk1zOiBEYXRlLm5vdygpIC0gdGhpcy5zdGVwU3RhcnQsXG4gICAgICBjb25maWRlbmNlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5jdXJyZW50U3RlcCA9IG51bGw7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ29tcGxldGUgdHJhamVjdG9yeSB3aXRoIGZpbmFsIG91dGNvbWVcbiAgICovXG4gIGNvbXBsZXRlKG91dGNvbWU6IFRyYWplY3RvcnlPdXRjb21lKTogUXVlcnlUcmFqZWN0b3J5IHtcbiAgICAvLyBDb21wbGV0ZSBhbnkgcGVuZGluZyBzdGVwXG4gICAgaWYgKHRoaXMuY3VycmVudFN0ZXApIHtcbiAgICAgIHRoaXMuZW5kU3RlcCgnaW5jb21wbGV0ZScsIDApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpZDogdGhpcy5pZCxcbiAgICAgIHN0ZXBzOiB0aGlzLnN0ZXBzLFxuICAgICAgb3V0Y29tZSxcbiAgICAgIGR1cmF0aW9uTXM6IERhdGUubm93KCkgLSB0aGlzLnN0YXJ0VGltZSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IHRyYWplY3RvcnkgSURcbiAgICovXG4gIGdldElkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuaWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBSZWFzb25pbmdCYW5rIC0gUGF0dGVybiBzdG9yYWdlIGFuZCByZXRyaWV2YWxcbiAqXG4gKiBTdG9yZXMgbGVhcm5lZCBwYXR0ZXJucyBmcm9tIHN1Y2Nlc3NmdWwgaW50ZXJhY3Rpb25zIGFuZFxuICogZW5hYmxlcyBwYXR0ZXJuLWJhc2VkIHJlYXNvbmluZyBzaG9ydGN1dHMuXG4gKlxuICogT1BUSU1JWkVEOiBVc2VzIEZsb2F0NjRBcnJheSBmb3IgZW1iZWRkaW5ncyBhbmQgcGFydGlhbCBzb3J0aW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWFzb25pbmdCYW5rIHtcbiAgcHJpdmF0ZSBwYXR0ZXJuczogTWFwPHN0cmluZywgTGVhcm5lZFBhdHRlcm4+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIGVtYmVkZGluZ3M6IE1hcDxzdHJpbmcsIEZsb2F0NjRBcnJheT4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgZW1iZWRkaW5nTm9ybXM6IE1hcDxzdHJpbmcsIG51bWJlcj4gPSBuZXcgTWFwKCk7IC8vIFByZS1jb21wdXRlZCBub3Jtc1xuICBwcml2YXRlIHRocmVzaG9sZDogbnVtYmVyO1xuICAvLyBSZXVzYWJsZSBhcnJheXMgZm9yIGZpbmRTaW1pbGFyIHRvIGF2b2lkIGFsbG9jYXRpb25zXG4gIHByaXZhdGUgX3NpbWlsYXJpdHlSZXN1bHRzOiBBcnJheTx7IGlkOiBzdHJpbmc7IHNjb3JlOiBudW1iZXIgfT4gPSBbXTtcblxuICBjb25zdHJ1Y3Rvcih0aHJlc2hvbGQgPSAwLjg1KSB7XG4gICAgdGhpcy50aHJlc2hvbGQgPSB0aHJlc2hvbGQ7XG4gIH1cblxuICAvKipcbiAgICogU3RvcmUgYSBuZXcgcGF0dGVyblxuICAgKi9cbiAgc3RvcmUoXG4gICAgdHlwZTogUGF0dGVyblR5cGUsXG4gICAgZW1iZWRkaW5nOiBFbWJlZGRpbmcsXG4gICAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IGlkID0gYHBhdC0ke0RhdGUubm93KCl9LSR7TWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc2xpY2UoMiwgOCl9YDtcblxuICAgIGNvbnN0IHBhdHRlcm46IExlYXJuZWRQYXR0ZXJuID0ge1xuICAgICAgaWQsXG4gICAgICB0eXBlLFxuICAgICAgZW1iZWRkaW5nLFxuICAgICAgc3VjY2Vzc1JhdGU6IDEuMCxcbiAgICAgIHVzZUNvdW50OiAwLFxuICAgICAgbGFzdFVzZWQ6IG5ldyBEYXRlKCksXG4gICAgfTtcblxuICAgIHRoaXMucGF0dGVybnMuc2V0KGlkLCBwYXR0ZXJuKTtcblxuICAgIC8vIFN0b3JlIGFzIHR5cGVkIGFycmF5IGZvciBmYXN0ZXIgc2ltaWxhcml0eSBjb21wdXRhdGlvblxuICAgIGNvbnN0IHR5cGVkRW1iID0gbmV3IEZsb2F0NjRBcnJheShlbWJlZGRpbmcpO1xuICAgIHRoaXMuZW1iZWRkaW5ncy5zZXQoaWQsIHR5cGVkRW1iKTtcblxuICAgIC8vIFByZS1jb21wdXRlIGFuZCBjYWNoZSB0aGUgbm9ybVxuICAgIGxldCBub3JtID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHR5cGVkRW1iLmxlbmd0aDsgaSsrKSB7XG4gICAgICBub3JtICs9IHR5cGVkRW1iW2ldICogdHlwZWRFbWJbaV07XG4gICAgfVxuICAgIHRoaXMuZW1iZWRkaW5nTm9ybXMuc2V0KGlkLCBNYXRoLnNxcnQobm9ybSkpO1xuXG4gICAgcmV0dXJuIGlkO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmQgc2ltaWxhciBwYXR0ZXJuc1xuICAgKiBPUFRJTUlaRUQ6IFVzZXMgdHlwZWQgYXJyYXlzLCBwcmUtY29tcHV0ZWQgbm9ybXMsIGFuZCBwYXJ0aWFsIHNvcnRpbmdcbiAgICovXG4gIGZpbmRTaW1pbGFyKGVtYmVkZGluZzogRW1iZWRkaW5nLCBrID0gNSk6IExlYXJuZWRQYXR0ZXJuW10ge1xuICAgIC8vIFByZS1jb21wdXRlIHF1ZXJ5IG5vcm1cbiAgICBsZXQgcXVlcnlOb3JtID0gMDtcbiAgICBjb25zdCBxdWVyeUxlbiA9IGVtYmVkZGluZy5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBxdWVyeUxlbjsgaSsrKSB7XG4gICAgICBxdWVyeU5vcm0gKz0gZW1iZWRkaW5nW2ldICogZW1iZWRkaW5nW2ldO1xuICAgIH1cbiAgICBxdWVyeU5vcm0gPSBNYXRoLnNxcnQocXVlcnlOb3JtKTtcblxuICAgIGlmIChxdWVyeU5vcm0gPT09IDApIHJldHVybiBbXTtcblxuICAgIC8vIFJldXNlIGFycmF5IHRvIGF2b2lkIGFsbG9jYXRpb25zXG4gICAgdGhpcy5fc2ltaWxhcml0eVJlc3VsdHMubGVuZ3RoID0gMDtcblxuICAgIGZvciAoY29uc3QgW2lkLCBwYXRFbWJdIG9mIHRoaXMuZW1iZWRkaW5ncykge1xuICAgICAgY29uc3QgcGF0Tm9ybSA9IHRoaXMuZW1iZWRkaW5nTm9ybXMuZ2V0KGlkKSB8fCAwO1xuICAgICAgaWYgKHBhdE5vcm0gPT09IDApIGNvbnRpbnVlO1xuXG4gICAgICAvLyBGYXN0IGRvdCBwcm9kdWN0XG4gICAgICBsZXQgZG90ID0gMDtcbiAgICAgIGNvbnN0IG1pbkxlbiA9IE1hdGgubWluKHF1ZXJ5TGVuLCBwYXRFbWIubGVuZ3RoKTtcblxuICAgICAgLy8gVW5yb2xsZWQgbG9vcFxuICAgICAgbGV0IGkgPSAwO1xuICAgICAgZm9yICg7IGkgKyAzIDwgbWluTGVuOyBpICs9IDQpIHtcbiAgICAgICAgZG90ICs9IGVtYmVkZGluZ1tpXSAqIHBhdEVtYltpXSArXG4gICAgICAgICAgICAgICBlbWJlZGRpbmdbaSArIDFdICogcGF0RW1iW2kgKyAxXSArXG4gICAgICAgICAgICAgICBlbWJlZGRpbmdbaSArIDJdICogcGF0RW1iW2kgKyAyXSArXG4gICAgICAgICAgICAgICBlbWJlZGRpbmdbaSArIDNdICogcGF0RW1iW2kgKyAzXTtcbiAgICAgIH1cbiAgICAgIGZvciAoOyBpIDwgbWluTGVuOyBpKyspIHtcbiAgICAgICAgZG90ICs9IGVtYmVkZGluZ1tpXSAqIHBhdEVtYltpXTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2NvcmUgPSBkb3QgLyAocXVlcnlOb3JtICogcGF0Tm9ybSk7XG5cbiAgICAgIGlmIChzY29yZSA+PSB0aGlzLnRocmVzaG9sZCkge1xuICAgICAgICB0aGlzLl9zaW1pbGFyaXR5UmVzdWx0cy5wdXNoKHsgaWQsIHNjb3JlIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFBhcnRpYWwgc29ydCBmb3IgdG9wLWsgKGZhc3RlciB0aGFuIGZ1bGwgc29ydCBmb3IgbGFyZ2UgYXJyYXlzKVxuICAgIGlmICh0aGlzLl9zaW1pbGFyaXR5UmVzdWx0cy5sZW5ndGggPD0gaykge1xuICAgICAgdGhpcy5fc2ltaWxhcml0eVJlc3VsdHMuc29ydCgoYSwgYikgPT4gYi5zY29yZSAtIGEuc2NvcmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBRdWljayBwYXJ0aWFsIHNvcnQgZm9yIHRvcCBrXG4gICAgICB0aGlzLnBhcnRpYWxTb3J0KHRoaXMuX3NpbWlsYXJpdHlSZXN1bHRzLCBrKTtcbiAgICB9XG5cbiAgICBjb25zdCB0b3BLID0gdGhpcy5fc2ltaWxhcml0eVJlc3VsdHMuc2xpY2UoMCwgayk7XG5cbiAgICByZXR1cm4gdG9wS1xuICAgICAgLm1hcChzID0+IHRoaXMucGF0dGVybnMuZ2V0KHMuaWQpKVxuICAgICAgLmZpbHRlcigocCk6IHAgaXMgTGVhcm5lZFBhdHRlcm4gPT4gcCAhPT0gdW5kZWZpbmVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJ0aWFsIHNvcnQgdG8gZ2V0IHRvcCBrIGVsZW1lbnRzIChmYXN0ZXIgdGhhbiBmdWxsIHNvcnQpXG4gICAqL1xuICBwcml2YXRlIHBhcnRpYWxTb3J0KGFycjogQXJyYXk8eyBpZDogc3RyaW5nOyBzY29yZTogbnVtYmVyIH0+LCBrOiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBTaW1wbGUgc2VsZWN0aW9uIGZvciBzbWFsbCBrXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBrICYmIGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBtYXhJZHggPSBpO1xuICAgICAgZm9yIChsZXQgaiA9IGkgKyAxOyBqIDwgYXJyLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChhcnJbal0uc2NvcmUgPiBhcnJbbWF4SWR4XS5zY29yZSkge1xuICAgICAgICAgIG1heElkeCA9IGo7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChtYXhJZHggIT09IGkpIHtcbiAgICAgICAgY29uc3QgdGVtcCA9IGFycltpXTtcbiAgICAgICAgYXJyW2ldID0gYXJyW21heElkeF07XG4gICAgICAgIGFyclttYXhJZHhdID0gdGVtcDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVjb3JkIHBhdHRlcm4gdXNhZ2UgKHN1Y2Nlc3Mgb3IgZmFpbHVyZSlcbiAgICovXG4gIHJlY29yZFVzYWdlKHBhdHRlcm5JZDogc3RyaW5nLCBzdWNjZXNzOiBib29sZWFuKTogdm9pZCB7XG4gICAgY29uc3QgcGF0dGVybiA9IHRoaXMucGF0dGVybnMuZ2V0KHBhdHRlcm5JZCk7XG4gICAgaWYgKCFwYXR0ZXJuKSByZXR1cm47XG5cbiAgICBwYXR0ZXJuLnVzZUNvdW50Kys7XG4gICAgcGF0dGVybi5sYXN0VXNlZCA9IG5ldyBEYXRlKCk7XG5cbiAgICAvLyBVcGRhdGUgc3VjY2VzcyByYXRlIHdpdGggZXhwb25lbnRpYWwgbW92aW5nIGF2ZXJhZ2VcbiAgICBjb25zdCBhbHBoYSA9IDAuMTtcbiAgICBjb25zdCBvdXRjb21lID0gc3VjY2VzcyA/IDEuMCA6IDAuMDtcbiAgICBwYXR0ZXJuLnN1Y2Nlc3NSYXRlID0gYWxwaGEgKiBvdXRjb21lICsgKDEgLSBhbHBoYSkgKiBwYXR0ZXJuLnN1Y2Nlc3NSYXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBwYXR0ZXJuIGJ5IElEXG4gICAqL1xuICBnZXQocGF0dGVybklkOiBzdHJpbmcpOiBMZWFybmVkUGF0dGVybiB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucGF0dGVybnMuZ2V0KHBhdHRlcm5JZCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCBwYXR0ZXJucyBvZiBhIHR5cGVcbiAgICovXG4gIGdldEJ5VHlwZSh0eXBlOiBQYXR0ZXJuVHlwZSk6IExlYXJuZWRQYXR0ZXJuW10ge1xuICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMucGF0dGVybnMudmFsdWVzKCkpLmZpbHRlcihwID0+IHAudHlwZSA9PT0gdHlwZSk7XG4gIH1cblxuICAvKipcbiAgICogUHJ1bmUgbG93LXBlcmZvcm1pbmcgcGF0dGVybnNcbiAgICovXG4gIHBydW5lKG1pblN1Y2Nlc3NSYXRlID0gMC4zLCBtaW5Vc2VDb3VudCA9IDUpOiBudW1iZXIge1xuICAgIGxldCBwcnVuZWQgPSAwO1xuXG4gICAgZm9yIChjb25zdCBbaWQsIHBhdHRlcm5dIG9mIHRoaXMucGF0dGVybnMpIHtcbiAgICAgIGlmIChwYXR0ZXJuLnVzZUNvdW50ID49IG1pblVzZUNvdW50ICYmIHBhdHRlcm4uc3VjY2Vzc1JhdGUgPCBtaW5TdWNjZXNzUmF0ZSkge1xuICAgICAgICB0aGlzLnBhdHRlcm5zLmRlbGV0ZShpZCk7XG4gICAgICAgIHRoaXMuZW1iZWRkaW5ncy5kZWxldGUoaWQpO1xuICAgICAgICB0aGlzLmVtYmVkZGluZ05vcm1zLmRlbGV0ZShpZCk7XG4gICAgICAgIHBydW5lZCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwcnVuZWQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHN0YXRpc3RpY3NcbiAgICovXG4gIHN0YXRzKCk6IHsgdG90YWxQYXR0ZXJuczogbnVtYmVyOyBhdmdTdWNjZXNzUmF0ZTogbnVtYmVyOyBieVR5cGU6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gfSB7XG4gICAgY29uc3QgcGF0dGVybnMgPSBBcnJheS5mcm9tKHRoaXMucGF0dGVybnMudmFsdWVzKCkpO1xuICAgIGNvbnN0IGJ5VHlwZTogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuXG4gICAgbGV0IHRvdGFsU3VjY2VzcyA9IDA7XG4gICAgZm9yIChjb25zdCBwIG9mIHBhdHRlcm5zKSB7XG4gICAgICB0b3RhbFN1Y2Nlc3MgKz0gcC5zdWNjZXNzUmF0ZTtcbiAgICAgIGJ5VHlwZVtwLnR5cGVdID0gKGJ5VHlwZVtwLnR5cGVdIHx8IDApICsgMTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG90YWxQYXR0ZXJuczogcGF0dGVybnMubGVuZ3RoLFxuICAgICAgYXZnU3VjY2Vzc1JhdGU6IHBhdHRlcm5zLmxlbmd0aCA+IDAgPyB0b3RhbFN1Y2Nlc3MgLyBwYXR0ZXJucy5sZW5ndGggOiAwLFxuICAgICAgYnlUeXBlLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGNvc2luZVNpbWlsYXJpdHkoYTogRW1iZWRkaW5nLCBiOiBFbWJlZGRpbmcpOiBudW1iZXIge1xuICAgIGxldCBkb3QgPSAwLCBub3JtQSA9IDAsIG5vcm1CID0gMDtcbiAgICBjb25zdCBsZW4gPSBNYXRoLm1pbihhLmxlbmd0aCwgYi5sZW5ndGgpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgZG90ICs9IGFbaV0gKiBiW2ldO1xuICAgICAgbm9ybUEgKz0gYVtpXSAqIGFbaV07XG4gICAgICBub3JtQiArPSBiW2ldICogYltpXTtcbiAgICB9XG5cbiAgICBjb25zdCBkZW5vbSA9IE1hdGguc3FydChub3JtQSkgKiBNYXRoLnNxcnQobm9ybUIpO1xuICAgIHJldHVybiBkZW5vbSA+IDAgPyBkb3QgLyBkZW5vbSA6IDA7XG4gIH1cbn1cblxuLyoqXG4gKiBFV0MrKyAoRWxhc3RpYyBXZWlnaHQgQ29uc29saWRhdGlvbikgTWFuYWdlclxuICpcbiAqIFByZXZlbnRzIGNhdGFzdHJvcGhpYyBmb3JnZXR0aW5nIGJ5IHByb3RlY3RpbmcgaW1wb3J0YW50IHdlaWdodHMuXG4gKiBUaGlzIGlzIGEgc2ltcGxpZmllZCBKUyBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgY29uY2VwdC5cbiAqXG4gKiBPUFRJTUlaRUQ6IFVzZXMgRmxvYXQ2NEFycmF5IGZvciA1LTEweCBmYXN0ZXIgcGVuYWx0eSBjb21wdXRhdGlvblxuICovXG5leHBvcnQgY2xhc3MgRXdjTWFuYWdlciB7XG4gIHByaXZhdGUgbGFtYmRhOiBudW1iZXI7XG4gIHByaXZhdGUgdGFza3NMZWFybmVkOiBudW1iZXIgPSAwO1xuICBwcml2YXRlIGZpc2hlckRpYWdvbmFsOiBNYXA8c3RyaW5nLCBGbG9hdDY0QXJyYXk+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIG9wdGltYWxXZWlnaHRzOiBNYXA8c3RyaW5nLCBGbG9hdDY0QXJyYXk+ID0gbmV3IE1hcCgpO1xuICAvLyBQcmUtYWxsb2NhdGVkIGJ1ZmZlciBmb3IgcGVuYWx0eSBjb21wdXRhdGlvblxuICBwcml2YXRlIF9wZW5hbHR5QnVmZmVyOiBGbG9hdDY0QXJyYXkgfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihsYW1iZGEgPSAyMDAwKSB7XG4gICAgdGhpcy5sYW1iZGEgPSBsYW1iZGE7XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBuZXcgdGFzayAoYWZ0ZXIgc3VjY2Vzc2Z1bCBsZWFybmluZylcbiAgICovXG4gIHJlZ2lzdGVyVGFzayh0YXNrSWQ6IHN0cmluZywgd2VpZ2h0czogbnVtYmVyW10pOiB2b2lkIHtcbiAgICAvLyBTdG9yZSBvcHRpbWFsIHdlaWdodHMgZm9yIHRoaXMgdGFzayB1c2luZyB0eXBlZCBhcnJheXNcbiAgICBjb25zdCBvcHRpbWFsQXJyID0gbmV3IEZsb2F0NjRBcnJheSh3ZWlnaHRzLmxlbmd0aCk7XG4gICAgY29uc3QgZmlzaGVyQXJyID0gbmV3IEZsb2F0NjRBcnJheSh3ZWlnaHRzLmxlbmd0aCk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHdlaWdodHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIG9wdGltYWxBcnJbaV0gPSB3ZWlnaHRzW2ldO1xuICAgICAgZmlzaGVyQXJyW2ldID0gTWF0aC5hYnMod2VpZ2h0c1tpXSkgKiB0aGlzLmxhbWJkYTtcbiAgICB9XG5cbiAgICB0aGlzLm9wdGltYWxXZWlnaHRzLnNldCh0YXNrSWQsIG9wdGltYWxBcnIpO1xuICAgIHRoaXMuZmlzaGVyRGlhZ29uYWwuc2V0KHRhc2tJZCwgZmlzaGVyQXJyKTtcbiAgICB0aGlzLnRhc2tzTGVhcm5lZCsrO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbXB1dGUgRVdDIHBlbmFsdHkgZm9yIHdlaWdodCB1cGRhdGVcbiAgICogT1BUSU1JWkVEOiBVc2VzIHR5cGVkIGFycmF5cyBhbmQgbWluaW1pemVzIGFsbG9jYXRpb25zXG4gICAqL1xuICBjb21wdXRlUGVuYWx0eShjdXJyZW50V2VpZ2h0czogbnVtYmVyW10pOiBudW1iZXIge1xuICAgIGxldCBwZW5hbHR5ID0gMDtcbiAgICBjb25zdCBsZW4gPSBjdXJyZW50V2VpZ2h0cy5sZW5ndGg7XG5cbiAgICBmb3IgKGNvbnN0IFt0YXNrSWQsIG9wdGltYWxdIG9mIHRoaXMub3B0aW1hbFdlaWdodHMpIHtcbiAgICAgIGNvbnN0IGZpc2hlciA9IHRoaXMuZmlzaGVyRGlhZ29uYWwuZ2V0KHRhc2tJZCk7XG4gICAgICBpZiAoIWZpc2hlcikgY29udGludWU7XG5cbiAgICAgIGNvbnN0IG1pbkxlbiA9IE1hdGgubWluKGxlbiwgb3B0aW1hbC5sZW5ndGgpO1xuXG4gICAgICAvLyBVbnJvbGxlZCBsb29wIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICAgIGxldCBpID0gMDtcbiAgICAgIGZvciAoOyBpICsgMyA8IG1pbkxlbjsgaSArPSA0KSB7XG4gICAgICAgIGNvbnN0IGRpZmYwID0gY3VycmVudFdlaWdodHNbaV0gLSBvcHRpbWFsW2ldO1xuICAgICAgICBjb25zdCBkaWZmMSA9IGN1cnJlbnRXZWlnaHRzW2kgKyAxXSAtIG9wdGltYWxbaSArIDFdO1xuICAgICAgICBjb25zdCBkaWZmMiA9IGN1cnJlbnRXZWlnaHRzW2kgKyAyXSAtIG9wdGltYWxbaSArIDJdO1xuICAgICAgICBjb25zdCBkaWZmMyA9IGN1cnJlbnRXZWlnaHRzW2kgKyAzXSAtIG9wdGltYWxbaSArIDNdO1xuICAgICAgICBwZW5hbHR5ICs9IGZpc2hlcltpXSAqIGRpZmYwICogZGlmZjAgK1xuICAgICAgICAgICAgICAgICAgIGZpc2hlcltpICsgMV0gKiBkaWZmMSAqIGRpZmYxICtcbiAgICAgICAgICAgICAgICAgICBmaXNoZXJbaSArIDJdICogZGlmZjIgKiBkaWZmMiArXG4gICAgICAgICAgICAgICAgICAgZmlzaGVyW2kgKyAzXSAqIGRpZmYzICogZGlmZjM7XG4gICAgICB9XG4gICAgICAvLyBIYW5kbGUgcmVtYWluaW5nIGVsZW1lbnRzXG4gICAgICBmb3IgKDsgaSA8IG1pbkxlbjsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGRpZmYgPSBjdXJyZW50V2VpZ2h0c1tpXSAtIG9wdGltYWxbaV07XG4gICAgICAgIHBlbmFsdHkgKz0gZmlzaGVyW2ldICogZGlmZiAqIGRpZmY7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBlbmFsdHkgKiAwLjU7XG4gIH1cblxuICAvKipcbiAgICogR2V0IEVXQyBzdGF0aXN0aWNzXG4gICAqL1xuICBzdGF0cygpOiBFd2NTdGF0cyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRhc2tzTGVhcm5lZDogdGhpcy50YXNrc0xlYXJuZWQsXG4gICAgICBmaXNoZXJDb21wdXRlZDogdGhpcy5maXNoZXJEaWFnb25hbC5zaXplID4gMCxcbiAgICAgIHByb3RlY3Rpb25TdHJlbmd0aDogdGhpcy5sYW1iZGEsXG4gICAgICBmb3JnZXR0aW5nUmF0ZTogdGhpcy5lc3RpbWF0ZUZvcmdldHRpbmdSYXRlKCksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgZXN0aW1hdGVGb3JnZXR0aW5nUmF0ZSgpOiBudW1iZXIge1xuICAgIC8vIFNpbXBsaWZpZWQgZXN0aW1hdGlvbiBiYXNlZCBvbiBudW1iZXIgb2YgdGFza3NcbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgMSAtIE1hdGguZXhwKC10aGlzLnRhc2tzTGVhcm5lZCAqIDAuMSkpO1xuICB9XG59XG5cbi8qKlxuICogU09OQSBMZWFybmluZyBDb29yZGluYXRvclxuICpcbiAqIE9yY2hlc3RyYXRlcyB0aGUgbGVhcm5pbmcgbG9vcHMgYW5kIGNvbXBvbmVudHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBTb25hQ29vcmRpbmF0b3Ige1xuICBwcml2YXRlIGNvbmZpZzogUmVxdWlyZWQ8U29uYUNvbmZpZz47XG4gIHByaXZhdGUgdHJhamVjdG9yeUJ1ZmZlcjogUXVlcnlUcmFqZWN0b3J5W10gPSBbXTtcbiAgcHJpdmF0ZSByZWFzb25pbmdCYW5rOiBSZWFzb25pbmdCYW5rO1xuICBwcml2YXRlIGV3Y01hbmFnZXI6IEV3Y01hbmFnZXI7XG4gIHByaXZhdGUgc2lnbmFsQnVmZmVyOiBMZWFybmluZ1NpZ25hbFtdID0gW107XG4gIHByaXZhdGUgbWljcm9Mb3JhOiBMb3JhQWRhcHRlcjtcbiAgcHJpdmF0ZSBtaWNyb0xvcmFVcGRhdGVzID0gMDtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc/OiBTb25hQ29uZmlnKSB7XG4gICAgdGhpcy5jb25maWcgPSB7IC4uLkRFRkFVTFRfU09OQV9DT05GSUcsIC4uLmNvbmZpZyB9O1xuICAgIHRoaXMucmVhc29uaW5nQmFuayA9IG5ldyBSZWFzb25pbmdCYW5rKHRoaXMuY29uZmlnLnBhdHRlcm5UaHJlc2hvbGQpO1xuICAgIHRoaXMuZXdjTWFuYWdlciA9IG5ldyBFd2NNYW5hZ2VyKHRoaXMuY29uZmlnLmV3Y0xhbWJkYSk7XG4gICAgdGhpcy5taWNyb0xvcmEgPSBuZXcgTG9yYUFkYXB0ZXIoXG4gICAgICB7IHJhbms6IE1JQ1JPX0xPUkFfUkFOSyB9LFxuICAgICAgTUlDUk9fTE9SQV9ESU0sXG4gICAgICBNSUNST19MT1JBX0RJTVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmVjb3JkIGEgbGVhcm5pbmcgc2lnbmFsXG4gICAqXG4gICAqIEV2ZXJ5IHNpZ25hbCBkcml2ZXMgdGhlIGluc3RhbnQgbG9vcDogcXVhbGl0eSBhYm92ZSAwLjUgcmVpbmZvcmNlcyB0aGVcbiAgICogc2lnbmFsJ3MgZGlyZWN0aW9uIGluIHRoZSBtaWNyby1Mb1JBLCBxdWFsaXR5IGJlbG93IDAuNSB1bmxlYXJucyBpdFxuICAgKiAocHJldmlvdXNseSBvbmx5IHF1YWxpdHkgPj0gMC44IHdhcyBwcm9jZXNzZWQsIHNvIG5lZ2F0aXZlIGZlZWRiYWNrXG4gICAqIG5ldmVyIGFkYXB0ZWQgYW55dGhpbmcpLlxuICAgKi9cbiAgcmVjb3JkU2lnbmFsKHNpZ25hbDogTGVhcm5pbmdTaWduYWwpOiB2b2lkIHtcbiAgICB0aGlzLnNpZ25hbEJ1ZmZlci5wdXNoKHNpZ25hbCk7XG5cbiAgICAvLyBJbnN0YW50IGxvb3AgLSBpbW1lZGlhdGUgbGVhcm5pbmdcbiAgICBpZiAodGhpcy5jb25maWcuaW5zdGFudExvb3BFbmFibGVkKSB7XG4gICAgICB0aGlzLnByb2Nlc3NJbnN0YW50TGVhcm5pbmcoc2lnbmFsKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVjb3JkIGEgY29tcGxldGVkIHRyYWplY3RvcnlcbiAgICovXG4gIHJlY29yZFRyYWplY3RvcnkodHJhamVjdG9yeTogUXVlcnlUcmFqZWN0b3J5KTogdm9pZCB7XG4gICAgdGhpcy50cmFqZWN0b3J5QnVmZmVyLnB1c2godHJhamVjdG9yeSk7XG5cbiAgICAvLyBNYWludGFpbiBidWZmZXIgc2l6ZVxuICAgIHdoaWxlICh0aGlzLnRyYWplY3RvcnlCdWZmZXIubGVuZ3RoID4gdGhpcy5jb25maWcubWF4VHJhamVjdG9yeVNpemUpIHtcbiAgICAgIHRoaXMudHJhamVjdG9yeUJ1ZmZlci5zaGlmdCgpO1xuICAgIH1cblxuICAgIC8vIEV4dHJhY3QgcGF0dGVybnMgZnJvbSBzdWNjZXNzZnVsIHRyYWplY3Rvcmllc1xuICAgIGlmICh0cmFqZWN0b3J5Lm91dGNvbWUgPT09ICdzdWNjZXNzJykge1xuICAgICAgdGhpcy5leHRyYWN0UGF0dGVybnModHJhamVjdG9yeSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1biBiYWNrZ3JvdW5kIGxlYXJuaW5nIGxvb3BcbiAgICovXG4gIHJ1bkJhY2tncm91bmRMb29wKCk6IHsgcGF0dGVybnNMZWFybmVkOiBudW1iZXI7IHRyYWplY3Rvcmllc1Byb2Nlc3NlZDogbnVtYmVyIH0ge1xuICAgIGlmICghdGhpcy5jb25maWcuYmFja2dyb3VuZExvb3BFbmFibGVkKSB7XG4gICAgICByZXR1cm4geyBwYXR0ZXJuc0xlYXJuZWQ6IDAsIHRyYWplY3Rvcmllc1Byb2Nlc3NlZDogMCB9O1xuICAgIH1cblxuICAgIGxldCBwYXR0ZXJuc0xlYXJuZWQgPSAwO1xuICAgIGNvbnN0IHRyYWplY3Rvcmllc1Byb2Nlc3NlZCA9IHRoaXMudHJhamVjdG9yeUJ1ZmZlci5sZW5ndGg7XG5cbiAgICAvLyBQcm9jZXNzIGFjY3VtdWxhdGVkIHRyYWplY3Rvcmllc1xuICAgIGZvciAoY29uc3QgdHJhaiBvZiB0aGlzLnRyYWplY3RvcnlCdWZmZXIpIHtcbiAgICAgIGlmICh0cmFqLm91dGNvbWUgPT09ICdzdWNjZXNzJyB8fCB0cmFqLm91dGNvbWUgPT09ICdwYXJ0aWFsJykge1xuICAgICAgICBwYXR0ZXJuc0xlYXJuZWQgKz0gdGhpcy5leHRyYWN0UGF0dGVybnModHJhaik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUHJ1bmUgbG93LXBlcmZvcm1pbmcgcGF0dGVybnNcbiAgICB0aGlzLnJlYXNvbmluZ0JhbmsucHJ1bmUoKTtcblxuICAgIC8vIENsZWFyIHByb2Nlc3NlZCB0cmFqZWN0b3JpZXNcbiAgICB0aGlzLnRyYWplY3RvcnlCdWZmZXIgPSBbXTtcblxuICAgIHJldHVybiB7IHBhdHRlcm5zTGVhcm5lZCwgdHJhamVjdG9yaWVzUHJvY2Vzc2VkIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHJlYXNvbmluZyBiYW5rIGZvciBwYXR0ZXJuIHF1ZXJpZXNcbiAgICovXG4gIGdldFJlYXNvbmluZ0JhbmsoKTogUmVhc29uaW5nQmFuayB7XG4gICAgcmV0dXJuIHRoaXMucmVhc29uaW5nQmFuaztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgRVdDIG1hbmFnZXJcbiAgICovXG4gIGdldEV3Y01hbmFnZXIoKTogRXdjTWFuYWdlciB7XG4gICAgcmV0dXJuIHRoaXMuZXdjTWFuYWdlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgc3RhdGlzdGljc1xuICAgKi9cbiAgc3RhdHMoKToge1xuICAgIHNpZ25hbHNSZWNlaXZlZDogbnVtYmVyO1xuICAgIHRyYWplY3Rvcmllc0J1ZmZlcmVkOiBudW1iZXI7XG4gICAgcGF0dGVybnM6IFJldHVyblR5cGU8UmVhc29uaW5nQmFua1snc3RhdHMnXT47XG4gICAgZXdjOiBFd2NTdGF0cztcbiAgICBtaWNyb0xvcmE6IHsgdXBkYXRlczogbnVtYmVyOyBkZWx0YU5vcm06IG51bWJlciB9O1xuICB9IHtcbiAgICByZXR1cm4ge1xuICAgICAgc2lnbmFsc1JlY2VpdmVkOiB0aGlzLnNpZ25hbEJ1ZmZlci5sZW5ndGgsXG4gICAgICB0cmFqZWN0b3JpZXNCdWZmZXJlZDogdGhpcy50cmFqZWN0b3J5QnVmZmVyLmxlbmd0aCxcbiAgICAgIHBhdHRlcm5zOiB0aGlzLnJlYXNvbmluZ0Jhbmsuc3RhdHMoKSxcbiAgICAgIGV3YzogdGhpcy5ld2NNYW5hZ2VyLnN0YXRzKCksXG4gICAgICBtaWNyb0xvcmE6IHtcbiAgICAgICAgdXBkYXRlczogdGhpcy5taWNyb0xvcmFVcGRhdGVzLFxuICAgICAgICBkZWx0YU5vcm06IHRoaXMubWljcm9Mb3JhRGVsdGFOb3JtKCksXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQXBwbHkgdGhlIG1pY3JvLUxvUkEgdHJhbnNmb3JtYXRpb24gbGVhcm5lZCBmcm9tIGZlZWRiYWNrLlxuICAgKlxuICAgKiBJbnB1dCBpcyB0cnVuY2F0ZWQvemVyby1wYWRkZWQgdG8gdGhlIGFkYXB0ZXIgZGltZW5zaW9uOyB0aGUgcmVzaWR1YWxcbiAgICogY29ubmVjdGlvbiBtZWFucyBhbiB1bnRyYWluZWQgYWRhcHRlciByZXR1cm5zIHRoZSBpbnB1dCB1bmNoYW5nZWQuXG4gICAqL1xuICBhcHBseU1pY3JvTG9yYShpbnB1dDogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgcmV0dXJuIHRoaXMubWljcm9Mb3JhLmZvcndhcmQoaW5wdXQuc2xpY2UoMCwgTUlDUk9fTE9SQV9ESU0pKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGcm9iZW5pdXMgbm9ybSBvZiB0aGUgbWljcm8tTG9SQSB3ZWlnaHQgZGVsdGEgKHNjYWxpbmcgKiBBIEAgQikuXG4gICAqXG4gICAqIDAgbWVhbnMgbm8gYWRhcHRhdGlvbiBoYXMgb2NjdXJyZWQgKExvUkEgQiBpcyB6ZXJvLWluaXRpYWxpemVkLCBzbyB0aGVcbiAgICogZGVsdGEgaXMgZXhhY3RseSB6ZXJvIHVudGlsIHRoZSBmaXJzdCBmZWVkYmFjayB1cGRhdGUpLiBDb25zdW1lcnMgY2FuXG4gICAqIHN1cmZhY2UgdGhpcyBkaXJlY3RseSAoZS5nLiBhIHN0YXR1c2xpbmUgXCJkZWx0YSBMb1JBXCIgZmllbGQpIOKAlCBzZWUgIzU1My5cbiAgICovXG4gIG1pY3JvTG9yYURlbHRhTm9ybSgpOiBudW1iZXIge1xuICAgIGNvbnN0IHsgbG9yYUEsIGxvcmFCLCBzY2FsaW5nIH0gPSB0aGlzLm1pY3JvTG9yYS5nZXRXZWlnaHRzKCk7XG4gICAgY29uc3QgcmFuayA9IGxvcmFCLmxlbmd0aDtcbiAgICBsZXQgc3VtU3EgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbG9yYUEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgTUlDUk9fTE9SQV9ESU07IGorKykge1xuICAgICAgICBsZXQgZCA9IDA7XG4gICAgICAgIGZvciAobGV0IHIgPSAwOyByIDwgcmFuazsgcisrKSB7XG4gICAgICAgICAgZCArPSBsb3JhQVtpXVtyXSAqIGxvcmFCW3JdW2pdO1xuICAgICAgICB9XG4gICAgICAgIHN1bVNxICs9IHNjYWxpbmcgKiBkICogKHNjYWxpbmcgKiBkKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIE1hdGguc3FydChzdW1TcSk7XG4gIH1cblxuICAvKipcbiAgICogSW5zdGFudC1sb29wIGxlYXJuaW5nOiBhIHNpbmdsZSBmZWVkYmFjayBzaWduYWwgcHJvZHVjZXMgYSByZWFsXG4gICAqIG1pY3JvLUxvUkEgd2VpZ2h0IHVwZGF0ZSAoZml4ZXMgIzU1MyDigJQgdGhpcyB3YXMgYSBuby1vcCBzdHViLCBzb1xuICAgKiBsZWFybi1mcm9tLWZlZWRiYWNrIG5ldmVyIGNoYW5nZWQgYW55IHdlaWdodCkuXG4gICAqXG4gICAqIFJFSU5GT1JDRS1zdHlsZSB3aXRoIGEgZml4ZWQgMC41IGJhc2VsaW5lOiByZXdhcmQgPSBxdWFsaXR5IC0gMC41LlxuICAgKiBUaGUgZ3JhZGllbnQgcHVzaGVzIHRoZSBhZGFwdGVyIG91dHB1dCB0b3dhcmQgdGhlIHNpZ25hbCdzIGVtYmVkZGluZ1xuICAgKiBkaXJlY3Rpb24gZm9yIHBvc2l0aXZlIHJld2FyZCBhbmQgYXdheSBmcm9tIGl0IGZvciBuZWdhdGl2ZSByZXdhcmRcbiAgICogKGJhY2t3YXJkKCkgYXBwbGllcyBgd2VpZ2h0cyAtPSBsciAqIGdyYWRgLCBoZW5jZSB0aGUgbmVnYXRlZCBzaWduKS5cbiAgICovXG4gIHByaXZhdGUgcHJvY2Vzc0luc3RhbnRMZWFybmluZyhzaWduYWw6IExlYXJuaW5nU2lnbmFsKTogdm9pZCB7XG4gICAgY29uc3QgcmV3YXJkID0gc2lnbmFsLnF1YWxpdHkgLSAwLjU7XG4gICAgaWYgKHJld2FyZCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgY29uc3QgaW5wdXQgPSB0aGlzLmNyZWF0ZUVtYmVkZGluZyhcbiAgICAgIHNpZ25hbC5jb3JyZWN0aW9uID8/IGAke3NpZ25hbC5yZXF1ZXN0SWR9OiR7c2lnbmFsLnR5cGV9YFxuICAgICk7XG4gICAgY29uc3QgZ3JhZE91dHB1dCA9IGlucHV0Lm1hcCh4ID0+IC1yZXdhcmQgKiB4KTtcbiAgICB0aGlzLm1pY3JvTG9yYS5iYWNrd2FyZChpbnB1dCwgZ3JhZE91dHB1dCwgdGhpcy5jb25maWcubG9yYUxlYXJuaW5nUmF0ZSk7XG4gICAgdGhpcy5taWNyb0xvcmFVcGRhdGVzKys7XG4gIH1cblxuICBwcml2YXRlIGV4dHJhY3RQYXR0ZXJucyh0cmFqZWN0b3J5OiBRdWVyeVRyYWplY3RvcnkpOiBudW1iZXIge1xuICAgIGxldCBleHRyYWN0ZWQgPSAwO1xuXG4gICAgZm9yIChjb25zdCBzdGVwIG9mIHRyYWplY3Rvcnkuc3RlcHMpIHtcbiAgICAgIGlmIChzdGVwLmNvbmZpZGVuY2UgPj0gdGhpcy5jb25maWcucGF0dGVyblRocmVzaG9sZCkge1xuICAgICAgICAvLyBDcmVhdGUgZW1iZWRkaW5nIGZyb20gc3RlcCAoc2ltcGxpZmllZClcbiAgICAgICAgY29uc3QgZW1iZWRkaW5nID0gdGhpcy5jcmVhdGVFbWJlZGRpbmcoc3RlcC5pbnB1dCArIHN0ZXAub3V0cHV0KTtcblxuICAgICAgICAvLyBEZXRlcm1pbmUgcGF0dGVybiB0eXBlXG4gICAgICAgIGNvbnN0IHR5cGUgPSB0aGlzLnN0ZXBUeXBlVG9QYXR0ZXJuVHlwZShzdGVwLnR5cGUpO1xuXG4gICAgICAgIC8vIFN0b3JlIGlmIG5vdCB0b28gc2ltaWxhciB0byBleGlzdGluZ1xuICAgICAgICBjb25zdCBzaW1pbGFyID0gdGhpcy5yZWFzb25pbmdCYW5rLmZpbmRTaW1pbGFyKGVtYmVkZGluZywgMSk7XG4gICAgICAgIGlmIChzaW1pbGFyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMucmVhc29uaW5nQmFuay5zdG9yZSh0eXBlLCBlbWJlZGRpbmcpO1xuICAgICAgICAgIGV4dHJhY3RlZCsrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGV4dHJhY3RlZDtcbiAgfVxuXG4gIHByaXZhdGUgc3RlcFR5cGVUb1BhdHRlcm5UeXBlKHN0ZXBUeXBlOiBUcmFqZWN0b3J5U3RlcFsndHlwZSddKTogUGF0dGVyblR5cGUge1xuICAgIHN3aXRjaCAoc3RlcFR5cGUpIHtcbiAgICAgIGNhc2UgJ3F1ZXJ5JzpcbiAgICAgIGNhc2UgJ2dlbmVyYXRlJzpcbiAgICAgICAgcmV0dXJuICdxdWVyeV9yZXNwb25zZSc7XG4gICAgICBjYXNlICdyb3V0ZSc6XG4gICAgICAgIHJldHVybiAncm91dGluZyc7XG4gICAgICBjYXNlICdtZW1vcnknOlxuICAgICAgICByZXR1cm4gJ2NvbnRleHRfcmV0cmlldmFsJztcbiAgICAgIGNhc2UgJ2ZlZWRiYWNrJzpcbiAgICAgICAgcmV0dXJuICdjb3JyZWN0aW9uJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiAncXVlcnlfcmVzcG9uc2UnO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlRW1iZWRkaW5nKHRleHQ6IHN0cmluZyk6IEVtYmVkZGluZyB7XG4gICAgLy8gU2ltcGxpZmllZCBoYXNoLWJhc2VkIGVtYmVkZGluZyAocmVhbCBpbXBsIHVzZXMgbW9kZWwpXG4gICAgY29uc3QgZGltID0gNjQ7XG4gICAgY29uc3QgZW1iZWRkaW5nID0gbmV3IEFycmF5KGRpbSkuZmlsbCgwKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgaWR4ID0gKHRleHQuY2hhckNvZGVBdChpKSAqIChpICsgMSkpICUgZGltO1xuICAgICAgZW1iZWRkaW5nW2lkeF0gKz0gMC4xO1xuICAgIH1cblxuICAgIC8vIE5vcm1hbGl6ZVxuICAgIGNvbnN0IG5vcm0gPSBNYXRoLnNxcnQoZW1iZWRkaW5nLnJlZHVjZSgocywgeCkgPT4gcyArIHggKiB4LCAwKSkgfHwgMTtcbiAgICByZXR1cm4gZW1iZWRkaW5nLm1hcCh4ID0+IHggLyBub3JtKTtcbiAgfVxufVxuXG4vLyBFeHBvcnQgYWxsIFNPTkEgY29tcG9uZW50c1xuZXhwb3J0IHtcbiAgREVGQVVMVF9TT05BX0NPTkZJRyxcbn07XG4iXX0=