@ruvector/ruvllm 2.4.0 → 2.5.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.
- package/README.md +26 -302
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/intelligence.d.ts +136 -0
- package/dist/cjs/intelligence.d.ts.map +1 -0
- package/dist/cjs/intelligence.js +162 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -3
- package/dist/esm/intelligence.d.ts +136 -0
- package/dist/esm/intelligence.d.ts.map +1 -0
- package/dist/esm/intelligence.js +157 -0
- package/package.json +3 -7
- package/scripts/training/validation-results.json +1 -1
- package/dist/cjs/rlm/controller.d.ts +0 -245
- package/dist/cjs/rlm/controller.d.ts.map +0 -1
- package/dist/cjs/rlm/controller.js +0 -554
- package/dist/cjs/rlm/index.d.ts +0 -62
- package/dist/cjs/rlm/index.d.ts.map +0 -1
- package/dist/cjs/rlm/index.js +0 -97
- package/dist/cjs/rlm/training.d.ts +0 -333
- package/dist/cjs/rlm/training.d.ts.map +0 -1
- package/dist/cjs/rlm/training.js +0 -680
- package/dist/cjs/rlm/types.d.ts +0 -189
- package/dist/cjs/rlm/types.d.ts.map +0 -1
- package/dist/cjs/rlm/types.js +0 -10
- package/dist/esm/rlm/controller.d.ts +0 -245
- package/dist/esm/rlm/controller.d.ts.map +0 -1
- package/dist/esm/rlm/controller.js +0 -550
- package/dist/esm/rlm/index.d.ts +0 -62
- package/dist/esm/rlm/index.d.ts.map +0 -1
- package/dist/esm/rlm/index.js +0 -71
- package/dist/esm/rlm/training.d.ts +0 -333
- package/dist/esm/rlm/training.d.ts.map +0 -1
- package/dist/esm/rlm/training.js +0 -672
- package/dist/esm/rlm/types.d.ts +0 -189
- package/dist/esm/rlm/types.d.ts.map +0 -1
- package/dist/esm/rlm/types.js +0 -9
- package/scripts/training/rlm-dataset.js +0 -671
package/dist/cjs/rlm/training.js
DELETED
|
@@ -1,680 +0,0 @@
|
|
|
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
|