@ruvector/ruvllm 2.6.0 → 2.6.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 (63) hide show
  1. package/dist/cjs/engine.d.ts +2 -2
  2. package/dist/cjs/engine.d.ts.map +1 -1
  3. package/dist/cjs/engine.js +41 -19
  4. package/dist/cjs/native.d.ts +17 -8
  5. package/dist/cjs/native.d.ts.map +1 -1
  6. package/dist/cjs/native.js +1 -1
  7. package/dist/cjs/rlm/controller.d.ts +245 -0
  8. package/dist/cjs/rlm/controller.d.ts.map +1 -0
  9. package/dist/cjs/rlm/controller.js +554 -0
  10. package/dist/cjs/rlm/index.d.ts +62 -0
  11. package/dist/cjs/rlm/index.d.ts.map +1 -0
  12. package/dist/cjs/rlm/index.js +97 -0
  13. package/dist/cjs/rlm/training.d.ts +333 -0
  14. package/dist/cjs/rlm/training.d.ts.map +1 -0
  15. package/dist/cjs/rlm/training.js +680 -0
  16. package/dist/cjs/rlm/types.d.ts +189 -0
  17. package/dist/cjs/rlm/types.d.ts.map +1 -0
  18. package/dist/cjs/rlm/types.js +10 -0
  19. package/dist/cjs/types.d.ts +4 -2
  20. package/dist/cjs/types.d.ts.map +1 -1
  21. package/dist/cjs/types.js +1 -1
  22. package/dist/esm/benchmarks/index.d.ts +5 -5
  23. package/dist/esm/benchmarks/index.js +5 -5
  24. package/dist/esm/benchmarks/model-comparison.d.ts +2 -2
  25. package/dist/esm/benchmarks/model-comparison.js +2 -2
  26. package/dist/esm/contrastive.d.ts +1 -1
  27. package/dist/esm/engine.d.ts +2 -2
  28. package/dist/esm/engine.d.ts.map +1 -1
  29. package/dist/esm/engine.js +42 -20
  30. package/dist/esm/export.d.ts +2 -2
  31. package/dist/esm/federated.d.ts +1 -1
  32. package/dist/esm/federated.js +1 -1
  33. package/dist/esm/index.d.ts +16 -16
  34. package/dist/esm/index.js +16 -16
  35. package/dist/esm/lora.d.ts +1 -1
  36. package/dist/esm/native.d.ts +17 -8
  37. package/dist/esm/native.d.ts.map +1 -1
  38. package/dist/esm/native.js +1 -1
  39. package/dist/esm/rlm/controller.d.ts +245 -0
  40. package/dist/esm/rlm/controller.d.ts.map +1 -0
  41. package/dist/esm/rlm/controller.js +550 -0
  42. package/dist/esm/rlm/index.d.ts +62 -0
  43. package/dist/esm/rlm/index.d.ts.map +1 -0
  44. package/dist/esm/rlm/index.js +71 -0
  45. package/dist/esm/rlm/training.d.ts +333 -0
  46. package/dist/esm/rlm/training.d.ts.map +1 -0
  47. package/dist/esm/rlm/training.js +672 -0
  48. package/dist/esm/rlm/types.d.ts +189 -0
  49. package/dist/esm/rlm/types.d.ts.map +1 -0
  50. package/dist/esm/rlm/types.js +9 -0
  51. package/dist/esm/session.d.ts +1 -1
  52. package/dist/esm/simd.js +1 -1
  53. package/dist/esm/sona.d.ts +1 -1
  54. package/dist/esm/sona.js +1 -1
  55. package/dist/esm/streaming.d.ts +1 -1
  56. package/dist/esm/training.d.ts +3 -3
  57. package/dist/esm/training.js +2 -2
  58. package/dist/esm/types.d.ts +4 -2
  59. package/dist/esm/types.d.ts.map +1 -1
  60. package/dist/esm/types.js +1 -1
  61. package/package.json +4 -2
  62. package/scripts/fix-esm-extensions.mjs +181 -0
  63. package/scripts/smoke-esm.mjs +82 -0
@@ -0,0 +1,680 @@
1
+ "use strict";
2
+ /**
3
+ * RLM (Recursive Learning Machine) Training Module
4
+ *
5
+ * Provides training capabilities for RuvLTRA models on RLM task routing
6
+ * and decomposition, including query decomposition, answer synthesis,
7
+ * and agent routing optimization.
8
+ *
9
+ * @module rlm/training
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RlmTrainer = exports.HARD_NEGATIVE_PAIRS = exports.AGENT_DEFINITIONS = exports.ROUTING_FOCUSED_CONFIG = exports.THOROUGH_RLM_CONFIG = exports.FAST_RLM_CONFIG = exports.DEFAULT_RLM_CONFIG = void 0;
13
+ exports.createRlmTrainer = createRlmTrainer;
14
+ exports.createEmptyExample = createEmptyExample;
15
+ exports.createSubQuery = createSubQuery;
16
+ exports.createSubAnswer = createSubAnswer;
17
+ // =============================================================================
18
+ // Default Configurations
19
+ // =============================================================================
20
+ /**
21
+ * Default RLM training configuration
22
+ */
23
+ exports.DEFAULT_RLM_CONFIG = {
24
+ decompositionLr: 1e-5,
25
+ synthesisLr: 1e-5,
26
+ contrastiveLr: 2e-5,
27
+ batchSize: 32,
28
+ epochs: 10,
29
+ contrastiveMargin: 0.5,
30
+ infonceTemperature: 0.07,
31
+ decompositionWeight: 1.0,
32
+ synthesisWeight: 1.0,
33
+ routingWeight: 1.0,
34
+ qualityThreshold: 0.7,
35
+ evaluationInterval: 1,
36
+ warmupSteps: 100,
37
+ earlyStoppingPatience: 3,
38
+ validationSplit: 0.1,
39
+ seed: 42,
40
+ };
41
+ /**
42
+ * Fast training configuration
43
+ */
44
+ exports.FAST_RLM_CONFIG = {
45
+ ...exports.DEFAULT_RLM_CONFIG,
46
+ epochs: 3,
47
+ batchSize: 64,
48
+ decompositionLr: 1e-4,
49
+ synthesisLr: 1e-4,
50
+ contrastiveLr: 5e-5,
51
+ earlyStoppingPatience: 1,
52
+ };
53
+ /**
54
+ * Thorough training configuration
55
+ */
56
+ exports.THOROUGH_RLM_CONFIG = {
57
+ ...exports.DEFAULT_RLM_CONFIG,
58
+ epochs: 50,
59
+ batchSize: 16,
60
+ decompositionLr: 5e-6,
61
+ synthesisLr: 5e-6,
62
+ contrastiveLr: 1e-5,
63
+ earlyStoppingPatience: 10,
64
+ };
65
+ /**
66
+ * Routing-focused training configuration
67
+ */
68
+ exports.ROUTING_FOCUSED_CONFIG = {
69
+ ...exports.DEFAULT_RLM_CONFIG,
70
+ routingWeight: 2.0,
71
+ decompositionWeight: 0.5,
72
+ synthesisWeight: 0.5,
73
+ contrastiveLr: 3e-5,
74
+ contrastiveMargin: 0.3,
75
+ infonceTemperature: 0.05,
76
+ };
77
+ // =============================================================================
78
+ // Agent Definitions
79
+ // =============================================================================
80
+ /**
81
+ * Agent types with descriptions and keywords
82
+ */
83
+ exports.AGENT_DEFINITIONS = {
84
+ coder: {
85
+ description: 'Software developer who writes and implements code',
86
+ keywords: ['implement', 'build', 'create', 'code', 'write', 'develop', 'program'],
87
+ },
88
+ researcher: {
89
+ description: 'Technical researcher who investigates and analyzes',
90
+ keywords: ['research', 'investigate', 'analyze', 'explore', 'study', 'examine'],
91
+ },
92
+ reviewer: {
93
+ description: 'Code reviewer who evaluates code quality',
94
+ keywords: ['review', 'check', 'evaluate', 'assess', 'examine', 'inspect'],
95
+ },
96
+ tester: {
97
+ description: 'QA engineer who writes and runs tests',
98
+ keywords: ['test', 'unit test', 'coverage', 'validate', 'verify', 'qa'],
99
+ },
100
+ architect: {
101
+ description: 'System architect who designs software structure',
102
+ keywords: ['design', 'plan', 'architecture', 'schema', 'structure', 'diagram'],
103
+ },
104
+ 'security-architect': {
105
+ description: 'Security specialist who audits vulnerabilities',
106
+ keywords: ['security', 'audit', 'vulnerability', 'xss', 'injection', 'cve'],
107
+ },
108
+ debugger: {
109
+ description: 'Bug hunter who fixes errors and traces issues',
110
+ keywords: ['fix', 'debug', 'bug', 'error', 'trace', 'crash', 'troubleshoot'],
111
+ },
112
+ documenter: {
113
+ description: 'Technical writer who creates documentation',
114
+ keywords: ['document', 'jsdoc', 'readme', 'comment', 'explain', 'describe'],
115
+ },
116
+ refactorer: {
117
+ description: 'Code modernizer who restructures without changing behavior',
118
+ keywords: ['refactor', 'restructure', 'modernize', 'clean', 'simplify', 'consolidate'],
119
+ },
120
+ optimizer: {
121
+ description: 'Performance engineer who speeds up slow code',
122
+ keywords: ['optimize', 'performance', 'speed', 'cache', 'improve', 'faster'],
123
+ },
124
+ devops: {
125
+ description: 'DevOps engineer who manages deployment and infrastructure',
126
+ keywords: ['deploy', 'ci/cd', 'kubernetes', 'docker', 'infrastructure', 'pipeline'],
127
+ },
128
+ 'api-docs': {
129
+ description: 'API documentation specialist who creates specs',
130
+ keywords: ['openapi', 'swagger', 'api reference', 'endpoint', 'spec', 'rest'],
131
+ },
132
+ planner: {
133
+ description: 'Project planner who organizes and schedules work',
134
+ keywords: ['plan', 'estimate', 'schedule', 'timeline', 'sprint', 'roadmap'],
135
+ },
136
+ };
137
+ /**
138
+ * Hard negative pairs (confusable agent combinations)
139
+ */
140
+ exports.HARD_NEGATIVE_PAIRS = [
141
+ ['coder', 'debugger'],
142
+ ['coder', 'refactorer'],
143
+ ['researcher', 'reviewer'],
144
+ ['tester', 'reviewer'],
145
+ ['architect', 'planner'],
146
+ ['documenter', 'api-docs'],
147
+ ['optimizer', 'debugger'],
148
+ ['devops', 'architect'],
149
+ ['security-architect', 'reviewer'],
150
+ ];
151
+ // =============================================================================
152
+ // RLM Trainer Class
153
+ // =============================================================================
154
+ /**
155
+ * RLM Trainer for RuvLTRA models
156
+ *
157
+ * Provides training capabilities for decomposition, synthesis, and routing tasks.
158
+ */
159
+ class RlmTrainer {
160
+ /**
161
+ * Create a new RLM trainer
162
+ */
163
+ constructor(config = {}) {
164
+ this.currentEpoch = 0;
165
+ this.currentStep = 0;
166
+ this.bestValLoss = Infinity;
167
+ this.patienceCounter = 0;
168
+ this.lossHistory = [];
169
+ this.valLossHistory = [];
170
+ this.config = { ...exports.DEFAULT_RLM_CONFIG, ...config };
171
+ }
172
+ /**
173
+ * Train on decomposition task
174
+ *
175
+ * Learns to break complex queries into manageable sub-queries.
176
+ */
177
+ async trainDecomposition(dataset) {
178
+ const startTime = Date.now();
179
+ this.resetState();
180
+ const { trainSet, valSet } = this.splitDataset(dataset);
181
+ const batches = this.createBatches(trainSet);
182
+ for (let epoch = 0; epoch < this.config.epochs; epoch++) {
183
+ this.currentEpoch = epoch;
184
+ let epochLoss = 0;
185
+ for (const batch of batches) {
186
+ const batchLoss = this.trainDecompositionBatch(batch);
187
+ epochLoss += batchLoss;
188
+ this.currentStep++;
189
+ }
190
+ const avgLoss = epochLoss / batches.length;
191
+ this.lossHistory.push(avgLoss);
192
+ // Validation
193
+ const valLoss = this.validateDecomposition(valSet);
194
+ this.valLossHistory.push(valLoss);
195
+ // Early stopping
196
+ if (valLoss < this.bestValLoss) {
197
+ this.bestValLoss = valLoss;
198
+ this.patienceCounter = 0;
199
+ }
200
+ else {
201
+ this.patienceCounter++;
202
+ if (this.patienceCounter >= this.config.earlyStoppingPatience) {
203
+ break;
204
+ }
205
+ }
206
+ }
207
+ return {
208
+ phase: 'decomposition',
209
+ epochsCompleted: this.currentEpoch + 1,
210
+ totalSteps: this.currentStep,
211
+ finalLoss: this.lossHistory[this.lossHistory.length - 1] || 0,
212
+ bestValLoss: this.bestValLoss,
213
+ bestEpoch: this.findBestEpoch(),
214
+ accuracy: 0, // Not applicable for decomposition
215
+ lossHistory: this.lossHistory,
216
+ valLossHistory: this.valLossHistory,
217
+ durationMs: Date.now() - startTime,
218
+ earlyStopped: this.patienceCounter >= this.config.earlyStoppingPatience,
219
+ };
220
+ }
221
+ /**
222
+ * Train on synthesis task
223
+ *
224
+ * Learns to combine sub-answers into coherent final responses.
225
+ */
226
+ async trainSynthesis(dataset) {
227
+ const startTime = Date.now();
228
+ this.resetState();
229
+ const { trainSet, valSet } = this.splitDataset(dataset);
230
+ const batches = this.createBatches(trainSet);
231
+ for (let epoch = 0; epoch < this.config.epochs; epoch++) {
232
+ this.currentEpoch = epoch;
233
+ let epochLoss = 0;
234
+ for (const batch of batches) {
235
+ const batchLoss = this.trainSynthesisBatch(batch);
236
+ epochLoss += batchLoss;
237
+ this.currentStep++;
238
+ }
239
+ const avgLoss = epochLoss / batches.length;
240
+ this.lossHistory.push(avgLoss);
241
+ // Validation
242
+ const valLoss = this.validateSynthesis(valSet);
243
+ this.valLossHistory.push(valLoss);
244
+ // Early stopping
245
+ if (valLoss < this.bestValLoss) {
246
+ this.bestValLoss = valLoss;
247
+ this.patienceCounter = 0;
248
+ }
249
+ else {
250
+ this.patienceCounter++;
251
+ if (this.patienceCounter >= this.config.earlyStoppingPatience) {
252
+ break;
253
+ }
254
+ }
255
+ }
256
+ return {
257
+ phase: 'synthesis',
258
+ epochsCompleted: this.currentEpoch + 1,
259
+ totalSteps: this.currentStep,
260
+ finalLoss: this.lossHistory[this.lossHistory.length - 1] || 0,
261
+ bestValLoss: this.bestValLoss,
262
+ bestEpoch: this.findBestEpoch(),
263
+ accuracy: 0,
264
+ lossHistory: this.lossHistory,
265
+ valLossHistory: this.valLossHistory,
266
+ durationMs: Date.now() - startTime,
267
+ earlyStopped: this.patienceCounter >= this.config.earlyStoppingPatience,
268
+ };
269
+ }
270
+ /**
271
+ * Contrastive fine-tuning for agent routing
272
+ *
273
+ * Uses triplet loss and InfoNCE to improve routing accuracy.
274
+ */
275
+ async trainContrastive(pairs) {
276
+ const startTime = Date.now();
277
+ this.resetState();
278
+ if (pairs.length === 0) {
279
+ throw new Error('No contrastive pairs provided');
280
+ }
281
+ const { trainSet, valSet } = this.splitPairs(pairs);
282
+ const batches = this.createPairBatches(trainSet);
283
+ let totalCorrect = 0;
284
+ let totalExamples = 0;
285
+ for (let epoch = 0; epoch < this.config.epochs; epoch++) {
286
+ this.currentEpoch = epoch;
287
+ let epochLoss = 0;
288
+ for (const batch of batches) {
289
+ const batchLoss = this.trainContrastiveBatch(batch);
290
+ epochLoss += batchLoss;
291
+ this.currentStep++;
292
+ }
293
+ const avgLoss = epochLoss / batches.length;
294
+ this.lossHistory.push(avgLoss);
295
+ // Validation
296
+ const { loss: valLoss, correct, total } = this.validateContrastive(valSet);
297
+ this.valLossHistory.push(valLoss);
298
+ totalCorrect = correct;
299
+ totalExamples = total;
300
+ // Early stopping
301
+ if (valLoss < this.bestValLoss) {
302
+ this.bestValLoss = valLoss;
303
+ this.patienceCounter = 0;
304
+ }
305
+ else {
306
+ this.patienceCounter++;
307
+ if (this.patienceCounter >= this.config.earlyStoppingPatience) {
308
+ break;
309
+ }
310
+ }
311
+ }
312
+ return {
313
+ phase: 'contrastive',
314
+ epochsCompleted: this.currentEpoch + 1,
315
+ totalSteps: this.currentStep,
316
+ finalLoss: this.lossHistory[this.lossHistory.length - 1] || 0,
317
+ bestValLoss: this.bestValLoss,
318
+ bestEpoch: this.findBestEpoch(),
319
+ accuracy: totalExamples > 0 ? totalCorrect / totalExamples : 0,
320
+ lossHistory: this.lossHistory,
321
+ valLossHistory: this.valLossHistory,
322
+ durationMs: Date.now() - startTime,
323
+ earlyStopped: this.patienceCounter >= this.config.earlyStoppingPatience,
324
+ };
325
+ }
326
+ /**
327
+ * Evaluate trained model on test set
328
+ */
329
+ async evaluate(testSet) {
330
+ const perAgentAccuracy = {};
331
+ let decompositionCorrect = 0;
332
+ let synthesisQualitySum = 0;
333
+ let routingCorrect = 0;
334
+ let hardNegativeCorrect = 0;
335
+ let hardNegativeTotal = 0;
336
+ let totalLatency = 0;
337
+ for (const example of testSet) {
338
+ // Decomposition evaluation
339
+ if (example.decomposition.success && example.decomposition.subQueries.length > 0) {
340
+ decompositionCorrect++;
341
+ }
342
+ // Synthesis quality
343
+ synthesisQualitySum += example.qualityScore;
344
+ // Routing evaluation
345
+ for (const subQuery of example.decomposition.subQueries) {
346
+ if (subQuery.recommendedAgent) {
347
+ const predicted = this.predictAgent(subQuery.query);
348
+ const correct = predicted === subQuery.recommendedAgent;
349
+ if (correct) {
350
+ routingCorrect++;
351
+ }
352
+ // Track per-agent accuracy
353
+ if (!perAgentAccuracy[subQuery.recommendedAgent]) {
354
+ perAgentAccuracy[subQuery.recommendedAgent] = { correct: 0, total: 0 };
355
+ }
356
+ perAgentAccuracy[subQuery.recommendedAgent].total++;
357
+ if (correct) {
358
+ perAgentAccuracy[subQuery.recommendedAgent].correct++;
359
+ }
360
+ // Check hard negatives
361
+ if (this.isHardNegative(subQuery.recommendedAgent, predicted)) {
362
+ hardNegativeTotal++;
363
+ if (correct) {
364
+ hardNegativeCorrect++;
365
+ }
366
+ }
367
+ }
368
+ }
369
+ totalLatency += example.trajectory.totalLatencyMs;
370
+ }
371
+ const totalRoutingExamples = testSet.reduce((sum, ex) => sum + ex.decomposition.subQueries.filter((sq) => sq.recommendedAgent).length, 0);
372
+ const perAgentResult = {};
373
+ for (const [agent, stats] of Object.entries(perAgentAccuracy)) {
374
+ perAgentResult[agent] = stats.total > 0 ? stats.correct / stats.total : 0;
375
+ }
376
+ return {
377
+ decompositionAccuracy: testSet.length > 0 ? decompositionCorrect / testSet.length : 0,
378
+ synthesisQuality: testSet.length > 0 ? synthesisQualitySum / testSet.length : 0,
379
+ routingAccuracy: totalRoutingExamples > 0 ? routingCorrect / totalRoutingExamples : 0,
380
+ hardNegativeAccuracy: hardNegativeTotal > 0 ? hardNegativeCorrect / hardNegativeTotal : 0,
381
+ avgLatencyMs: testSet.length > 0 ? totalLatency / testSet.length : 0,
382
+ totalExamples: testSet.length,
383
+ perAgentAccuracy: perAgentResult,
384
+ };
385
+ }
386
+ /**
387
+ * Generate contrastive pairs from dataset
388
+ */
389
+ generateContrastivePairs(dataset, hardNegativeRatio = 0.3) {
390
+ const pairs = [];
391
+ const agents = Object.keys(exports.AGENT_DEFINITIONS);
392
+ for (const example of dataset) {
393
+ for (const subQuery of example.decomposition.subQueries) {
394
+ if (!subQuery.recommendedAgent)
395
+ continue;
396
+ const positiveAgent = subQuery.recommendedAgent;
397
+ for (const negativeAgent of agents) {
398
+ if (negativeAgent === positiveAgent)
399
+ continue;
400
+ const isHard = this.isHardNegative(positiveAgent, negativeAgent);
401
+ // Apply hard negative ratio
402
+ const include = isHard
403
+ ? Math.random() < hardNegativeRatio
404
+ : Math.random() < 1 - hardNegativeRatio;
405
+ if (include) {
406
+ pairs.push({
407
+ anchor: subQuery.query,
408
+ anchorEmbedding: example.queryEmbedding,
409
+ positiveAgent,
410
+ negativeAgent,
411
+ isHardNegative: isHard,
412
+ quality: example.qualityScore,
413
+ sourceId: example.id,
414
+ });
415
+ }
416
+ }
417
+ }
418
+ }
419
+ return pairs;
420
+ }
421
+ // =============================================================================
422
+ // Private Methods
423
+ // =============================================================================
424
+ resetState() {
425
+ this.currentEpoch = 0;
426
+ this.currentStep = 0;
427
+ this.bestValLoss = Infinity;
428
+ this.patienceCounter = 0;
429
+ this.lossHistory = [];
430
+ this.valLossHistory = [];
431
+ }
432
+ splitDataset(dataset) {
433
+ const valSize = Math.floor(dataset.length * this.config.validationSplit);
434
+ const shuffled = this.shuffle([...dataset]);
435
+ return {
436
+ trainSet: shuffled.slice(valSize),
437
+ valSet: shuffled.slice(0, valSize),
438
+ };
439
+ }
440
+ splitPairs(pairs) {
441
+ const valSize = Math.floor(pairs.length * this.config.validationSplit);
442
+ const shuffled = this.shuffle([...pairs]);
443
+ return {
444
+ trainSet: shuffled.slice(valSize),
445
+ valSet: shuffled.slice(0, valSize),
446
+ };
447
+ }
448
+ createBatches(dataset) {
449
+ const batches = [];
450
+ for (let i = 0; i < dataset.length; i += this.config.batchSize) {
451
+ batches.push(dataset.slice(i, i + this.config.batchSize));
452
+ }
453
+ return batches;
454
+ }
455
+ createPairBatches(pairs) {
456
+ const batches = [];
457
+ for (let i = 0; i < pairs.length; i += this.config.batchSize) {
458
+ batches.push(pairs.slice(i, i + this.config.batchSize));
459
+ }
460
+ return batches;
461
+ }
462
+ shuffle(array) {
463
+ // Fisher-Yates shuffle
464
+ for (let i = array.length - 1; i > 0; i--) {
465
+ const j = Math.floor(Math.random() * (i + 1));
466
+ [array[i], array[j]] = [array[j], array[i]];
467
+ }
468
+ return array;
469
+ }
470
+ trainDecompositionBatch(batch) {
471
+ let batchLoss = 0;
472
+ for (const example of batch) {
473
+ // Decomposition quality loss
474
+ const qualityLoss = 1 - (example.decomposition.success ? example.qualityScore : 0);
475
+ // Depth appropriateness (penalize too shallow or too deep)
476
+ const depth = example.decomposition.subQueries.length;
477
+ const idealDepth = 3;
478
+ const depthLoss = Math.abs(depth - idealDepth) / idealDepth;
479
+ // Complexity balance loss
480
+ const complexityLoss = Math.abs(example.decomposition.totalComplexity - 1) / 3;
481
+ const loss = qualityLoss * this.config.decompositionWeight * 0.6 +
482
+ depthLoss * 0.2 +
483
+ complexityLoss * 0.2;
484
+ batchLoss += loss;
485
+ }
486
+ return batchLoss / batch.length;
487
+ }
488
+ trainSynthesisBatch(batch) {
489
+ let batchLoss = 0;
490
+ for (const example of batch) {
491
+ // Sub-answer quality
492
+ const subAnswerQuality = example.subAnswers.length > 0
493
+ ? example.subAnswers.reduce((sum, a) => sum + a.quality, 0) / example.subAnswers.length
494
+ : 0;
495
+ // Final answer quality
496
+ const finalQuality = example.qualityScore;
497
+ // Coherence bonus (final should be better than parts average)
498
+ const coherenceBonus = Math.max(0, finalQuality - subAnswerQuality) * 0.5;
499
+ const loss = (1 - (subAnswerQuality * 0.4 + finalQuality * 0.4 + coherenceBonus * 0.2));
500
+ batchLoss += loss * this.config.synthesisWeight;
501
+ }
502
+ return batchLoss / batch.length;
503
+ }
504
+ trainContrastiveBatch(batch) {
505
+ let batchLoss = 0;
506
+ for (const pair of batch) {
507
+ // Triplet loss
508
+ const tripletLoss = this.computeTripletLoss(pair);
509
+ // InfoNCE loss
510
+ const infonceLoss = this.computeInfoNCELoss(pair);
511
+ batchLoss += (tripletLoss * 0.5 + infonceLoss * 0.5) * this.config.routingWeight;
512
+ }
513
+ return batchLoss / batch.length;
514
+ }
515
+ validateDecomposition(valSet) {
516
+ if (valSet.length === 0)
517
+ return 0;
518
+ let totalLoss = 0;
519
+ for (const example of valSet) {
520
+ totalLoss += 1 - example.qualityScore;
521
+ }
522
+ return totalLoss / valSet.length;
523
+ }
524
+ validateSynthesis(valSet) {
525
+ if (valSet.length === 0)
526
+ return 0;
527
+ let totalLoss = 0;
528
+ for (const example of valSet) {
529
+ totalLoss += 1 - example.qualityScore;
530
+ }
531
+ return totalLoss / valSet.length;
532
+ }
533
+ validateContrastive(valSet) {
534
+ if (valSet.length === 0)
535
+ return { loss: 0, correct: 0, total: 0 };
536
+ let totalLoss = 0;
537
+ let correct = 0;
538
+ for (const pair of valSet) {
539
+ const tripletLoss = this.computeTripletLoss(pair);
540
+ const infonceLoss = this.computeInfoNCELoss(pair);
541
+ totalLoss += tripletLoss * 0.5 + infonceLoss * 0.5;
542
+ // Check routing correctness
543
+ const posDist = this.agentDistance(pair.anchor, pair.positiveAgent);
544
+ const negDist = this.agentDistance(pair.anchor, pair.negativeAgent);
545
+ if (posDist < negDist) {
546
+ correct++;
547
+ }
548
+ }
549
+ return {
550
+ loss: totalLoss / valSet.length,
551
+ correct,
552
+ total: valSet.length,
553
+ };
554
+ }
555
+ computeTripletLoss(pair) {
556
+ const posDist = this.agentDistance(pair.anchor, pair.positiveAgent);
557
+ const negDist = this.agentDistance(pair.anchor, pair.negativeAgent);
558
+ return Math.max(0, this.config.contrastiveMargin + posDist - negDist);
559
+ }
560
+ computeInfoNCELoss(pair) {
561
+ const posSim = 1 - this.agentDistance(pair.anchor, pair.positiveAgent);
562
+ const negSim = 1 - this.agentDistance(pair.anchor, pair.negativeAgent);
563
+ const temp = this.config.infonceTemperature;
564
+ const posExp = Math.exp(posSim / temp);
565
+ const negExp = Math.exp(negSim / temp);
566
+ return -Math.log(posExp / (posExp + negExp));
567
+ }
568
+ agentDistance(query, agent) {
569
+ const queryLower = query.toLowerCase();
570
+ const agentDef = exports.AGENT_DEFINITIONS[agent];
571
+ if (!agentDef)
572
+ return 1.0;
573
+ const matches = agentDef.keywords.filter((kw) => queryLower.includes(kw)).length;
574
+ return 1.0 - Math.min(1.0, matches / agentDef.keywords.length);
575
+ }
576
+ predictAgent(query) {
577
+ let bestAgent = 'coder';
578
+ let bestScore = 0;
579
+ for (const [agent, def] of Object.entries(exports.AGENT_DEFINITIONS)) {
580
+ const queryLower = query.toLowerCase();
581
+ const matches = def.keywords.filter((kw) => queryLower.includes(kw)).length;
582
+ const score = matches / def.keywords.length;
583
+ if (score > bestScore) {
584
+ bestScore = score;
585
+ bestAgent = agent;
586
+ }
587
+ }
588
+ return bestAgent;
589
+ }
590
+ isHardNegative(agent1, agent2) {
591
+ return exports.HARD_NEGATIVE_PAIRS.some(([a, b]) => (agent1 === a && agent2 === b) || (agent1 === b && agent2 === a));
592
+ }
593
+ findBestEpoch() {
594
+ if (this.valLossHistory.length === 0)
595
+ return 0;
596
+ let bestIdx = 0;
597
+ let bestLoss = this.valLossHistory[0];
598
+ for (let i = 1; i < this.valLossHistory.length; i++) {
599
+ if (this.valLossHistory[i] < bestLoss) {
600
+ bestLoss = this.valLossHistory[i];
601
+ bestIdx = i;
602
+ }
603
+ }
604
+ return bestIdx;
605
+ }
606
+ }
607
+ exports.RlmTrainer = RlmTrainer;
608
+ // =============================================================================
609
+ // Factory Functions
610
+ // =============================================================================
611
+ /**
612
+ * Create an RLM trainer with default configuration
613
+ */
614
+ function createRlmTrainer(config) {
615
+ return new RlmTrainer(config);
616
+ }
617
+ /**
618
+ * Create an empty RLM training example
619
+ */
620
+ function createEmptyExample(query) {
621
+ return {
622
+ id: crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(36)}`,
623
+ query,
624
+ decomposition: {
625
+ subQueries: [],
626
+ strategy: 'none',
627
+ rationale: '',
628
+ totalComplexity: 0,
629
+ success: false,
630
+ },
631
+ subAnswers: [],
632
+ finalAnswer: '',
633
+ qualityScore: 0,
634
+ trajectory: {
635
+ totalLatencyMs: 0,
636
+ retries: 0,
637
+ maxParallelism: 1,
638
+ modelsUsed: [],
639
+ agentsInvoked: [],
640
+ toolsUsed: [],
641
+ attributes: {},
642
+ },
643
+ success: false,
644
+ lessons: [],
645
+ source: 'manual',
646
+ };
647
+ }
648
+ /**
649
+ * Create a sub-query
650
+ */
651
+ function createSubQuery(id, query, options = {}) {
652
+ return {
653
+ id,
654
+ query,
655
+ expectedType: 'text',
656
+ dependencies: [],
657
+ complexity: 0.5,
658
+ ...options,
659
+ };
660
+ }
661
+ /**
662
+ * Create a sub-answer
663
+ */
664
+ function createSubAnswer(subQueryId, content, agent, options = {}) {
665
+ return {
666
+ subQueryId,
667
+ content,
668
+ confidence: 0.8,
669
+ agent,
670
+ latencyMs: 0,
671
+ quality: 0.8,
672
+ success: true,
673
+ ...options,
674
+ };
675
+ }
676
+ // =============================================================================
677
+ // Exports
678
+ // =============================================================================
679
+ exports.default = RlmTrainer;
680
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhaW5pbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcmxtL3RyYWluaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7R0FRRzs7O0FBczdCSCw0Q0FFQztBQUtELGdEQTJCQztBQUtELHdDQWFDO0FBS0QsMENBZ0JDO0FBaHhCRCxnRkFBZ0Y7QUFDaEYseUJBQXlCO0FBQ3pCLGdGQUFnRjtBQUVoRjs7R0FFRztBQUNVLFFBQUEsa0JBQWtCLEdBQXNCO0lBQ25ELGVBQWUsRUFBRSxJQUFJO0lBQ3JCLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLGFBQWEsRUFBRSxJQUFJO0lBQ25CLFNBQVMsRUFBRSxFQUFFO0lBQ2IsTUFBTSxFQUFFLEVBQUU7SUFDVixpQkFBaUIsRUFBRSxHQUFHO0lBQ3RCLGtCQUFrQixFQUFFLElBQUk7SUFDeEIsbUJBQW1CLEVBQUUsR0FBRztJQUN4QixlQUFlLEVBQUUsR0FBRztJQUNwQixhQUFhLEVBQUUsR0FBRztJQUNsQixnQkFBZ0IsRUFBRSxHQUFHO0lBQ3JCLGtCQUFrQixFQUFFLENBQUM7SUFDckIsV0FBVyxFQUFFLEdBQUc7SUFDaEIscUJBQXFCLEVBQUUsQ0FBQztJQUN4QixlQUFlLEVBQUUsR0FBRztJQUNwQixJQUFJLEVBQUUsRUFBRTtDQUNULENBQUM7QUFFRjs7R0FFRztBQUNVLFFBQUEsZUFBZSxHQUFzQjtJQUNoRCxHQUFHLDBCQUFrQjtJQUNyQixNQUFNLEVBQUUsQ0FBQztJQUNULFNBQVMsRUFBRSxFQUFFO0lBQ2IsZUFBZSxFQUFFLElBQUk7SUFDckIsV0FBVyxFQUFFLElBQUk7SUFDakIsYUFBYSxFQUFFLElBQUk7SUFDbkIscUJBQXFCLEVBQUUsQ0FBQztDQUN6QixDQUFDO0FBRUY7O0dBRUc7QUFDVSxRQUFBLG1CQUFtQixHQUFzQjtJQUNwRCxHQUFHLDBCQUFrQjtJQUNyQixNQUFNLEVBQUUsRUFBRTtJQUNWLFNBQVMsRUFBRSxFQUFFO0lBQ2Is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SUFBSTtRQUNiLEdBQUcsT0FBTztLQUNYLENBQUM7QUFDSixDQUFDO0FBRUQsZ0ZBQWdGO0FBQ2hGLFVBQVU7QUFDVixnRkFBZ0Y7QUFFaEYsa0JBQWUsVUFBVSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSTE0gKFJlY3Vyc2l2ZSBMZWFybmluZyBNYWNoaW5lKSBUcmFpbmluZyBNb2R1bGVcbiAqXG4gKiBQcm92aWRlcyB0cmFpbmluZyBjYXBhYmlsaXRpZXMgZm9yIFJ1dkxUUkEgbW9kZWxzIG9uIFJMTSB0YXNrIHJvdXRpbmdcbiAqIGFuZCBkZWNvbXBvc2l0aW9uLCBpbmNsdWRpbmcgcXVlcnkgZGVjb21wb3NpdGlvbiwgYW5zd2VyIHN5bnRoZXNpcyxcbiAqIGFuZCBhZ2VudCByb3V0aW5nIG9wdGltaXphdGlvbi5cbiAqXG4gKiBAbW9kdWxlIHJsbS90cmFpbmluZ1xuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUeXBlcyBhbmQgSW50ZXJmYWNlc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBTdHJhdGVneSBmb3IgZGVjb21wb3NpbmcgYSBjb21wbGV4IHF1ZXJ5XG4gKi9cbmV4cG9ydCB0eXBlIERlY29tcG9zaXRpb25TdHJhdGVneSA9XG4gIHwgJ3NlcXVlbnRpYWwnXG4gIHwgJ3BhcmFsbGVsJ1xuICB8ICdoaWVyYXJjaGljYWwnXG4gIHwgJ2RhZy1iYXNlZCdcbiAgfCAnaXRlcmF0aXZlJ1xuICB8ICdub25lJztcblxuLyoqXG4gKiBBIHN1Yi1xdWVyeSBpbiB0aGUgZGVjb21wb3NpdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN1YlF1ZXJ5IHtcbiAgLyoqIFVuaXF1ZSBpZGVudGlmaWVyIHdpdGhpbiB0aGUgZGVjb21wb3NpdGlvbiAqL1xuICBpZDogbnVtYmVyO1xuICAvKiogVGhlIHN1Yi1xdWVyeSB0ZXh0ICovXG4gIHF1ZXJ5OiBzdHJpbmc7XG4gIC8qKiBFeHBlY3RlZCBvdXRwdXQgdHlwZSAoZS5nLiwgXCJjb2RlXCIsIFwiYW5hbHlzaXNcIiwgXCJkYXRhXCIpICovXG4gIGV4cGVjdGVkVHlwZTogc3RyaW5nO1xuICAvKiogRGVwZW5kZW5jaWVzIChJRHMgb2Ygc3ViLXF1ZXJpZXMgdGhhdCBtdXN0IGNvbXBsZXRlIGZpcnN0KSAqL1xuICBkZXBlbmRlbmNpZXM6IG51bWJlcltdO1xuICAvKiogUmVjb21tZW5kZWQgYWdlbnQgdHlwZSBmb3IgdGhpcyBzdWItcXVlcnkgKi9cbiAgcmVjb21tZW5kZWRBZ2VudD86IHN0cmluZztcbiAgLyoqIEVzdGltYXRlZCBjb21wbGV4aXR5ICgwLjAtMS4wKSAqL1xuICBjb21wbGV4aXR5OiBudW1iZXI7XG4gIC8qKiBPcHRpb25hbCBjb250ZXh0IGZyb20gcGFyZW50IHF1ZXJ5ICovXG4gIGNvbnRleHQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGVjb21wb3NpdGlvbiBvZiBhIGNvbXBsZXggcXVlcnkgaW50byBzdWItcXVlcmllc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXJ5RGVjb21wb3NpdGlvbiB7XG4gIC8qKiBTdWItcXVlcmllcyBpbiBleGVjdXRpb24gb3JkZXIgKi9cbiAgc3ViUXVlcmllczogU3ViUXVlcnlbXTtcbiAgLyoqIERlY29tcG9zaXRpb24gc3RyYXRlZ3kgdXNlZCAqL1xuICBzdHJhdGVneTogRGVjb21wb3NpdGlvblN0cmF0ZWd5O1xuICAvKiogUmVhc29uaW5nIGZvciB0aGlzIGRlY29tcG9zaXRpb24gKi9cbiAgcmF0aW9uYWxlOiBzdHJpbmc7XG4gIC8qKiBUb3RhbCBlc3RpbWF0ZWQgY29tcGxleGl0eSAqL1xuICB0b3RhbENvbXBsZXhpdHk6IG51bWJlcjtcbiAgLyoqIFdoZXRoZXIgZGVjb21wb3NpdGlvbiB3YXMgc3VjY2Vzc2Z1bCAqL1xuICBzdWNjZXNzOiBib29sZWFuO1xuICAvKiogRXJyb3IgbWVzc2FnZSBpZiBkZWNvbXBvc2l0aW9uIGZhaWxlZCAqL1xuICBlcnJvcj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBBbnN3ZXIgdG8gYSBzdWItcXVlcnlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdWJBbnN3ZXIge1xuICAvKiogSUQgb2YgdGhlIHN1Yi1xdWVyeSB0aGlzIGFuc3dlcnMgKi9cbiAgc3ViUXVlcnlJZDogbnVtYmVyO1xuICAvKiogVGhlIGFuc3dlciBjb250ZW50ICovXG4gIGNvbnRlbnQ6IHN0cmluZztcbiAgLyoqIENvbmZpZGVuY2UgaW4gdGhpcyBhbnN3ZXIgKDAuMC0xLjApICovXG4gIGNvbmZpZGVuY2U6IG51bWJlcjtcbiAgLyoqIEFnZW50IHRoYXQgcHJvZHVjZWQgdGhpcyBhbnN3ZXIgKi9cbiAgYWdlbnQ6IHN0cmluZztcbiAgLyoqIExhdGVuY3kgaW4gbWlsbGlzZWNvbmRzICovXG4gIGxhdGVuY3lNczogbnVtYmVyO1xuICAvKiogUXVhbGl0eSBzY29yZSAoMC4wLTEuMCkgKi9cbiAgcXVhbGl0eTogbnVtYmVyO1xuICAvKiogV2hldGhlciB0aGlzIGFuc3dlciB3YXMgc3VjY2Vzc2Z1bCAqL1xuICBzdWNjZXNzOiBib29sZWFuO1xuICAvKiogRXJyb3IgbWVzc2FnZSBpZiBmYWlsZWQgKi9cbiAgZXJyb3I/OiBzdHJpbmc7XG4gIC8qKiBJbnRlcm1lZGlhdGUgcmVhc29uaW5nL2NoYWluLW9mLXRob3VnaHQgKi9cbiAgcmVhc29uaW5nPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIE1ldGFkYXRhIGFib3V0IHRoZSBSTE0gZXhlY3V0aW9uIHRyYWplY3RvcnlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSbG1UcmFqZWN0b3J5TWV0YWRhdGEge1xuICAvKiogU2Vzc2lvbiBJRCAqL1xuICBzZXNzaW9uSWQ/OiBzdHJpbmc7XG4gIC8qKiBVc2VyIElEICovXG4gIHVzZXJJZD86IHN0cmluZztcbiAgLyoqIFRvdGFsIGxhdGVuY3kgaW4gbWlsbGlzZWNvbmRzICovXG4gIHRvdGFsTGF0ZW5jeU1zOiBudW1iZXI7XG4gIC8qKiBOdW1iZXIgb2YgcmV0cmllcyAqL1xuICByZXRyaWVzOiBudW1iZXI7XG4gIC8qKiBNYXhpbXVtIHBhcmFsbGVsIGJyYW5jaGVzIGV4ZWN1dGVkICovXG4gIG1heFBhcmFsbGVsaXNtOiBudW1iZXI7XG4gIC8qKiBNb2RlbHMgdXNlZCBkdXJpbmcgZXhlY3V0aW9uICovXG4gIG1vZGVsc1VzZWQ6IHN0cmluZ1tdO1xuICAvKiogQWdlbnRzIGludm9rZWQgKi9cbiAgYWdlbnRzSW52b2tlZDogc3RyaW5nW107XG4gIC8qKiBUb29scyB1c2VkICovXG4gIHRvb2xzVXNlZDogc3RyaW5nW107XG4gIC8qKiBDdXN0b20gYXR0cmlidXRlcyAqL1xuICBhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufVxuXG4vKipcbiAqIEEgY29tcGxldGUgUkxNIHRyYWluaW5nIGV4YW1wbGVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSbG1UcmFpbmluZ0V4YW1wbGUge1xuICAvKiogVW5pcXVlIGlkZW50aWZpZXIgKi9cbiAgaWQ6IHN0cmluZztcbiAgLyoqIE9yaWdpbmFsIGNvbXBsZXggcXVlcnkgKi9cbiAgcXVlcnk6IHN0cmluZztcbiAgLyoqIFF1ZXJ5IGVtYmVkZGluZyAob3B0aW9uYWwpICovXG4gIHF1ZXJ5RW1iZWRkaW5nPzogbnVtYmVyW107XG4gIC8qKiBIb3cgdGhlIHF1ZXJ5IHdhcyBkZWNvbXBvc2VkICovXG4gIGRlY29tcG9zaXRpb246IFF1ZXJ5RGVjb21wb3NpdGlvbjtcbiAgLyoqIEFuc3dlcnMgdG8gZWFjaCBzdWItcXVlcnkgKi9cbiAgc3ViQW5zd2VyczogU3ViQW5zd2VyW107XG4gIC8qKiBGaW5hbCBzeW50aGVzaXplZCBhbnN3ZXIgKi9cbiAgZmluYWxBbnN3ZXI6IHN0cmluZztcbiAgLyoqIEZpbmFsIGFuc3dlciBlbWJlZGRpbmcgKG9wdGlvbmFsKSAqL1xuICBmaW5hbEVtYmVkZGluZz86IG51bWJlcltdO1xuICAvKiogT3ZlcmFsbCBxdWFsaXR5IHNjb3JlICgwLjAtMS4wKSAqL1xuICBxdWFsaXR5U2NvcmU6IG51bWJlcjtcbiAgLyoqIEV4ZWN1dGlvbiB0cmFqZWN0b3J5IG1ldGFkYXRhICovXG4gIHRyYWplY3Rvcnk6IFJsbVRyYWplY3RvcnlNZXRhZGF0YTtcbiAgLyoqIFdoZXRoZXIgdGhpcyBleGFtcGxlIHdhcyBzdWNjZXNzZnVsICovXG4gIHN1Y2Nlc3M6IGJvb2xlYW47XG4gIC8qKiBMZXNzb25zIGxlYXJuZWQgZnJvbSB0aGlzIGV4YW1wbGUgKi9cbiAgbGVzc29uczogc3RyaW5nW107XG4gIC8qKiBTb3VyY2Ugb2YgdGhpcyBleGFtcGxlICovXG4gIHNvdXJjZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgY29udHJhc3RpdmUgcGFpciBmb3IgYWdlbnQgcm91dGluZyB0cmFpbmluZ1xuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRyYXN0aXZlUGFpciB7XG4gIC8qKiBBbmNob3IgcXVlcnkgKi9cbiAgYW5jaG9yOiBzdHJpbmc7XG4gIC8qKiBBbmNob3IgZW1iZWRkaW5nIChvcHRpb25hbCkgKi9cbiAgYW5jaG9yRW1iZWRkaW5nPzogbnVtYmVyW107XG4gIC8qKiBQb3NpdGl2ZSBhZ2VudCAoY29ycmVjdCByb3V0aW5nKSAqL1xuICBwb3NpdGl2ZUFnZW50OiBzdHJpbmc7XG4gIC8qKiBOZWdhdGl2ZSBhZ2VudCAoaW5jb3JyZWN0IHJvdXRpbmcpICovXG4gIG5lZ2F0aXZlQWdlbnQ6IHN0cmluZztcbiAgLyoqIFdoZXRoZXIgdGhpcyBpcyBhIGhhcmQgbmVnYXRpdmUgKi9cbiAgaXNIYXJkTmVnYXRpdmU6IGJvb2xlYW47XG4gIC8qKiBRdWFsaXR5IHNjb3JlIG9mIHRoZSBhbmNob3IgZXhhbXBsZSAqL1xuICBxdWFsaXR5OiBudW1iZXI7XG4gIC8qKiBTb3VyY2UgZXhhbXBsZSBJRCAqL1xuICBzb3VyY2VJZDogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIFJMTSB0cmFpbmluZ1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFJsbVRyYWluaW5nQ29uZmlnIHtcbiAgLyoqIExlYXJuaW5nIHJhdGUgZm9yIGRlY29tcG9zaXRpb24gdHJhaW5pbmcgKi9cbiAgZGVjb21wb3NpdGlvbkxyOiBudW1iZXI7XG4gIC8qKiBMZWFybmluZyByYXRlIGZvciBzeW50aGVzaXMgdHJhaW5pbmcgKi9cbiAgc3ludGhlc2lzTHI6IG51bWJlcjtcbiAgLyoqIExlYXJuaW5nIHJhdGUgZm9yIGNvbnRyYXN0aXZlIGZpbmUtdHVuaW5nICovXG4gIGNvbnRyYXN0aXZlTHI6IG51bWJlcjtcbiAgLyoqIEJhdGNoIHNpemUgKi9cbiAgYmF0Y2hTaXplOiBudW1iZXI7XG4gIC8qKiBOdW1iZXIgb2YgZXBvY2hzICovXG4gIGVwb2NoczogbnVtYmVyO1xuICAvKiogQ29udHJhc3RpdmUgbWFyZ2luIGZvciB0cmlwbGV0IGxvc3MgKi9cbiAgY29udHJhc3RpdmVNYXJnaW46IG51bWJlcjtcbiAgLyoqIFRlbXBlcmF0dXJlIGZvciBJbmZvTkNFIGxvc3MgKi9cbiAgaW5mb25jZVRlbXBlcmF0dXJlOiBudW1iZXI7XG4gIC8qKiBXZWlnaHQgZm9yIGRlY29tcG9zaXRpb24gbG9zcyAqL1xuICBkZWNvbXBvc2l0aW9uV2VpZ2h0OiBudW1iZXI7XG4gIC8qKiBXZWlnaHQgZm9yIHN5bnRoZXNpcyBsb3NzICovXG4gIHN5bnRoZXNpc1dlaWdodDogbnVtYmVyO1xuICAvKiogV2VpZ2h0IGZvciByb3V0aW5nIGxvc3MgKi9cbiAgcm91dGluZ1dlaWdodDogbnVtYmVyO1xuICAvKiogTWluaW11bSBxdWFsaXR5IGZvciB1cGRhdGVzICovXG4gIHF1YWxpdHlUaHJlc2hvbGQ6IG51bWJlcjtcbiAgLyoqIEV2YWx1YXRpb24gaW50ZXJ2YWwgKGVwb2NocykgKi9cbiAgZXZhbHVhdGlvbkludGVydmFsOiBudW1iZXI7XG4gIC8qKiBXYXJtdXAgc3RlcHMgKi9cbiAgd2FybXVwU3RlcHM6IG51bWJlcjtcbiAgLyoqIEVhcmx5IHN0b3BwaW5nIHBhdGllbmNlICovXG4gIGVhcmx5U3RvcHBpbmdQYXRpZW5jZTogbnVtYmVyO1xuICAvKiogVmFsaWRhdGlvbiBzcGxpdCByYXRpbyAqL1xuICB2YWxpZGF0aW9uU3BsaXQ6IG51bWJlcjtcbiAgLyoqIFJhbmRvbSBzZWVkICovXG4gIHNlZWQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUcmFpbmluZyByZXN1bHQgZm9yIGEgcGhhc2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUcmFpbmluZ1Jlc3VsdCB7XG4gIC8qKiBUcmFpbmluZyBwaGFzZSBuYW1lICovXG4gIHBoYXNlOiBzdHJpbmc7XG4gIC8qKiBFcG9jaHMgY29tcGxldGVkICovXG4gIGVwb2Noc0NvbXBsZXRlZDogbnVtYmVyO1xuICAvKiogVG90YWwgc3RlcHMgKi9cbiAgdG90YWxTdGVwczogbnVtYmVyO1xuICAvKiogRmluYWwgdHJhaW5pbmcgbG9zcyAqL1xuICBmaW5hbExvc3M6IG51bWJlcjtcbiAgLyoqIEJlc3QgdmFsaWRhdGlvbiBsb3NzICovXG4gIGJlc3RWYWxMb3NzOiBudW1iZXI7XG4gIC8qKiBCZXN0IGVwb2NoICovXG4gIGJlc3RFcG9jaDogbnVtYmVyO1xuICAvKiogRmluYWwgYWNjdXJhY3kgKGZvciBjbGFzc2lmaWNhdGlvbiB0YXNrcykgKi9cbiAgYWNjdXJhY3k6IG51bWJlcjtcbiAgLyoqIExvc3MgaGlzdG9yeSBwZXIgZXBvY2ggKi9cbiAgbG9zc0hpc3Rvcnk6IG51bWJlcltdO1xuICAvKiogVmFsaWRhdGlvbiBsb3NzIGhpc3RvcnkgKi9cbiAgdmFsTG9zc0hpc3Rvcnk6IG51bWJlcltdO1xuICAvKiogVHJhaW5pbmcgZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzICovXG4gIGR1cmF0aW9uTXM6IG51bWJlcjtcbiAgLyoqIFdoZXRoZXIgZWFybHkgc3RvcHBpbmcgd2FzIHRyaWdnZXJlZCAqL1xuICBlYXJseVN0b3BwZWQ6IGJvb2xlYW47XG59XG5cbi8qKlxuICogRXZhbHVhdGlvbiByZXN1bHQgZm9yIHRoZSB0cmFpbmVkIG1vZGVsXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRXZhbHVhdGlvblJlc3VsdCB7XG4gIC8qKiBEZWNvbXBvc2l0aW9uIGFjY3VyYWN5ICovXG4gIGRlY29tcG9zaXRpb25BY2N1cmFjeTogbnVtYmVyO1xuICAvKiogU3ludGhlc2lzIHF1YWxpdHkgKi9cbiAgc3ludGhlc2lzUXVhbGl0eTogbnVtYmVyO1xuICAvKiogUm91dGluZyBhY2N1cmFjeSAqL1xuICByb3V0aW5nQWNjdXJhY3k6IG51bWJlcjtcbiAgLyoqIEhhcmQgbmVnYXRpdmUgYWNjdXJhY3kgKi9cbiAgaGFyZE5lZ2F0aXZlQWNjdXJhY3k6IG51bWJlcjtcbiAgLyoqIEF2ZXJhZ2UgbGF0ZW5jeSBpbiBtcyAqL1xuICBhdmdMYXRlbmN5TXM6IG51bWJlcjtcbiAgLyoqIFRvdGFsIGV4YW1wbGVzIGV2YWx1YXRlZCAqL1xuICB0b3RhbEV4YW1wbGVzOiBudW1iZXI7XG4gIC8qKiBQZXItYWdlbnQgYWNjdXJhY3kgKi9cbiAgcGVyQWdlbnRBY2N1cmFjeTogUmVjb3JkPHN0cmluZywgbnVtYmVyPjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERlZmF1bHQgQ29uZmlndXJhdGlvbnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogRGVmYXVsdCBSTE0gdHJhaW5pbmcgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9STE1fQ09ORklHOiBSbG1UcmFpbmluZ0NvbmZpZyA9IHtcbiAgZGVjb21wb3NpdGlvbkxyOiAxZS01LFxuICBzeW50aGVzaXNMcjogMWUtNSxcbiAgY29udHJhc3RpdmVMcjogMmUtNSxcbiAgYmF0Y2hTaXplOiAzMixcbiAgZXBvY2hzOiAxMCxcbiAgY29udHJhc3RpdmVNYXJnaW46IDAuNSxcbiAgaW5mb25jZVRlbXBlcmF0dXJlOiAwLjA3LFxuICBkZWNvbXBvc2l0aW9uV2VpZ2h0OiAxLjAsXG4gIHN5bnRoZXNpc1dlaWdodDogMS4wLFxuICByb3V0aW5nV2VpZ2h0OiAxLjAsXG4gIHF1YWxpdHlUaHJlc2hvbGQ6IDAuNyxcbiAgZXZhbHVhdGlvbkludGVydmFsOiAxLFxuICB3YXJtdXBTdGVwczogMTAwLFxuICBlYXJseVN0b3BwaW5nUGF0aWVuY2U6IDMsXG4gIHZhbGlkYXRpb25TcGxpdDogMC4xLFxuICBzZWVkOiA0Mixcbn07XG5cbi8qKlxuICogRmFzdCB0cmFpbmluZyBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBGQVNUX1JMTV9DT05GSUc6IFJsbVRyYWluaW5nQ29uZmlnID0ge1xuICAuLi5ERUZBVUxUX1JMTV9DT05GSUcsXG4gIGVwb2NoczogMyxcbiAgYmF0Y2hTaXplOiA2NCxcbiAgZGVjb21wb3NpdGlvbkxyOiAxZS00LFxuICBzeW50aGVzaXNMcjogMWUtNCxcbiAgY29udHJhc3RpdmVMcjogNWUtNSxcbiAgZWFybHlTdG9wcGluZ1BhdGllbmNlOiAxLFxufTtcblxuLyoqXG4gKiBUaG9yb3VnaCB0cmFpbmluZyBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBUSE9ST1VHSF9STE1fQ09ORklHOiBSbG1UcmFpbmluZ0NvbmZpZyA9IHtcbiAgLi4uREVGQVVMVF9STE1fQ09ORklHLFxuICBlcG9jaHM6IDUwLFxuICBiYXRjaFNpemU6IDE2LFxuICBkZWNvbXBvc2l0aW9uTHI6IDVlLTYsXG4gIHN5bnRoZXNpc0xyOiA1ZS02LFxuICBjb250cmFzdGl2ZUxyOiAxZS01LFxuICBlYXJseVN0b3BwaW5nUGF0aWVuY2U6IDEwLFxufTtcblxuLyoqXG4gKiBSb3V0aW5nLWZvY3VzZWQgdHJhaW5pbmcgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgY29uc3QgUk9VVElOR19GT0NVU0VEX0NPTkZJRzogUmxtVHJhaW5pbmdDb25maWcgPSB7XG4gIC4uLkRFRkFVTFRfUkxNX0NPTkZJRyxcbiAgcm91dGluZ1dlaWdodDogMi4wLFxuICBkZWNvbXBvc2l0aW9uV2VpZ2h0OiAwLjUsXG4gIHN5bnRoZXNpc1dlaWdodDogMC41LFxuICBjb250cmFzdGl2ZUxyOiAzZS01LFxuICBjb250cmFzdGl2ZU1hcmdpbjogMC4zLFxuICBpbmZvbmNlVGVtcGVyYXR1cmU6IDAuMDUsXG59O1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQWdlbnQgRGVmaW5pdGlvbnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogQWdlbnQgdHlwZXMgd2l0aCBkZXNjcmlwdGlvbnMgYW5kIGtleXdvcmRzXG4gKi9cbmV4cG9ydCBjb25zdCBBR0VOVF9ERUZJTklUSU9OUzogUmVjb3JkPHN0cmluZywgeyBkZXNjcmlwdGlvbjogc3RyaW5nOyBrZXl3b3Jkczogc3RyaW5nW10gfT4gPSB7XG4gIGNvZGVyOiB7XG4gICAgZGVzY3JpcHRpb246ICdTb2Z0d2FyZSBkZXZlbG9wZXIgd2hvIHdyaXRlcyBhbmQgaW1wbGVtZW50cyBjb2RlJyxcbiAgICBrZXl3b3JkczogWydpbXBsZW1lbnQnLCAnYnVpbGQnLCAnY3JlYXRlJywgJ2NvZGUnLCAnd3JpdGUnLCAnZGV2ZWxvcCcsICdwcm9ncmFtJ10sXG4gIH0sXG4gIHJlc2VhcmNoZXI6IHtcbiAgICBkZXNjcmlwdGlvbjogJ1RlY2huaWNhbCByZXNlYXJjaGVyIHdobyBpbnZlc3RpZ2F0ZXMgYW5kIGFuYWx5emVzJyxcbiAgICBrZXl3b3JkczogWydyZXNlYXJjaCcsICdpbnZlc3RpZ2F0ZScsICdhbmFseXplJywgJ2V4cGxvcmUnLCAnc3R1ZHknLCAnZXhhbWluZSddLFxuICB9LFxuICByZXZpZXdlcjoge1xuICAgIGRlc2NyaXB0aW9uOiAnQ29kZSByZXZpZXdlciB3aG8gZXZhbHVhdGVzIGNvZGUgcXVhbGl0eScsXG4gICAga2V5d29yZHM6IFsncmV2aWV3JywgJ2NoZWNrJywgJ2V2YWx1YXRlJywgJ2Fzc2VzcycsICdleGFtaW5lJywgJ2luc3BlY3QnXSxcbiAgfSxcbiAgdGVzdGVyOiB7XG4gICAgZGVzY3JpcHRpb246ICdRQSBlbmdpbmVlciB3aG8gd3JpdGVzIGFuZCBydW5zIHRlc3RzJyxcbiAgICBrZXl3b3JkczogWyd0ZXN0JywgJ3VuaXQgdGVzdCcsICdjb3ZlcmFnZScsICd2YWxpZGF0ZScsICd2ZXJpZnknLCAncWEnXSxcbiAgfSxcbiAgYXJjaGl0ZWN0OiB7XG4gICAgZGVzY3JpcHRpb246ICdTeXN0ZW0gYXJjaGl0ZWN0IHdobyBkZXNpZ25zIHNvZnR3YXJlIHN0cnVjdHVyZScsXG4gICAga2V5d29yZHM6IFsnZGVzaWduJywgJ3BsYW4nLCAnYXJjaGl0ZWN0dXJlJywgJ3NjaGVtYScsICdzdHJ1Y3R1cmUnLCAnZGlhZ3JhbSddLFxuICB9LFxuICAnc2VjdXJpdHktYXJjaGl0ZWN0Jzoge1xuICAgIGRlc2NyaXB0aW9uOiAnU2VjdXJpdHkgc3BlY2lhbGlzdCB3aG8gYXVkaXRzIHZ1bG5lcmFiaWxpdGllcycsXG4gICAga2V5d29yZHM6IFsnc2VjdXJpdHknLCAnYXVkaXQnLCAndnVsbmVyYWJpbGl0eScsICd4c3MnLCAnaW5qZWN0aW9uJywgJ2N2ZSddLFxuICB9LFxuICBkZWJ1Z2dlcjoge1xuICAgIGRlc2NyaXB0aW9uOiAnQnVnIGh1bnRlciB3aG8gZml4ZXMgZXJyb3JzIGFuZCB0cmFjZXMgaXNzdWVzJyxcbiAgICBrZXl3b3JkczogWydmaXgnLCAnZGVidWcnLCAnYnVnJywgJ2Vycm9yJywgJ3RyYWNlJywgJ2NyYXNoJywgJ3Ryb3VibGVzaG9vdCddLFxuICB9LFxuICBkb2N1bWVudGVyOiB7XG4gICAgZGVzY3JpcHRpb246ICdUZWNobmljYWwgd3JpdGVyIHdobyBjcmVhdGVzIGRvY3VtZW50YXRpb24nLFxuICAgIGtleXdvcmRzOiBbJ2RvY3VtZW50JywgJ2pzZG9jJywgJ3JlYWRtZScsICdjb21tZW50JywgJ2V4cGxhaW4nLCAnZGVzY3JpYmUnXSxcbiAgfSxcbiAgcmVmYWN0b3Jlcjoge1xuICAgIGRlc2NyaXB0aW9uOiAnQ29kZSBtb2Rlcm5pemVyIHdobyByZXN0cnVjdHVyZXMgd2l0aG91dCBjaGFuZ2luZyBiZWhhdmlvcicsXG4gICAga2V5d29yZHM6IFsncmVmYWN0b3InLCAncmVzdHJ1Y3R1cmUnLCAnbW9kZXJuaXplJywgJ2NsZWFuJywgJ3NpbXBsaWZ5JywgJ2NvbnNvbGlkYXRlJ10sXG4gIH0sXG4gIG9wdGltaXplcjoge1xuICAgIGRlc2NyaXB0aW9uOiAnUGVyZm9ybWFuY2UgZW5naW5lZXIgd2hvIHNwZWVkcyB1cCBzbG93IGNvZGUnLFxuICAgIGtleXdvcmRzOiBbJ29wdGltaXplJywgJ3BlcmZvcm1hbmNlJywgJ3NwZWVkJywgJ2NhY2hlJywgJ2ltcHJvdmUnLCAnZmFzdGVyJ10sXG4gIH0sXG4gIGRldm9wczoge1xuICAgIGRlc2NyaXB0aW9uOiAnRGV2T3BzIGVuZ2luZWVyIHdobyBtYW5hZ2VzIGRlcGxveW1lbnQgYW5kIGluZnJhc3RydWN0dXJlJyxcbiAgICBrZXl3b3JkczogWydkZXBsb3knLCAnY2kvY2QnLCAna3ViZXJuZXRlcycsICdkb2NrZXInLCAnaW5mcmFzdHJ1Y3R1cmUnLCAncGlwZWxpbmUnXSxcbiAgfSxcbiAgJ2FwaS1kb2NzJzoge1xuICAgIGRlc2NyaXB0aW9uOiAnQVBJIGRvY3VtZW50YXRpb24gc3BlY2lhbGlzdCB3aG8gY3JlYXRlcyBzcGVjcycsXG4gICAga2V5d29yZHM6IFsnb3BlbmFwaScsICdzd2FnZ2VyJywgJ2FwaSByZWZlcmVuY2UnLCAnZW5kcG9pbnQnLCAnc3BlYycsICdyZXN0J10sXG4gIH0sXG4gIHBsYW5uZXI6IHtcbiAgICBkZXNjcmlwdGlvbjogJ1Byb2plY3QgcGxhbm5lciB3aG8gb3JnYW5pemVzIGFuZCBzY2hlZHVsZXMgd29yaycsXG4gICAga2V5d29yZHM6IFsncGxhbicsICdlc3RpbWF0ZScsICdzY2hlZHVsZScsICd0aW1lbGluZScsICdzcHJpbnQnLCAncm9hZG1hcCddLFxuICB9LFxufTtcblxuLyoqXG4gKiBIYXJkIG5lZ2F0aXZlIHBhaXJzIChjb25mdXNhYmxlIGFnZW50IGNvbWJpbmF0aW9ucylcbiAqL1xuZXhwb3J0IGNvbnN0IEhBUkRfTkVHQVRJVkVfUEFJUlM6IFtzdHJpbmcsIHN0cmluZ11bXSA9IFtcbiAgWydjb2RlcicsICdkZWJ1Z2dlciddLFxuICBbJ2NvZGVyJywgJ3JlZmFjdG9yZXInXSxcbiAgWydyZXNlYXJjaGVyJywgJ3Jldmlld2VyJ10sXG4gIFsndGVzdGVyJywgJ3Jldmlld2VyJ10sXG4gIFsnYXJjaGl0ZWN0JywgJ3BsYW5uZXInXSxcbiAgWydkb2N1bWVudGVyJywgJ2FwaS1kb2NzJ10sXG4gIFsnb3B0aW1pemVyJywgJ2RlYnVnZ2VyJ10sXG4gIFsnZGV2b3BzJywgJ2FyY2hpdGVjdCddLFxuICBbJ3NlY3VyaXR5LWFyY2hpdGVjdCcsICdyZXZpZXdlciddLFxuXTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFJMTSBUcmFpbmVyIENsYXNzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFJMTSBUcmFpbmVyIGZvciBSdXZMVFJBIG1vZGVsc1xuICpcbiAqIFByb3ZpZGVzIHRyYWluaW5nIGNhcGFiaWxpdGllcyBmb3IgZGVjb21wb3NpdGlvbiwgc3ludGhlc2lzLCBhbmQgcm91dGluZyB0YXNrcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFJsbVRyYWluZXIge1xuICBwcml2YXRlIGNvbmZpZzogUmxtVHJhaW5pbmdDb25maWc7XG4gIHByaXZhdGUgY3VycmVudEVwb2NoID0gMDtcbiAgcHJpdmF0ZSBjdXJyZW50U3RlcCA9IDA7XG4gIHByaXZhdGUgYmVzdFZhbExvc3MgPSBJbmZpbml0eTtcbiAgcHJpdmF0ZSBwYXRpZW5jZUNvdW50ZXIgPSAwO1xuICBwcml2YXRlIGxvc3NIaXN0b3J5OiBudW1iZXJbXSA9IFtdO1xuICBwcml2YXRlIHZhbExvc3NIaXN0b3J5OiBudW1iZXJbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgUkxNIHRyYWluZXJcbiAgICovXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogUGFydGlhbDxSbG1UcmFpbmluZ0NvbmZpZz4gPSB7fSkge1xuICAgIHRoaXMuY29uZmlnID0geyAuLi5ERUZBVUxUX1JMTV9DT05GSUcsIC4uLmNvbmZpZyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYWluIG9uIGRlY29tcG9zaXRpb24gdGFza1xuICAgKlxuICAgKiBMZWFybnMgdG8gYnJlYWsgY29tcGxleCBxdWVyaWVzIGludG8gbWFuYWdlYWJsZSBzdWItcXVlcmllcy5cbiAgICovXG4gIGFzeW5jIHRyYWluRGVjb21wb3NpdGlvbihkYXRhc2V0OiBSbG1UcmFpbmluZ0V4YW1wbGVbXSk6IFByb21pc2U8VHJhaW5pbmdSZXN1bHQ+IHtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIHRoaXMucmVzZXRTdGF0ZSgpO1xuXG4gICAgY29uc3QgeyB0cmFpblNldCwgdmFsU2V0IH0gPSB0aGlzLnNwbGl0RGF0YXNldChkYXRhc2V0KTtcbiAgICBjb25zdCBiYXRjaGVzID0gdGhpcy5jcmVhdGVCYXRjaGVzKHRyYWluU2V0KTtcblxuICAgIGZvciAobGV0IGVwb2NoID0gMDsgZXBvY2ggPCB0aGlzLmNvbmZpZy5lcG9jaHM7IGVwb2NoKyspIHtcbiAgICAgIHRoaXMuY3VycmVudEVwb2NoID0gZXBvY2g7XG4gICAgICBsZXQgZXBvY2hMb3NzID0gMDtcblxuICAgICAgZm9yIChjb25zdCBiYXRjaCBvZiBiYXRjaGVzKSB7XG4gICAgICAgIGNvbnN0IGJhdGNoTG9zcyA9IHRoaXMudHJhaW5EZWNvbXBvc2l0aW9uQmF0Y2goYmF0Y2gpO1xuICAgICAgICBlcG9jaExvc3MgKz0gYmF0Y2hMb3NzO1xuICAgICAgICB0aGlzLmN1cnJlbnRTdGVwKys7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGF2Z0xvc3MgPSBlcG9jaExvc3MgLyBiYXRjaGVzLmxlbmd0aDtcbiAgICAgIHRoaXMubG9zc0hpc3RvcnkucHVzaChhdmdMb3NzKTtcblxuICAgICAgLy8gVmFsaWRhdGlvblxuICAgICAgY29uc3QgdmFsTG9zcyA9IHRoaXMudmFsaWRhdGVEZWNvbXBvc2l0aW9uKHZhbFNldCk7XG4gICAgICB0aGlzLnZhbExvc3NIaXN0b3J5LnB1c2godmFsTG9zcyk7XG5cbiAgICAgIC8vIEVhcmx5IHN0b3BwaW5nXG4gICAgICBpZiAodmFsTG9zcyA8IHRoaXMuYmVzdFZhbExvc3MpIHtcbiAgICAgICAgdGhpcy5iZXN0VmFsTG9zcyA9IHZhbExvc3M7XG4gICAgICAgIHRoaXMucGF0aWVuY2VDb3VudGVyID0gMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucGF0aWVuY2VDb3VudGVyKys7XG4gICAgICAgIGlmICh0aGlzLnBhdGllbmNlQ291bnRlciA+PSB0aGlzLmNvbmZpZy5lYXJseVN0b3BwaW5nUGF0aWVuY2UpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBwaGFzZTogJ2RlY29tcG9zaXRpb24nLFxuICAgICAgZXBvY2hzQ29tcGxldGVkOiB0aGlzLmN1cnJlbnRFcG9jaCArIDEsXG4gICAgICB0b3RhbFN0ZXBzOiB0aGlzLmN1cnJlbnRTdGVwLFxuICAgICAgZmluYWxMb3NzOiB0aGlzLmxvc3NIaXN0b3J5W3RoaXMubG9zc0hpc3RvcnkubGVuZ3RoIC0gMV0gfHwgMCxcbiAgICAgIGJlc3RWYWxMb3NzOiB0aGlzLmJlc3RWYWxMb3NzLFxuICAgICAgYmVzdEVwb2NoOiB0aGlzLmZpbmRCZXN0RXBvY2goKSxcbiAgICAgIGFjY3VyYWN5OiAwLCAvLyBOb3QgYXBwbGljYWJsZSBmb3IgZGVjb21wb3NpdGlvblxuICAgICAgbG9zc0hpc3Rvcnk6IHRoaXMubG9zc0hpc3RvcnksXG4gICAgICB2YWxMb3NzSGlzdG9yeTogdGhpcy52YWxMb3NzSGlzdG9yeSxcbiAgICAgIGR1cmF0aW9uTXM6IERhdGUubm93KCkgLSBzdGFydFRpbWUsXG4gICAgICBlYXJseVN0b3BwZWQ6IHRoaXMucGF0aWVuY2VDb3VudGVyID49IHRoaXMuY29uZmlnLmVhcmx5U3RvcHBpbmdQYXRpZW5jZSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYWluIG9uIHN5bnRoZXNpcyB0YXNrXG4gICAqXG4gICAqIExlYXJucyB0byBjb21iaW5lIHN1Yi1hbnN3ZXJzIGludG8gY29oZXJlbnQgZmluYWwgcmVzcG9uc2VzLlxuICAgKi9cbiAgYXN5bmMgdHJhaW5TeW50aGVzaXMoZGF0YXNldDogUmxtVHJhaW5pbmdFeGFtcGxlW10pOiBQcm9taXNlPFRyYWluaW5nUmVzdWx0PiB7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICB0aGlzLnJlc2V0U3RhdGUoKTtcblxuICAgIGNvbnN0IHsgdHJhaW5TZXQsIHZhbFNldCB9ID0gdGhpcy5zcGxpdERhdGFzZXQoZGF0YXNldCk7XG4gICAgY29uc3QgYmF0Y2hlcyA9IHRoaXMuY3JlYXRlQmF0Y2hlcyh0cmFpblNldCk7XG5cbiAgICBmb3IgKGxldCBlcG9jaCA9IDA7IGVwb2NoIDwgdGhpcy5jb25maWcuZXBvY2hzOyBlcG9jaCsrKSB7XG4gICAgICB0aGlzLmN1cnJlbnRFcG9jaCA9IGVwb2NoO1xuICAgICAgbGV0IGVwb2NoTG9zcyA9IDA7XG5cbiAgICAgIGZvciAoY29uc3QgYmF0Y2ggb2YgYmF0Y2hlcykge1xuICAgICAgICBjb25zdCBiYXRjaExvc3MgPSB0aGlzLnRyYWluU3ludGhlc2lzQmF0Y2goYmF0Y2gpO1xuICAgICAgICBlcG9jaExvc3MgKz0gYmF0Y2hMb3NzO1xuICAgICAgICB0aGlzLmN1cnJlbnRTdGVwKys7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGF2Z0xvc3MgPSBlcG9jaExvc3MgLyBiYXRjaGVzLmxlbmd0aDtcbiAgICAgIHRoaXMubG9zc0hpc3RvcnkucHVzaChhdmdMb3NzKTtcblxuICAgICAgLy8gVmFsaWRhdGlvblxuICAgICAgY29uc3QgdmFsTG9zcyA9IHRoaXMudmFsaWRhdGVTeW50aGVzaXModmFsU2V0KTtcbiAgICAgIHRoaXMudmFsTG9zc0hpc3RvcnkucHVzaCh2YWxMb3NzKTtcblxuICAgICAgLy8gRWFybHkgc3RvcHBpbmdcbiAgICAgIGlmICh2YWxMb3NzIDwgdGhpcy5iZXN0VmFsTG9zcykge1xuICAgICAgICB0aGlzLmJlc3RWYWxMb3NzID0gdmFsTG9zcztcbiAgICAgICAgdGhpcy5wYXRpZW5jZUNvdW50ZXIgPSAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5wYXRpZW5jZUNvdW50ZXIrKztcbiAgICAgICAgaWYgKHRoaXMucGF0aWVuY2VDb3VudGVyID49IHRoaXMuY29uZmlnLmVhcmx5U3RvcHBpbmdQYXRpZW5jZSkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHBoYXNlOiAnc3ludGhlc2lzJyxcbiAgICAgIGVwb2Noc0NvbXBsZXRlZDogdGhpcy5jdXJyZW50RXBvY2ggKyAxLFxuICAgICAgdG90YWxTdGVwczogdGhpcy5jdXJyZW50U3RlcCxcbiAgICAgIGZpbmFsTG9zczogdGhpcy5sb3NzSGlzdG9yeVt0aGlzLmxvc3NIaXN0b3J5Lmxlbmd0aCAtIDFdIHx8IDAsXG4gICAgICBiZXN0VmFsTG9zczogdGhpcy5iZXN0VmFsTG9zcyxcbiAgICAgIGJlc3RFcG9jaDogdGhpcy5maW5kQmVzdEVwb2NoKCksXG4gICAgICBhY2N1cmFjeTogMCxcbiAgICAgIGxvc3NIaXN0b3J5OiB0aGlzLmxvc3NIaXN0b3J5LFxuICAgICAgdmFsTG9zc0hpc3Rvcnk6IHRoaXMudmFsTG9zc0hpc3RvcnksXG4gICAgICBkdXJhdGlvbk1zOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lLFxuICAgICAgZWFybHlTdG9wcGVkOiB0aGlzLnBhdGllbmNlQ291bnRlciA+PSB0aGlzLmNvbmZpZy5lYXJseVN0b3BwaW5nUGF0aWVuY2UsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb250cmFzdGl2ZSBmaW5lLXR1bmluZyBmb3IgYWdlbnQgcm91dGluZ1xuICAgKlxuICAgKiBVc2VzIHRyaXBsZXQgbG9zcyBhbmQgSW5mb05DRSB0byBpbXByb3ZlIHJvdXRpbmcgYWNjdXJhY3kuXG4gICAqL1xuICBhc3luYyB0cmFpbkNvbnRyYXN0aXZlKHBhaXJzOiBDb250cmFzdGl2ZVBhaXJbXSk6IFByb21pc2U8VHJhaW5pbmdSZXN1bHQ+IHtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIHRoaXMucmVzZXRTdGF0ZSgpO1xuXG4gICAgaWYgKHBhaXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjb250cmFzdGl2ZSBwYWlycyBwcm92aWRlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgdHJhaW5TZXQsIHZhbFNldCB9ID0gdGhpcy5zcGxpdFBhaXJzKHBhaXJzKTtcbiAgICBjb25zdCBiYXRjaGVzID0gdGhpcy5jcmVhdGVQYWlyQmF0Y2hlcyh0cmFpblNldCk7XG4gICAgbGV0IHRvdGFsQ29ycmVjdCA9IDA7XG4gICAgbGV0IHRvdGFsRXhhbXBsZXMgPSAwO1xuXG4gICAgZm9yIChsZXQgZXBvY2ggPSAwOyBlcG9jaCA8IHRoaXMuY29uZmlnLmVwb2NoczsgZXBvY2grKykge1xuICAgICAgdGhpcy5jdXJyZW50RXBvY2ggPSBlcG9jaDtcbiAgICAgIGxldCBlcG9jaExvc3MgPSAwO1xuXG4gICAgICBmb3IgKGNvbnN0IGJhdGNoIG9mIGJhdGNoZXMpIHtcbiAgICAgICAgY29uc3QgYmF0Y2hMb3NzID0gdGhpcy50cmFpbkNvbnRyYXN0aXZlQmF0Y2goYmF0Y2gpO1xuICAgICAgICBlcG9jaExvc3MgKz0gYmF0Y2hMb3NzO1xuICAgICAgICB0aGlzLmN1cnJlbnRTdGVwKys7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGF2Z0xvc3MgPSBlcG9jaExvc3MgLyBiYXRjaGVzLmxlbmd0aDtcbiAgICAgIHRoaXMubG9zc0hpc3RvcnkucHVzaChhdmdMb3NzKTtcblxuICAgICAgLy8gVmFsaWRhdGlvblxuICAgICAgY29uc3QgeyBsb3NzOiB2YWxMb3NzLCBjb3JyZWN0LCB0b3RhbCB9ID0gdGhpcy52YWxpZGF0ZUNvbnRyYXN0aXZlKHZhbFNldCk7XG4gICAgICB0aGlzLnZhbExvc3NIaXN0b3J5LnB1c2godmFsTG9zcyk7XG4gICAgICB0b3RhbENvcnJlY3QgPSBjb3JyZWN0O1xuICAgICAgdG90YWxFeGFtcGxlcyA9IHRvdGFsO1xuXG4gICAgICAvLyBFYXJseSBzdG9wcGluZ1xuICAgICAgaWYgKHZhbExvc3MgPCB0aGlzLmJlc3RWYWxMb3NzKSB7XG4gICAgICAgIHRoaXMuYmVzdFZhbExvc3MgPSB2YWxMb3NzO1xuICAgICAgICB0aGlzLnBhdGllbmNlQ291bnRlciA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnBhdGllbmNlQ291bnRlcisrO1xuICAgICAgICBpZiAodGhpcy5wYXRpZW5jZUNvdW50ZXIgPj0gdGhpcy5jb25maWcuZWFybHlTdG9wcGluZ1BhdGllbmNlKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGhhc2U6ICdjb250cmFzdGl2ZScsXG4gICAgICBlcG9jaHNDb21wbGV0ZWQ6IHRoaXMuY3VycmVudEVwb2NoICsgMSxcbiAgICAgIHRvdGFsU3RlcHM6IHRoaXMuY3VycmVudFN0ZXAsXG4gICAgICBmaW5hbExvc3M6IHRoaXMubG9zc0hpc3RvcnlbdGhpcy5sb3NzSGlzdG9yeS5sZW5ndGggLSAxXSB8fCAwLFxuICAgICAgYmVzdFZhbExvc3M6IHRoaXMuYmVzdFZhbExvc3MsXG4gICAgICBiZXN0RXBvY2g6IHRoaXMuZmluZEJlc3RFcG9jaCgpLFxuICAgICAgYWNjdXJhY3k6IHRvdGFsRXhhbXBsZXMgPiAwID8gdG90YWxDb3JyZWN0IC8gdG90YWxFeGFtcGxlcyA6IDAsXG4gICAgICBsb3NzSGlzdG9yeTogdGhpcy5sb3NzSGlzdG9yeSxcbiAgICAgIHZhbExvc3NIaXN0b3J5OiB0aGlzLnZhbExvc3NIaXN0b3J5LFxuICAgICAgZHVyYXRpb25NczogRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSxcbiAgICAgIGVhcmx5U3RvcHBlZDogdGhpcy5wYXRpZW5jZUNvdW50ZXIgPj0gdGhpcy5jb25maWcuZWFybHlTdG9wcGluZ1BhdGllbmNlLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRXZhbHVhdGUgdHJhaW5lZCBtb2RlbCBvbiB0ZXN0IHNldFxuICAgKi9cbiAgYXN5bmMgZXZhbHVhdGUodGVzdFNldDogUmxtVHJhaW5pbmdFeGFtcGxlW10pOiBQcm9taXNlPEV2YWx1YXRpb25SZXN1bHQ+IHtcbiAgICBjb25zdCBwZXJBZ2VudEFjY3VyYWN5OiBSZWNvcmQ8c3RyaW5nLCB7IGNvcnJlY3Q6IG51bWJlcjsgdG90YWw6IG51bWJlciB9PiA9IHt9O1xuXG4gICAgbGV0IGRlY29tcG9zaXRpb25Db3JyZWN0ID0gMDtcbiAgICBsZXQgc3ludGhlc2lzUXVhbGl0eVN1bSA9IDA7XG4gICAgbGV0IHJvdXRpbmdDb3JyZWN0ID0gMDtcbiAgICBsZXQgaGFyZE5lZ2F0aXZlQ29ycmVjdCA9IDA7XG4gICAgbGV0IGhhcmROZWdhdGl2ZVRvdGFsID0gMDtcbiAgICBsZXQgdG90YWxMYXRlbmN5ID0gMDtcblxuICAgIGZvciAoY29uc3QgZXhhbXBsZSBvZiB0ZXN0U2V0KSB7XG4gICAgICAvLyBEZWNvbXBvc2l0aW9uIGV2YWx1YXRpb25cbiAgICAgIGlmIChleGFtcGxlLmRlY29tcG9zaXRpb24uc3VjY2VzcyAmJiBleGFtcGxlLmRlY29tcG9zaXRpb24uc3ViUXVlcmllcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGRlY29tcG9zaXRpb25Db3JyZWN0Kys7XG4gICAgICB9XG5cbiAgICAgIC8vIFN5bnRoZXNpcyBxdWFsaXR5XG4gICAgICBzeW50aGVzaXNRdWFsaXR5U3VtICs9IGV4YW1wbGUucXVhbGl0eVNjb3JlO1xuXG4gICAgICAvLyBSb3V0aW5nIGV2YWx1YXRpb25cbiAgICAgIGZvciAoY29uc3Qgc3ViUXVlcnkgb2YgZXhhbXBsZS5kZWNvbXBvc2l0aW9uLnN1YlF1ZXJpZXMpIHtcbiAgICAgICAgaWYgKHN1YlF1ZXJ5LnJlY29tbWVuZGVkQWdlbnQpIHtcbiAgICAgICAgICBjb25zdCBwcmVkaWN0ZWQgPSB0aGlzLnByZWRpY3RBZ2VudChzdWJRdWVyeS5xdWVyeSk7XG4gICAgICAgICAgY29uc3QgY29ycmVjdCA9IHByZWRpY3RlZCA9PT0gc3ViUXVlcnkucmVjb21tZW5kZWRBZ2VudDtcblxuICAgICAgICAgIGlmIChjb3JyZWN0KSB7XG4gICAgICAgICAgICByb3V0aW5nQ29ycmVjdCsrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIFRyYWNrIHBlci1hZ2VudCBhY2N1cmFjeVxuICAgICAgICAgIGlmICghcGVyQWdlbnRBY2N1cmFjeVtzdWJRdWVyeS5yZWNvbW1lbmRlZEFnZW50XSkge1xuICAgICAgICAgICAgcGVyQWdlbnRBY2N1cmFjeVtzdWJRdWVyeS5yZWNvbW1lbmRlZEFnZW50XSA9IHsgY29ycmVjdDogMCwgdG90YWw6IDAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGVyQWdlbnRBY2N1cmFjeVtzdWJRdWVyeS5yZWNvbW1lbmRlZEFnZW50XS50b3RhbCsrO1xuICAgICAgICAgIGlmIChjb3JyZWN0KSB7XG4gICAgICAgICAgICBwZXJBZ2VudEFjY3VyYWN5W3N1YlF1ZXJ5LnJlY29tbWVuZGVkQWdlbnRdLmNvcnJlY3QrKztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBDaGVjayBoYXJkIG5lZ2F0aXZlc1xuICAgICAgICAgIGlmICh0aGlzLmlzSGFyZE5lZ2F0aXZlKHN1YlF1ZXJ5LnJlY29tbWVuZGVkQWdlbnQsIHByZWRpY3RlZCkpIHtcbiAgICAgICAgICAgIGhhcmROZWdhdGl2ZVRvdGFsKys7XG4gICAgICAgICAgICBpZiAoY29ycmVjdCkge1xuICAgICAgICAgICAgICBoYXJkTmVnYXRpdmVDb3JyZWN0Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRvdGFsTGF0ZW5jeSArPSBleGFtcGxlLnRyYWplY3RvcnkudG90YWxMYXRlbmN5TXM7XG4gICAgfVxuXG4gICAgY29uc3QgdG90YWxSb3V0aW5nRXhhbXBsZXMgPSB0ZXN0U2V0LnJlZHVjZShcbiAgICAgIChzdW0sIGV4KSA9PiBzdW0gKyBleC5kZWNvbXBvc2l0aW9uLnN1YlF1ZXJpZXMuZmlsdGVyKChzcSkgPT4gc3EucmVjb21tZW5kZWRBZ2VudCkubGVuZ3RoLFxuICAgICAgMFxuICAgICk7XG5cbiAgICBjb25zdCBwZXJBZ2VudFJlc3VsdDogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICAgIGZvciAoY29uc3QgW2FnZW50LCBzdGF0c10gb2YgT2JqZWN0LmVudHJpZXMocGVyQWdlbnRBY2N1cmFjeSkpIHtcbiAgICAgIHBlckFnZW50UmVzdWx0W2FnZW50XSA9IHN0YXRzLnRvdGFsID4gMCA/IHN0YXRzLmNvcnJlY3QgLyBzdGF0cy50b3RhbCA6IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRlY29tcG9zaXRpb25BY2N1cmFjeTogdGVzdFNldC5sZW5ndGggPiAwID8gZGVjb21wb3NpdGlvbkNvcnJlY3QgLyB0ZXN0U2V0Lmxlbmd0aCA6IDAsXG4gICAgICBzeW50aGVzaXNRdWFsaXR5OiB0ZXN0U2V0Lmxlbmd0aCA+IDAgPyBzeW50aGVzaXNRdWFsaXR5U3VtIC8gdGVzdFNldC5sZW5ndGggOiAwLFxuICAgICAgcm91dGluZ0FjY3VyYWN5OiB0b3RhbFJvdXRpbmdFeGFtcGxlcyA+IDAgPyByb3V0aW5nQ29ycmVjdCAvIHRvdGFsUm91dGluZ0V4YW1wbGVzIDogMCxcbiAgICAgIGhhcmROZWdhdGl2ZUFjY3VyYWN5OiBoYXJkTmVnYXRpdmVUb3RhbCA+IDAgPyBoYXJkTmVnYXRpdmVDb3JyZWN0IC8gaGFyZE5lZ2F0aXZlVG90YWwgOiAwLFxuICAgICAgYXZnTGF0ZW5jeU1zOiB0ZXN0U2V0Lmxlbmd0aCA+IDAgPyB0b3RhbExhdGVuY3kgLyB0ZXN0U2V0Lmxlbmd0aCA6IDAsXG4gICAgICB0b3RhbEV4YW1wbGVzOiB0ZXN0U2V0Lmxlbmd0aCxcbiAgICAgIHBlckFnZW50QWNjdXJhY3k6IHBlckFnZW50UmVzdWx0LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgY29udHJhc3RpdmUgcGFpcnMgZnJvbSBkYXRhc2V0XG4gICAqL1xuICBnZW5lcmF0ZUNvbnRyYXN0aXZlUGFpcnMoXG4gICAgZGF0YXNldDogUmxtVHJhaW5pbmdFeGFtcGxlW10sXG4gICAgaGFyZE5lZ2F0aXZlUmF0aW8gPSAwLjNcbiAgKTogQ29udHJhc3RpdmVQYWlyW10ge1xuICAgIGNvbnN0IHBhaXJzOiBDb250cmFzdGl2ZVBhaXJbXSA9IFtdO1xuICAgIGNvbnN0IGFnZW50cyA9IE9iamVjdC5rZXlzKEFHRU5UX0RFRklOSVRJT05TKTtcblxuICAgIGZvciAoY29uc3QgZXhhbXBsZSBvZiBkYXRhc2V0KSB7XG4gICAgICBmb3IgKGNvbnN0IHN1YlF1ZXJ5IG9mIGV4YW1wbGUuZGVjb21wb3NpdGlvbi5zdWJRdWVyaWVzKSB7XG4gICAgICAgIGlmICghc3ViUXVlcnkucmVjb21tZW5kZWRBZ2VudCkgY29udGludWU7XG5cbiAgICAgICAgY29uc3QgcG9zaXRpdmVBZ2VudCA9IHN1YlF1ZXJ5LnJlY29tbWVuZGVkQWdlbnQ7XG5cbiAgICAgICAgZm9yIChjb25zdCBuZWdhdGl2ZUFnZW50IG9mIGFnZW50cykge1xuICAgICAgICAgIGlmIChuZWdhdGl2ZUFnZW50ID09PSBwb3NpdGl2ZUFnZW50KSBjb250aW51ZTtcblxuICAgICAgICAgIGNvbnN0IGlzSGFyZCA9IHRoaXMuaXNIYXJkTmVnYXRpdmUocG9zaXRpdmVBZ2VudCwgbmVnYXRpdmVBZ2VudCk7XG5cbiAgICAgICAgICAvLyBBcHBseSBoYXJkIG5lZ2F0aXZlIHJhdGlvXG4gICAgICAgICAgY29uc3QgaW5jbHVkZSA9IGlzSGFyZFxuICAgICAgICAgICAgPyBNYXRoLnJhbmRvbSgpIDwgaGFyZE5lZ2F0aXZlUmF0aW9cbiAgICAgICAgICAgIDogTWF0aC5yYW5kb20oKSA8IDEgLSBoYXJkTmVnYXRpdmVSYXRpbztcblxuICAgICAgICAgIGlmIChpbmNsdWRlKSB7XG4gICAgICAgICAgICBwYWlycy5wdXNoKHtcbiAgICAgICAgICAgICAgYW5jaG9yOiBzdWJRdWVyeS5xdWVyeSxcbiAgICAgICAgICAgICAgYW5jaG9yRW1iZWRkaW5nOiBleGFtcGxlLnF1ZXJ5RW1iZWRkaW5nLFxuICAgICAgICAgICAgICBwb3NpdGl2ZUFnZW50LFxuICAgICAgICAgICAgICBuZWdhdGl2ZUFnZW50LFxuICAgICAgICAgICAgICBpc0hhcmROZWdhdGl2ZTogaXNIYXJkLFxuICAgICAgICAgICAgICBxdWFsaXR5OiBleGFtcGxlLnF1YWxpdHlTY29yZSxcbiAgICAgICAgICAgICAgc291cmNlSWQ6IGV4YW1wbGUuaWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcGFpcnM7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBQcml2YXRlIE1ldGhvZHNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBwcml2YXRlIHJlc2V0U3RhdGUoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50RXBvY2ggPSAwO1xuICAgIHRoaXMuY3VycmVudFN0ZXAgPSAwO1xuICAgIHRoaXMuYmVzdFZhbExvc3MgPSBJbmZpbml0eTtcbiAgICB0aGlzLnBhdGllbmNlQ291bnRlciA9IDA7XG4gICAgdGhpcy5sb3NzSGlzdG9yeSA9IFtdO1xuICAgIHRoaXMudmFsTG9zc0hpc3RvcnkgPSBbXTtcbiAgfVxuXG4gIHByaXZhdGUgc3BsaXREYXRhc2V0KFxuICAgIGRhdGFzZXQ6IFJsbVRyYWluaW5nRXhhbXBsZVtdXG4gICk6IHsgdHJhaW5TZXQ6IFJsbVRyYWluaW5nRXhhbXBsZVtdOyB2YWxTZXQ6IFJsbVRyYWluaW5nRXhhbXBsZVtdIH0ge1xuICAgIGNvbnN0IHZhbFNpemUgPSBNYXRoLmZsb29yKGRhdGFzZXQubGVuZ3RoICogdGhpcy5jb25maWcudmFsaWRhdGlvblNwbGl0KTtcbiAgICBjb25zdCBzaHVmZmxlZCA9IHRoaXMuc2h1ZmZsZShbLi4uZGF0YXNldF0pO1xuICAgIHJldHVybiB7XG4gICAgICB0cmFpblNldDogc2h1ZmZsZWQuc2xpY2UodmFsU2l6ZSksXG4gICAgICB2YWxTZXQ6IHNodWZmbGVkLnNsaWNlKDAsIHZhbFNpemUpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHNwbGl0UGFpcnMoXG4gICAgcGFpcnM6IENvbnRyYXN0aXZlUGFpcltdXG4gICk6IHsgdHJhaW5TZXQ6IENvbnRyYXN0aXZlUGFpcltdOyB2YWxTZXQ6IENvbnRyYXN0aXZlUGFpcltdIH0ge1xuICAgIGNvbnN0IHZhbFNpemUgPSBNYXRoLmZsb29yKHBhaXJzLmxlbmd0aCAqIHRoaXMuY29uZmlnLnZhbGlkYXRpb25TcGxpdCk7XG4gICAgY29uc3Qgc2h1ZmZsZWQgPSB0aGlzLnNodWZmbGUoWy4uLnBhaXJzXSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRyYWluU2V0OiBzaHVmZmxlZC5zbGljZSh2YWxTaXplKSxcbiAgICAgIHZhbFNldDogc2h1ZmZsZWQuc2xpY2UoMCwgdmFsU2l6ZSksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQmF0Y2hlcyhkYXRhc2V0OiBSbG1UcmFpbmluZ0V4YW1wbGVbXSk6IFJsbVRyYWluaW5nRXhhbXBsZVtdW10ge1xuICAgIGNvbnN0IGJhdGNoZXM6IFJsbVRyYWluaW5nRXhhbXBsZVtdW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGFzZXQubGVuZ3RoOyBpICs9IHRoaXMuY29uZmlnLmJhdGNoU2l6ZSkge1xuICAgICAgYmF0Y2hlcy5wdXNoKGRhdGFzZXQuc2xpY2UoaSwgaSArIHRoaXMuY29uZmlnLmJhdGNoU2l6ZSkpO1xuICAgIH1cbiAgICByZXR1cm4gYmF0Y2hlcztcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlUGFpckJhdGNoZXMocGFpcnM6IENvbnRyYXN0aXZlUGFpcltdKTogQ29udHJhc3RpdmVQYWlyW11bXSB7XG4gICAgY29uc3QgYmF0Y2hlczogQ29udHJhc3RpdmVQYWlyW11bXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFpcnMubGVuZ3RoOyBpICs9IHRoaXMuY29uZmlnLmJhdGNoU2l6ZSkge1xuICAgICAgYmF0Y2hlcy5wdXNoKHBhaXJzLnNsaWNlKGksIGkgKyB0aGlzLmNvbmZpZy5iYXRjaFNpemUpKTtcbiAgICB9XG4gICAgcmV0dXJuIGJhdGNoZXM7XG4gIH1cblxuICBwcml2YXRlIHNodWZmbGU8VD4oYXJyYXk6IFRbXSk6IFRbXSB7XG4gICAgLy8gRmlzaGVyLVlhdGVzIHNodWZmbGVcbiAgICBmb3IgKGxldCBpID0gYXJyYXkubGVuZ3RoIC0gMTsgaSA+IDA7IGktLSkge1xuICAgICAgY29uc3QgaiA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChpICsgMSkpO1xuICAgICAgW2FycmF5W2ldLCBhcnJheVtqXV0gPSBbYXJyYXlbal0sIGFycmF5W2ldXTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cbiAgcHJpdmF0ZSB0cmFpbkRlY29tcG9zaXRpb25CYXRjaChiYXRjaDogUmxtVHJhaW5pbmdFeGFtcGxlW10pOiBudW1iZXIge1xuICAgIGxldCBiYXRjaExvc3MgPSAwO1xuXG4gICAgZm9yIChjb25zdCBleGFtcGxlIG9mIGJhdGNoKSB7XG4gICAgICAvLyBEZWNvbXBvc2l0aW9uIHF1YWxpdHkgbG9zc1xuICAgICAgY29uc3QgcXVhbGl0eUxvc3MgPSAxIC0gKGV4YW1wbGUuZGVjb21wb3NpdGlvbi5zdWNjZXNzID8gZXhhbXBsZS5xdWFsaXR5U2NvcmUgOiAwKTtcblxuICAgICAgLy8gRGVwdGggYXBwcm9wcmlhdGVuZXNzIChwZW5hbGl6ZSB0b28gc2hhbGxvdyBvciB0b28gZGVlcClcbiAgICAgIGNvbnN0IGRlcHRoID0gZXhhbXBsZS5kZWNvbXBvc2l0aW9uLnN1YlF1ZXJpZXMubGVuZ3RoO1xuICAgICAgY29uc3QgaWRlYWxEZXB0aCA9IDM7XG4gICAgICBjb25zdCBkZXB0aExvc3MgPSBNYXRoLmFicyhkZXB0aCAtIGlkZWFsRGVwdGgpIC8gaWRlYWxEZXB0aDtcblxuICAgICAgLy8gQ29tcGxleGl0eSBiYWxhbmNlIGxvc3NcbiAgICAgIGNvbnN0IGNvbXBsZXhpdHlMb3NzID0gTWF0aC5hYnMoZXhhbXBsZS5kZWNvbXBvc2l0aW9uLnRvdGFsQ29tcGxleGl0eSAtIDEpIC8gMztcblxuICAgICAgY29uc3QgbG9zcyA9XG4gICAgICAgIHF1YWxpdHlMb3NzICogdGhpcy5jb25maWcuZGVjb21wb3NpdGlvbldlaWdodCAqIDAuNiArXG4gICAgICAgIGRlcHRoTG9zcyAqIDAuMiArXG4gICAgICAgIGNvbXBsZXhpdHlMb3NzICogMC4yO1xuXG4gICAgICBiYXRjaExvc3MgKz0gbG9zcztcbiAgICB9XG5cbiAgICByZXR1cm4gYmF0Y2hMb3NzIC8gYmF0Y2gubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSB0cmFpblN5bnRoZXNpc0JhdGNoKGJhdGNoOiBSbG1UcmFpbmluZ0V4YW1wbGVbXSk6IG51bWJlciB7XG4gICAgbGV0IGJhdGNoTG9zcyA9IDA7XG5cbiAgICBmb3IgKGNvbnN0IGV4YW1wbGUgb2YgYmF0Y2gpIHtcbiAgICAgIC8vIFN1Yi1hbnN3ZXIgcXVhbGl0eVxuICAgICAgY29uc3Qgc3ViQW5zd2VyUXVhbGl0eSA9XG4gICAgICAgIGV4YW1wbGUuc3ViQW5zd2Vycy5sZW5ndGggPiAwXG4gICAgICAgICAgPyBleGFtcGxlLnN1YkFuc3dlcnMucmVkdWNlKChzdW0sIGEpID0+IHN1bSArIGEucXVhbGl0eSwgMCkgLyBleGFtcGxlLnN1YkFuc3dlcnMubGVuZ3RoXG4gICAgICAgICAgOiAwO1xuXG4gICAgICAvLyBGaW5hbCBhbnN3ZXIgcXVhbGl0eVxuICAgICAgY29uc3QgZmluYWxRdWFsaXR5ID0gZXhhbXBsZS5xdWFsaXR5U2NvcmU7XG5cbiAgICAgIC8vIENvaGVyZW5jZSBib251cyAoZmluYWwgc2hvdWxkIGJlIGJldHRlciB0aGFuIHBhcnRzIGF2ZXJhZ2UpXG4gICAgICBjb25zdCBjb2hlcmVuY2VCb251cyA9IE1hdGgubWF4KDAsIGZpbmFsUXVhbGl0eSAtIHN1YkFuc3dlclF1YWxpdHkpICogMC41O1xuXG4gICAgICBjb25zdCBsb3NzID0gKDEgLSAoc3ViQW5zd2VyUXVhbGl0eSAqIDAuNCArIGZpbmFsUXVhbGl0eSAqIDAuNCArIGNvaGVyZW5jZUJvbnVzICogMC4yKSk7XG5cbiAgICAgIGJhdGNoTG9zcyArPSBsb3NzICogdGhpcy5jb25maWcuc3ludGhlc2lzV2VpZ2h0O1xuICAgIH1cblxuICAgIHJldHVybiBiYXRjaExvc3MgLyBiYXRjaC5sZW5ndGg7XG4gIH1cblxuICBwcml2YXRlIHRyYWluQ29udHJhc3RpdmVCYXRjaChiYXRjaDogQ29udHJhc3RpdmVQYWlyW10pOiBudW1iZXIge1xuICAgIGxldCBiYXRjaExvc3MgPSAwO1xuXG4gICAgZm9yIChjb25zdCBwYWlyIG9mIGJhdGNoKSB7XG4gICAgICAvLyBUcmlwbGV0IGxvc3NcbiAgICAgIGNvbnN0IHRyaXBsZXRMb3NzID0gdGhpcy5jb21wdXRlVHJpcGxldExvc3MocGFpcik7XG5cbiAgICAgIC8vIEluZm9OQ0UgbG9zc1xuICAgICAgY29uc3QgaW5mb25jZUxvc3MgPSB0aGlzLmNvbXB1dGVJbmZvTkNFTG9zcyhwYWlyKTtcblxuICAgICAgYmF0Y2hMb3NzICs9ICh0cmlwbGV0TG9zcyAqIDAuNSArIGluZm9uY2VMb3NzICogMC41KSAqIHRoaXMuY29uZmlnLnJvdXRpbmdXZWlnaHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJhdGNoTG9zcyAvIGJhdGNoLmxlbmd0aDtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVEZWNvbXBvc2l0aW9uKHZhbFNldDogUmxtVHJhaW5pbmdFeGFtcGxlW10pOiBudW1iZXIge1xuICAgIGlmICh2YWxTZXQubGVuZ3RoID09PSAwKSByZXR1cm4gMDtcblxuICAgIGxldCB0b3RhbExvc3MgPSAwO1xuICAgIGZvciAoY29uc3QgZXhhbXBsZSBvZiB2YWxTZXQpIHtcbiAgICAgIHRvdGFsTG9zcyArPSAxIC0gZXhhbXBsZS5xdWFsaXR5U2NvcmU7XG4gICAgfVxuICAgIHJldHVybiB0b3RhbExvc3MgLyB2YWxTZXQubGVuZ3RoO1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVN5bnRoZXNpcyh2YWxTZXQ6IFJsbVRyYWluaW5nRXhhbXBsZVtdKTogbnVtYmVyIHtcbiAgICBpZiAodmFsU2V0Lmxlbmd0aCA9PT0gMCkgcmV0dXJuIDA7XG5cbiAgICBsZXQgdG90YWxMb3NzID0gMDtcbiAgICBmb3IgKGNvbnN0IGV4YW1wbGUgb2YgdmFsU2V0KSB7XG4gICAgICB0b3RhbExvc3MgKz0gMSAtIGV4YW1wbGUucXVhbGl0eVNjb3JlO1xuICAgIH1cbiAgICByZXR1cm4gdG90YWxMb3NzIC8gdmFsU2V0Lmxlbmd0aDtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVDb250cmFzdGl2ZShcbiAgICB2YWxTZXQ6IENvbnRyYXN0aXZlUGFpcltdXG4gICk6IHsgbG9zczogbnVtYmVyOyBjb3JyZWN0OiBudW1iZXI7IHRvdGFsOiBudW1iZXIgfSB7XG4gICAgaWYgKHZhbFNldC5sZW5ndGggPT09IDApIHJldHVybiB7IGxvc3M6IDAsIGNvcnJlY3Q6IDAsIHRvdGFsOiAwIH07XG5cbiAgICBsZXQgdG90YWxMb3NzID0gMDtcbiAgICBsZXQgY29ycmVjdCA9IDA7XG5cbiAgICBmb3IgKGNvbnN0IHBhaXIgb2YgdmFsU2V0KSB7XG4gICAgICBjb25zdCB0cmlwbGV0TG9zcyA9IHRoaXMuY29tcHV0ZVRyaXBsZXRMb3NzKHBhaXIpO1xuICAgICAgY29uc3QgaW5mb25jZUxvc3MgPSB0aGlzLmNvbXB1dGVJbmZvTkNFTG9zcyhwYWlyKTtcbiAgICAgIHRvdGFsTG9zcyArPSB0cmlwbGV0TG9zcyAqIDAuNSArIGluZm9uY2VMb3NzICogMC41O1xuXG4gICAgICAvLyBDaGVjayByb3V0aW5nIGNvcnJlY3RuZXNzXG4gICAgICBjb25zdCBwb3NEaXN0ID0gdGhpcy5hZ2VudERpc3RhbmNlKHBhaXIuYW5jaG9yLCBwYWlyLnBvc2l0aXZlQWdlbnQpO1xuICAgICAgY29uc3QgbmVnRGlzdCA9IHRoaXMuYWdlbnREaXN0YW5jZShwYWlyLmFuY2hvciwgcGFpci5uZWdhdGl2ZUFnZW50KTtcbiAgICAgIGlmIChwb3NEaXN0IDwgbmVnRGlzdCkge1xuICAgICAgICBjb3JyZWN0Kys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxvc3M6IHRvdGFsTG9zcyAvIHZhbFNldC5sZW5ndGgsXG4gICAgICBjb3JyZWN0LFxuICAgICAgdG90YWw6IHZhbFNldC5sZW5ndGgsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgY29tcHV0ZVRyaXBsZXRMb3NzKHBhaXI6IENvbnRyYXN0aXZlUGFpcik6IG51bWJlciB7XG4gICAgY29uc3QgcG9zRGlzdCA9IHRoaXMuYWdlbnREaXN0YW5jZShwYWlyLmFuY2hvciwgcGFpci5wb3NpdGl2ZUFnZW50KTtcbiAgICBjb25zdCBuZWdEaXN0ID0gdGhpcy5hZ2VudERpc3RhbmNlKHBhaXIuYW5jaG9yLCBwYWlyLm5lZ2F0aXZlQWdlbnQpO1xuICAgIHJldHVybiBNYXRoLm1heCgwLCB0aGlzLmNvbmZpZy5jb250cmFzdGl2ZU1hcmdpbiArIHBvc0Rpc3QgLSBuZWdEaXN0KTtcbiAgfVxuXG4gIHByaXZhdGUgY29tcHV0ZUluZm9OQ0VMb3NzKHBhaXI6IENvbnRyYXN0aXZlUGFpcik6IG51bWJlciB7XG4gICAgY29uc3QgcG9zU2ltID0gMSAtIHRoaXMuYWdlbnREaXN0YW5jZShwYWlyLmFuY2hvciwgcGFpci5wb3NpdGl2ZUFnZW50KTtcbiAgICBjb25zdCBuZWdTaW0gPSAxIC0gdGhpcy5hZ2VudERpc3RhbmNlKHBhaXIuYW5jaG9yLCBwYWlyLm5lZ2F0aXZlQWdlbnQpO1xuXG4gICAgY29uc3QgdGVtcCA9IHRoaXMuY29uZmlnLmluZm9uY2VUZW1wZXJhdHVyZTtcbiAgICBjb25zdCBwb3NFeHAgPSBNYXRoLmV4cChwb3NTaW0gLyB0ZW1wKTtcbiAgICBjb25zdCBuZWdFeHAgPSBNYXRoLmV4cChuZWdTaW0gLyB0ZW1wKTtcblxuICAgIHJldHVybiAtTWF0aC5sb2cocG9zRXhwIC8gKHBvc0V4cCArIG5lZ0V4cCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZ2VudERpc3RhbmNlKHF1ZXJ5OiBzdHJpbmcsIGFnZW50OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGNvbnN0IHF1ZXJ5TG93ZXIgPSBxdWVyeS50b0xvd2VyQ2FzZSgpO1xuICAgIGNvbnN0IGFnZW50RGVmID0gQUdFTlRfREVGSU5JVElPTlNbYWdlbnRdO1xuXG4gICAgaWYgKCFhZ2VudERlZikgcmV0dXJuIDEuMDtcblxuICAgIGNvbnN0IG1hdGNoZXMgPSBhZ2VudERlZi5rZXl3b3Jkcy5maWx0ZXIoKGt3KSA9PiBxdWVyeUxvd2VyLmluY2x1ZGVzKGt3KSkubGVuZ3RoO1xuICAgIHJldHVybiAxLjAgLSBNYXRoLm1pbigxLjAsIG1hdGNoZXMgLyBhZ2VudERlZi5rZXl3b3Jkcy5sZW5ndGgpO1xuICB9XG5cbiAgcHJpdmF0ZSBwcmVkaWN0QWdlbnQocXVlcnk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgbGV0IGJlc3RBZ2VudCA9ICdjb2Rlcic7XG4gICAgbGV0IGJlc3RTY29yZSA9IDA7XG5cbiAgICBmb3IgKGNvbnN0IFthZ2VudCwgZGVmXSBvZiBPYmplY3QuZW50cmllcyhBR0VOVF9ERUZJTklUSU9OUykpIHtcbiAgICAgIGNvbnN0IHF1ZXJ5TG93ZXIgPSBxdWVyeS50b0xvd2VyQ2FzZSgpO1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGRlZi5rZXl3b3Jkcy5maWx0ZXIoKGt3KSA9PiBxdWVyeUxvd2VyLmluY2x1ZGVzKGt3KSkubGVuZ3RoO1xuICAgICAgY29uc3Qgc2NvcmUgPSBtYXRjaGVzIC8gZGVmLmtleXdvcmRzLmxlbmd0aDtcblxuICAgICAgaWYgKHNjb3JlID4gYmVzdFNjb3JlKSB7XG4gICAgICAgIGJlc3RTY29yZSA9IHNjb3JlO1xuICAgICAgICBiZXN0QWdlbnQgPSBhZ2VudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYmVzdEFnZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBpc0hhcmROZWdhdGl2ZShhZ2VudDE6IHN0cmluZywgYWdlbnQyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gSEFSRF9ORUdBVElWRV9QQUlSUy5zb21lKFxuICAgICAgKFthLCBiXSkgPT4gKGFnZW50MSA9PT0gYSAmJiBhZ2VudDIgPT09IGIpIHx8IChhZ2VudDEgPT09IGIgJiYgYWdlbnQyID09PSBhKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGZpbmRCZXN0RXBvY2goKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy52YWxMb3NzSGlzdG9yeS5sZW5ndGggPT09IDApIHJldHVybiAwO1xuXG4gICAgbGV0IGJlc3RJZHggPSAwO1xuICAgIGxldCBiZXN0TG9zcyA9IHRoaXMudmFsTG9zc0hpc3RvcnlbMF07XG5cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHRoaXMudmFsTG9zc0hpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICh0aGlzLnZhbExvc3NIaXN0b3J5W2ldIDwgYmVzdExvc3MpIHtcbiAgICAgICAgYmVzdExvc3MgPSB0aGlzLnZhbExvc3NIaXN0b3J5W2ldO1xuICAgICAgICBiZXN0SWR4ID0gaTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYmVzdElkeDtcbiAgfVxufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRmFjdG9yeSBGdW5jdGlvbnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogQ3JlYXRlIGFuIFJMTSB0cmFpbmVyIHdpdGggZGVmYXVsdCBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSbG1UcmFpbmVyKGNvbmZpZz86IFBhcnRpYWw8UmxtVHJhaW5pbmdDb25maWc+KTogUmxtVHJhaW5lciB7XG4gIHJldHVybiBuZXcgUmxtVHJhaW5lcihjb25maWcpO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhbiBlbXB0eSBSTE0gdHJhaW5pbmcgZXhhbXBsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRW1wdHlFeGFtcGxlKHF1ZXJ5OiBzdHJpbmcpOiBSbG1UcmFpbmluZ0V4YW1wbGUge1xuICByZXR1cm4ge1xuICAgIGlkOiBjcnlwdG8ucmFuZG9tVVVJRCA/IGNyeXB0by5yYW5kb21VVUlEKCkgOiBgJHtEYXRlLm5vdygpfS0ke01hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpfWAsXG4gICAgcXVlcnksXG4gICAgZGVjb21wb3NpdGlvbjoge1xuICAgICAgc3ViUXVlcmllczogW10sXG4gICAgICBzdHJhdGVneTogJ25vbmUnLFxuICAgICAgcmF0aW9uYWxlOiAnJyxcbiAgICAgIHRvdGFsQ29tcGxleGl0eTogMCxcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgIH0sXG4gICAgc3ViQW5zd2VyczogW10sXG4gICAgZmluYWxBbnN3ZXI6ICcnLFxuICAgIHF1YWxpdHlTY29yZTogMCxcbiAgICB0cmFqZWN0b3J5OiB7XG4gICAgICB0b3RhbExhdGVuY3lNczogMCxcbiAgICAgIHJldHJpZXM6IDAsXG4gICAgICBtYXhQYXJhbGxlbGlzbTogMSxcbiAgICAgIG1vZGVsc1VzZWQ6IFtdLFxuICAgICAgYWdlbnRzSW52b2tlZDogW10sXG4gICAgICB0b29sc1VzZWQ6IFtdLFxuICAgICAgYXR0cmlidXRlczoge30sXG4gICAgfSxcbiAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICBsZXNzb25zOiBbXSxcbiAgICBzb3VyY2U6ICdtYW51YWwnLFxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHN1Yi1xdWVyeVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU3ViUXVlcnkoXG4gIGlkOiBudW1iZXIsXG4gIHF1ZXJ5OiBzdHJpbmcsXG4gIG9wdGlvbnM6IFBhcnRpYWw8U3ViUXVlcnk+ID0ge31cbik6IFN1YlF1ZXJ5IHtcbiAgcmV0dXJuIHtcbiAgICBpZCxcbiAgICBxdWVyeSxcbiAgICBleHBlY3RlZFR5cGU6ICd0ZXh0JyxcbiAgICBkZXBlbmRlbmNpZXM6IFtdLFxuICAgIGNvbXBsZXhpdHk6IDAuNSxcbiAgICAuLi5vcHRpb25zLFxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHN1Yi1hbnN3ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVN1YkFuc3dlcihcbiAgc3ViUXVlcnlJZDogbnVtYmVyLFxuICBjb250ZW50OiBzdHJpbmcsXG4gIGFnZW50OiBzdHJpbmcsXG4gIG9wdGlvbnM6IFBhcnRpYWw8U3ViQW5zd2VyPiA9IHt9XG4pOiBTdWJBbnN3ZXIge1xuICByZXR1cm4ge1xuICAgIHN1YlF1ZXJ5SWQsXG4gICAgY29udGVudCxcbiAgICBjb25maWRlbmNlOiAwLjgsXG4gICAgYWdlbnQsXG4gICAgbGF0ZW5jeU1zOiAwLFxuICAgIHF1YWxpdHk6IDAuOCxcbiAgICBzdWNjZXNzOiB0cnVlLFxuICAgIC4uLm9wdGlvbnMsXG4gIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFeHBvcnRzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgZGVmYXVsdCBSbG1UcmFpbmVyO1xuIl19