@ruvector/ruvllm 2.7.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/GPU-LOOP.md +229 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +9 -0
  4. package/README.md +157 -263
  5. package/examples/gpu-loop.example.json +26 -0
  6. package/package.json +50 -120
  7. package/src/adapters-cli.mjs +23 -0
  8. package/src/adapters.mjs +91 -0
  9. package/src/cli.mjs +30 -0
  10. package/src/engine.mjs +238 -0
  11. package/src/fixture.mjs +38 -0
  12. package/src/gpu-host.mjs +47 -0
  13. package/src/gpu-loop-cli.mjs +67 -0
  14. package/src/gpu-loop.mjs +184 -0
  15. package/src/gpu-spool-adapter.mjs +80 -0
  16. package/src/vast-host-adapter.mjs +274 -0
  17. package/bin/cli.js +0 -1020
  18. package/dist/cjs/benchmarks/embedding-benchmark.d.ts +0 -102
  19. package/dist/cjs/benchmarks/embedding-benchmark.d.ts.map +0 -1
  20. package/dist/cjs/benchmarks/embedding-benchmark.js +0 -436
  21. package/dist/cjs/benchmarks/index.d.ts +0 -34
  22. package/dist/cjs/benchmarks/index.d.ts.map +0 -1
  23. package/dist/cjs/benchmarks/index.js +0 -132
  24. package/dist/cjs/benchmarks/model-comparison.d.ts +0 -71
  25. package/dist/cjs/benchmarks/model-comparison.d.ts.map +0 -1
  26. package/dist/cjs/benchmarks/model-comparison.js +0 -476
  27. package/dist/cjs/benchmarks/routing-benchmark.d.ts +0 -70
  28. package/dist/cjs/benchmarks/routing-benchmark.d.ts.map +0 -1
  29. package/dist/cjs/benchmarks/routing-benchmark.js +0 -289
  30. package/dist/cjs/contrastive.d.ts +0 -229
  31. package/dist/cjs/contrastive.d.ts.map +0 -1
  32. package/dist/cjs/contrastive.js +0 -589
  33. package/dist/cjs/engine.d.ts +0 -95
  34. package/dist/cjs/engine.d.ts.map +0 -1
  35. package/dist/cjs/engine.js +0 -372
  36. package/dist/cjs/export.d.ts +0 -182
  37. package/dist/cjs/export.d.ts.map +0 -1
  38. package/dist/cjs/export.js +0 -422
  39. package/dist/cjs/federated.d.ts +0 -233
  40. package/dist/cjs/federated.d.ts.map +0 -1
  41. package/dist/cjs/federated.js +0 -525
  42. package/dist/cjs/index.d.ts +0 -68
  43. package/dist/cjs/index.d.ts.map +0 -1
  44. package/dist/cjs/index.js +0 -104
  45. package/dist/cjs/intelligence.d.ts +0 -136
  46. package/dist/cjs/intelligence.d.ts.map +0 -1
  47. package/dist/cjs/intelligence.js +0 -226
  48. package/dist/cjs/lora.d.ts +0 -251
  49. package/dist/cjs/lora.d.ts.map +0 -1
  50. package/dist/cjs/lora.js +0 -509
  51. package/dist/cjs/models.d.ts +0 -129
  52. package/dist/cjs/models.d.ts.map +0 -1
  53. package/dist/cjs/models.js +0 -323
  54. package/dist/cjs/native.d.ts +0 -92
  55. package/dist/cjs/native.d.ts.map +0 -1
  56. package/dist/cjs/native.js +0 -77
  57. package/dist/cjs/session.d.ts +0 -80
  58. package/dist/cjs/session.d.ts.map +0 -1
  59. package/dist/cjs/session.js +0 -203
  60. package/dist/cjs/simd.d.ts +0 -90
  61. package/dist/cjs/simd.d.ts.map +0 -1
  62. package/dist/cjs/simd.js +0 -209
  63. package/dist/cjs/sona.d.ts +0 -223
  64. package/dist/cjs/sona.d.ts.map +0 -1
  65. package/dist/cjs/sona.js +0 -562
  66. package/dist/cjs/streaming.d.ts +0 -55
  67. package/dist/cjs/streaming.d.ts.map +0 -1
  68. package/dist/cjs/streaming.js +0 -131
  69. package/dist/cjs/training.d.ts +0 -312
  70. package/dist/cjs/training.d.ts.map +0 -1
  71. package/dist/cjs/training.js +0 -610
  72. package/dist/cjs/types.d.ts +0 -615
  73. package/dist/cjs/types.d.ts.map +0 -1
  74. package/dist/cjs/types.js +0 -6
  75. package/dist/esm/benchmarks/embedding-benchmark.d.ts +0 -102
  76. package/dist/esm/benchmarks/embedding-benchmark.d.ts.map +0 -1
  77. package/dist/esm/benchmarks/embedding-benchmark.js +0 -427
  78. package/dist/esm/benchmarks/index.d.ts +0 -34
  79. package/dist/esm/benchmarks/index.d.ts.map +0 -1
  80. package/dist/esm/benchmarks/index.js +0 -110
  81. package/dist/esm/benchmarks/model-comparison.d.ts +0 -71
  82. package/dist/esm/benchmarks/model-comparison.d.ts.map +0 -1
  83. package/dist/esm/benchmarks/model-comparison.js +0 -434
  84. package/dist/esm/benchmarks/routing-benchmark.d.ts +0 -70
  85. package/dist/esm/benchmarks/routing-benchmark.d.ts.map +0 -1
  86. package/dist/esm/benchmarks/routing-benchmark.js +0 -283
  87. package/dist/esm/contrastive.d.ts +0 -229
  88. package/dist/esm/contrastive.d.ts.map +0 -1
  89. package/dist/esm/contrastive.js +0 -578
  90. package/dist/esm/engine.d.ts +0 -95
  91. package/dist/esm/engine.d.ts.map +0 -1
  92. package/dist/esm/engine.js +0 -368
  93. package/dist/esm/export.d.ts +0 -182
  94. package/dist/esm/export.d.ts.map +0 -1
  95. package/dist/esm/export.js +0 -414
  96. package/dist/esm/federated.d.ts +0 -233
  97. package/dist/esm/federated.d.ts.map +0 -1
  98. package/dist/esm/federated.js +0 -520
  99. package/dist/esm/index.d.ts +0 -68
  100. package/dist/esm/index.d.ts.map +0 -1
  101. package/dist/esm/index.js +0 -84
  102. package/dist/esm/intelligence.d.ts +0 -136
  103. package/dist/esm/intelligence.d.ts.map +0 -1
  104. package/dist/esm/intelligence.js +0 -188
  105. package/dist/esm/lora.d.ts +0 -251
  106. package/dist/esm/lora.d.ts.map +0 -1
  107. package/dist/esm/lora.js +0 -504
  108. package/dist/esm/models.d.ts +0 -129
  109. package/dist/esm/models.d.ts.map +0 -1
  110. package/dist/esm/models.js +0 -282
  111. package/dist/esm/native.d.ts +0 -92
  112. package/dist/esm/native.d.ts.map +0 -1
  113. package/dist/esm/native.js +0 -72
  114. package/dist/esm/session.d.ts +0 -80
  115. package/dist/esm/session.d.ts.map +0 -1
  116. package/dist/esm/session.js +0 -199
  117. package/dist/esm/simd.d.ts +0 -90
  118. package/dist/esm/simd.d.ts.map +0 -1
  119. package/dist/esm/simd.js +0 -205
  120. package/dist/esm/sona.d.ts +0 -223
  121. package/dist/esm/sona.d.ts.map +0 -1
  122. package/dist/esm/sona.js +0 -556
  123. package/dist/esm/streaming.d.ts +0 -55
  124. package/dist/esm/streaming.d.ts.map +0 -1
  125. package/dist/esm/streaming.js +0 -126
  126. package/dist/esm/training.d.ts +0 -312
  127. package/dist/esm/training.d.ts.map +0 -1
  128. package/dist/esm/training.js +0 -603
  129. package/dist/esm/types.d.ts +0 -615
  130. package/dist/esm/types.d.ts.map +0 -1
  131. package/dist/esm/types.js +0 -5
  132. package/scripts/ensemble-model-compare.js +0 -287
  133. package/scripts/fix-esm-extensions.mjs +0 -181
  134. package/scripts/huggingface/README.md +0 -537
  135. package/scripts/huggingface/publish.sh +0 -112
  136. package/scripts/hybrid-model-compare.js +0 -373
  137. package/scripts/improved-model-compare.js +0 -288
  138. package/scripts/optimized-model-compare.js +0 -364
  139. package/scripts/real-model-compare.js +0 -280
  140. package/scripts/smoke-esm.mjs +0 -82
  141. package/scripts/training/agentic-flow-capabilities.json +0 -329
  142. package/scripts/training/claude-code-synth.js +0 -505
  143. package/scripts/training/claude-flow-capabilities.json +0 -1322
  144. package/scripts/training/claude-hard-negatives.js +0 -222
  145. package/scripts/training/contrastive-finetune.js +0 -517
  146. package/scripts/training/ecosystem-triplets.jsonl +0 -1467
  147. package/scripts/training/generate-ecosystem-triplets.js +0 -1324
  148. package/scripts/training/routing-dataset.js +0 -634
  149. package/scripts/training/ruvector-capabilities.json +0 -798
  150. package/scripts/training/validate-ecosystem.js +0 -381
  151. package/scripts/training/validation-results.json +0 -23
@@ -1,589 +0,0 @@
1
- "use strict";
2
- /**
3
- * Contrastive Fine-tuning for RuvLTRA Claude Code Router
4
- *
5
- * Uses triplet loss to fine-tune embeddings:
6
- * - Anchor: task description
7
- * - Positive: correct agent description
8
- * - Negative: wrong agent description (hard negative)
9
- *
10
- * Goal: minimize distance(anchor, positive) and maximize distance(anchor, negative)
11
- *
12
- * @example
13
- * ```typescript
14
- * import { ContrastiveTrainer, tripletLoss, infoNCELoss } from '@ruvector/ruvllm';
15
- *
16
- * const trainer = new ContrastiveTrainer({
17
- * epochs: 10,
18
- * batchSize: 16,
19
- * margin: 0.5,
20
- * });
21
- *
22
- * // Add triplets
23
- * trainer.addTriplet(anchorEmb, positiveEmb, negativeEmb, true);
24
- *
25
- * // Train and export
26
- * const results = trainer.train();
27
- * trainer.exportTrainingData('./output');
28
- * ```
29
- */
30
- Object.defineProperty(exports, "__esModule", { value: true });
31
- exports.AGENT_TRAINING_DATA = exports.ContrastiveTrainer = void 0;
32
- exports.cosineSimilarity = cosineSimilarity;
33
- exports.tripletLoss = tripletLoss;
34
- exports.infoNCELoss = infoNCELoss;
35
- exports.computeGradient = computeGradient;
36
- exports.generateTrainingDataset = generateTrainingDataset;
37
- exports.generateContrastivePairs = generateContrastivePairs;
38
- exports.getDatasetStats = getDatasetStats;
39
- const fs_1 = require("fs");
40
- const path_1 = require("path");
41
- /**
42
- * Default contrastive config
43
- */
44
- const DEFAULT_CONTRASTIVE_CONFIG = {
45
- epochs: 10,
46
- batchSize: 16,
47
- learningRate: 0.0001,
48
- margin: 0.5,
49
- temperature: 0.07,
50
- hardNegativeRatio: 0.7,
51
- outputPath: './training-output',
52
- };
53
- /**
54
- * Compute cosine similarity between two embeddings
55
- */
56
- function cosineSimilarity(a, b) {
57
- if (!a || !b || a.length !== b.length)
58
- return 0;
59
- let dot = 0, normA = 0, normB = 0;
60
- for (let i = 0; i < a.length; i++) {
61
- dot += a[i] * b[i];
62
- normA += a[i] * a[i];
63
- normB += b[i] * b[i];
64
- }
65
- return dot / (Math.sqrt(normA) * Math.sqrt(normB) || 1);
66
- }
67
- /**
68
- * Compute triplet loss
69
- * L = max(0, margin + d(anchor, positive) - d(anchor, negative))
70
- */
71
- function tripletLoss(anchorEmb, positiveEmb, negativeEmb, margin = 0.5) {
72
- const posDist = 1 - cosineSimilarity(anchorEmb, positiveEmb);
73
- const negDist = 1 - cosineSimilarity(anchorEmb, negativeEmb);
74
- return Math.max(0, margin + posDist - negDist);
75
- }
76
- /**
77
- * Compute InfoNCE loss (contrastive)
78
- */
79
- function infoNCELoss(anchorEmb, positiveEmb, negativeEmbs, temperature = 0.07) {
80
- const posSim = cosineSimilarity(anchorEmb, positiveEmb) / temperature;
81
- const negSims = negativeEmbs.map(neg => cosineSimilarity(anchorEmb, neg) / temperature);
82
- // Softmax denominator
83
- const maxSim = Math.max(posSim, ...negSims);
84
- const expPos = Math.exp(posSim - maxSim);
85
- const expNegs = negSims.map(sim => Math.exp(sim - maxSim));
86
- const denominator = expPos + expNegs.reduce((a, b) => a + b, 0);
87
- // Cross-entropy loss
88
- return -Math.log(expPos / denominator);
89
- }
90
- /**
91
- * Compute gradient for embedding update (simplified)
92
- */
93
- function computeGradient(anchorEmb, positiveEmb, negativeEmb, lr = 0.0001) {
94
- const dim = anchorEmb.length;
95
- const gradient = new Array(dim).fill(0);
96
- // Pull anchor towards positive
97
- for (let i = 0; i < dim; i++) {
98
- gradient[i] += lr * (positiveEmb[i] - anchorEmb[i]);
99
- }
100
- // Push anchor away from negative
101
- for (let i = 0; i < dim; i++) {
102
- gradient[i] -= lr * 0.5 * (negativeEmb[i] - anchorEmb[i]);
103
- }
104
- return gradient;
105
- }
106
- /**
107
- * Contrastive Trainer for RuvLTRA models
108
- *
109
- * Implements triplet loss and InfoNCE loss for embedding fine-tuning.
110
- */
111
- class ContrastiveTrainer {
112
- constructor(config) {
113
- this.triplets = [];
114
- this.history = [];
115
- this.agentEmbeddings = new Map();
116
- this.config = { ...DEFAULT_CONTRASTIVE_CONFIG, ...config };
117
- }
118
- /**
119
- * Add a training triplet
120
- */
121
- addTriplet(anchor, anchorEmb, positive, positiveEmb, negative, negativeEmb, isHard = false) {
122
- this.triplets.push({
123
- anchor,
124
- anchorEmb,
125
- positive,
126
- positiveEmb,
127
- negative,
128
- negativeEmb,
129
- isHard,
130
- });
131
- }
132
- /**
133
- * Add agent embedding for reference
134
- */
135
- addAgentEmbedding(agentName, embedding) {
136
- this.agentEmbeddings.set(agentName, embedding);
137
- }
138
- /**
139
- * Get all agent embeddings
140
- */
141
- getAgentEmbeddings() {
142
- return this.agentEmbeddings;
143
- }
144
- /**
145
- * Get triplet count
146
- */
147
- getTripletCount() {
148
- return this.triplets.length;
149
- }
150
- /**
151
- * Simulate training (compute losses without actual backprop)
152
- * In a full implementation, this would use proper gradient descent
153
- */
154
- train() {
155
- const startTime = Date.now();
156
- const { epochs, batchSize, margin } = this.config;
157
- if (this.triplets.length === 0) {
158
- return {
159
- tripletCount: 0,
160
- finalLoss: 0,
161
- initialLoss: 0,
162
- improvement: 0,
163
- history: [],
164
- durationMs: 0,
165
- };
166
- }
167
- for (let epoch = 0; epoch < epochs; epoch++) {
168
- let epochLoss = 0;
169
- let batchCount = 0;
170
- // Shuffle triplets
171
- const shuffled = [...this.triplets].sort(() => Math.random() - 0.5);
172
- for (let i = 0; i < shuffled.length; i += batchSize) {
173
- const batch = shuffled.slice(i, i + batchSize);
174
- let batchLoss = 0;
175
- for (const triplet of batch) {
176
- const loss = tripletLoss(triplet.anchorEmb, triplet.positiveEmb, triplet.negativeEmb, margin);
177
- batchLoss += loss;
178
- }
179
- epochLoss += batchLoss / batch.length;
180
- batchCount++;
181
- }
182
- const avgLoss = epochLoss / batchCount;
183
- this.history.push({ epoch: epoch + 1, loss: avgLoss });
184
- }
185
- const initialLoss = this.history[0]?.loss || 0;
186
- const finalLoss = this.history[this.history.length - 1]?.loss || 0;
187
- const improvement = initialLoss > 0 ? (1 - finalLoss / initialLoss) * 100 : 0;
188
- return {
189
- tripletCount: this.triplets.length,
190
- finalLoss,
191
- initialLoss,
192
- improvement,
193
- history: this.history,
194
- durationMs: Date.now() - startTime,
195
- };
196
- }
197
- /**
198
- * Export training data for external fine-tuning tools
199
- */
200
- exportTrainingData(outputPath) {
201
- const outDir = outputPath || this.config.outputPath;
202
- if (!(0, fs_1.existsSync)(outDir)) {
203
- (0, fs_1.mkdirSync)(outDir, { recursive: true });
204
- }
205
- // JSONL format for fine-tuning
206
- const jsonlData = this.triplets.map(t => ({
207
- anchor: t.anchor,
208
- positive: t.positive,
209
- negative: t.negative,
210
- isHard: t.isHard,
211
- }));
212
- // CSV format for analysis
213
- const csvData = [
214
- 'anchor,positive,negative,is_hard',
215
- ...this.triplets.map(t => `"${t.anchor.replace(/"/g, '""')}",${t.positive},${t.negative},${t.isHard}`),
216
- ].join('\n');
217
- // Embedding matrix for direct training
218
- const embeddingData = {
219
- anchors: this.triplets.map(t => t.anchorEmb),
220
- positives: this.triplets.map(t => t.positiveEmb),
221
- negatives: this.triplets.map(t => t.negativeEmb),
222
- labels: this.triplets.map(t => t.positive),
223
- };
224
- (0, fs_1.writeFileSync)((0, path_1.join)(outDir, 'triplets.jsonl'), jsonlData.map(item => JSON.stringify(item)).join('\n'));
225
- (0, fs_1.writeFileSync)((0, path_1.join)(outDir, 'triplets.csv'), csvData);
226
- (0, fs_1.writeFileSync)((0, path_1.join)(outDir, 'embeddings.json'), JSON.stringify(embeddingData, null, 2));
227
- return outDir;
228
- }
229
- /**
230
- * Generate LoRA adapter configuration
231
- */
232
- generateLoRAConfig(outputPath) {
233
- const outDir = outputPath || this.config.outputPath;
234
- const loraConfig = {
235
- model_type: 'qwen2',
236
- base_model: 'Qwen/Qwen2.5-0.5B',
237
- output_dir: outDir,
238
- lora_r: 8,
239
- lora_alpha: 16,
240
- lora_dropout: 0.05,
241
- target_modules: ['q_proj', 'v_proj', 'k_proj', 'o_proj'],
242
- learning_rate: this.config.learningRate,
243
- num_train_epochs: this.config.epochs,
244
- per_device_train_batch_size: this.config.batchSize,
245
- gradient_accumulation_steps: 4,
246
- warmup_ratio: 0.1,
247
- loss_type: 'triplet',
248
- margin: this.config.margin,
249
- temperature: this.config.temperature,
250
- train_data: (0, path_1.join)(outDir, 'triplets.jsonl'),
251
- eval_data: (0, path_1.join)(outDir, 'eval.jsonl'),
252
- };
253
- if (!(0, fs_1.existsSync)(outDir)) {
254
- (0, fs_1.mkdirSync)(outDir, { recursive: true });
255
- }
256
- (0, fs_1.writeFileSync)((0, path_1.join)(outDir, 'lora_config.json'), JSON.stringify(loraConfig, null, 2));
257
- return loraConfig;
258
- }
259
- /**
260
- * Generate training script for external tools
261
- */
262
- generateTrainingScript(outputPath) {
263
- const outDir = outputPath || this.config.outputPath;
264
- const script = `#!/bin/bash
265
- # RuvLTRA Fine-tuning Script
266
- # Prerequisites: pip install transformers peft accelerate
267
-
268
- set -e
269
-
270
- MODEL_PATH="${outDir}"
271
- BASE_MODEL="Qwen/Qwen2.5-0.5B"
272
-
273
- echo "=== RuvLTRA Contrastive Fine-tuning ==="
274
- echo "Base model: $BASE_MODEL"
275
- echo "Output: $MODEL_PATH"
276
-
277
- # Check for training data
278
- if [ ! -f "$MODEL_PATH/triplets.jsonl" ]; then
279
- echo "Error: Training data not found at $MODEL_PATH/triplets.jsonl"
280
- exit 1
281
- fi
282
-
283
- # Install dependencies if needed
284
- python3 -c "import transformers, peft" 2>/dev/null || {
285
- echo "Installing dependencies..."
286
- pip install transformers peft accelerate sentencepiece
287
- }
288
-
289
- # Fine-tune with LoRA
290
- python3 << 'PYTHON'
291
- import json
292
- import torch
293
- from pathlib import Path
294
- from transformers import AutoModelForCausalLM, AutoTokenizer
295
- from peft import LoraConfig, get_peft_model, TaskType
296
-
297
- # Load config
298
- config_path = Path("${outDir}/lora_config.json")
299
- with open(config_path) as f:
300
- config = json.load(f)
301
-
302
- print(f"Loading base model: {config['base_model']}")
303
-
304
- # Load model and tokenizer
305
- tokenizer = AutoTokenizer.from_pretrained(config['base_model'])
306
- model = AutoModelForCausalLM.from_pretrained(
307
- config['base_model'],
308
- torch_dtype=torch.float16,
309
- device_map='auto'
310
- )
311
-
312
- # Configure LoRA
313
- lora_config = LoraConfig(
314
- r=config['lora_r'],
315
- lora_alpha=config['lora_alpha'],
316
- lora_dropout=config['lora_dropout'],
317
- target_modules=config['target_modules'],
318
- task_type=TaskType.CAUSAL_LM,
319
- )
320
-
321
- model = get_peft_model(model, lora_config)
322
- model.print_trainable_parameters()
323
-
324
- print("Model ready for fine-tuning!")
325
- print(f"Training data: {config['train_data']}")
326
- print("Note: Full training requires GPU. This script validates the setup.")
327
- PYTHON
328
-
329
- echo ""
330
- echo "=== Setup Complete ==="
331
- echo "To train on GPU, run the full training pipeline."
332
- echo "Training data exported to: $MODEL_PATH/triplets.jsonl"
333
- `;
334
- if (!(0, fs_1.existsSync)(outDir)) {
335
- (0, fs_1.mkdirSync)(outDir, { recursive: true });
336
- }
337
- const scriptPath = (0, path_1.join)(outDir, 'train.sh');
338
- (0, fs_1.writeFileSync)(scriptPath, script);
339
- return scriptPath;
340
- }
341
- /**
342
- * Get training history
343
- */
344
- getHistory() {
345
- return [...this.history];
346
- }
347
- /**
348
- * Reset trainer
349
- */
350
- reset() {
351
- this.triplets = [];
352
- this.history = [];
353
- }
354
- }
355
- exports.ContrastiveTrainer = ContrastiveTrainer;
356
- /**
357
- * Agent Training Data for Claude Code Router
358
- */
359
- exports.AGENT_TRAINING_DATA = {
360
- coder: {
361
- description: 'Implementation specialist for writing clean, efficient code. Handles coding tasks, feature implementation, and code generation.',
362
- keywords: ['implement', 'code', 'write', 'build', 'create', 'develop', 'function', 'class', 'component', 'feature'],
363
- examples: [
364
- 'Implement a binary search function',
365
- 'Write a React component for user registration',
366
- 'Create a REST API endpoint for user authentication',
367
- 'Build a caching layer for the database queries',
368
- ],
369
- confusing_with: ['refactorer', 'debugger'],
370
- },
371
- tester: {
372
- description: 'Testing specialist for writing and maintaining tests. Creates unit tests, integration tests, and ensures code quality through testing.',
373
- keywords: ['test', 'unit test', 'integration test', 'coverage', 'mock', 'assertion', 'spec', 'jest', 'pytest'],
374
- examples: [
375
- 'Write unit tests for the authentication module',
376
- 'Add integration tests for the payment gateway',
377
- 'Create test coverage for the user service',
378
- 'Write e2e tests for the checkout flow',
379
- ],
380
- confusing_with: ['reviewer'],
381
- },
382
- reviewer: {
383
- description: 'Code review specialist for analyzing code quality, identifying issues, and suggesting improvements.',
384
- keywords: ['review', 'analyze', 'check', 'inspect', 'audit', 'evaluate', 'assess', 'critique'],
385
- examples: [
386
- 'Review the pull request for code quality',
387
- 'Check the code for potential security vulnerabilities',
388
- 'Analyze the implementation for best practices',
389
- 'Evaluate the architecture decisions in this PR',
390
- ],
391
- confusing_with: ['tester', 'security-architect'],
392
- },
393
- researcher: {
394
- description: 'Research specialist for investigating technologies, gathering information, and analyzing options.',
395
- keywords: ['research', 'investigate', 'explore', 'analyze', 'study', 'compare', 'evaluate', 'learn'],
396
- examples: [
397
- 'Research best practices for React state management',
398
- 'Investigate the performance issues in the dashboard',
399
- 'Compare different authentication strategies',
400
- 'Study the codebase architecture for the new feature',
401
- ],
402
- confusing_with: ['planner'],
403
- },
404
- architect: {
405
- description: 'System architect for designing software architecture, making technical decisions, and planning system structure.',
406
- keywords: ['design', 'architect', 'structure', 'plan', 'schema', 'model', 'pattern', 'system'],
407
- examples: [
408
- 'Design the database schema for user profiles',
409
- 'Plan the architecture for real-time notifications',
410
- 'Create a system design for the microservices migration',
411
- 'Design the API structure for the new product catalog',
412
- ],
413
- confusing_with: ['planner'],
414
- },
415
- debugger: {
416
- description: 'Debugging specialist for finding and fixing bugs, analyzing errors, and troubleshooting issues.',
417
- keywords: ['debug', 'fix', 'bug', 'error', 'issue', 'crash', 'exception', 'troubleshoot'],
418
- examples: [
419
- 'Fix the null pointer exception in the login handler',
420
- 'Debug the memory leak in the WebSocket handler',
421
- 'Troubleshoot the race condition in the payment processor',
422
- 'Find the root cause of the intermittent test failures',
423
- ],
424
- confusing_with: ['coder'],
425
- },
426
- 'security-architect': {
427
- description: 'Security specialist for auditing code security, identifying vulnerabilities, and implementing security measures.',
428
- keywords: ['security', 'vulnerability', 'xss', 'sql injection', 'auth', 'encryption', 'audit', 'penetration'],
429
- examples: [
430
- 'Audit the API endpoints for XSS vulnerabilities',
431
- 'Review the authentication flow for security issues',
432
- 'Implement input validation for the user forms',
433
- 'Check for SQL injection vulnerabilities in the search',
434
- ],
435
- confusing_with: ['reviewer'],
436
- },
437
- documenter: {
438
- description: 'Documentation specialist for writing technical documentation, comments, and API docs.',
439
- keywords: ['document', 'comment', 'jsdoc', 'readme', 'docs', 'explain', 'describe', 'annotate'],
440
- examples: [
441
- 'Write JSDoc comments for the utility functions',
442
- 'Create README documentation for the new module',
443
- 'Document the API endpoints with examples',
444
- 'Add inline comments explaining the algorithm',
445
- ],
446
- confusing_with: ['api-docs'],
447
- },
448
- refactorer: {
449
- description: 'Refactoring specialist for improving code structure, cleaning up technical debt, and modernizing codebases.',
450
- keywords: ['refactor', 'clean', 'restructure', 'modernize', 'improve', 'simplify', 'extract', 'rename'],
451
- examples: [
452
- 'Refactor the payment module to use async/await',
453
- 'Clean up the legacy authentication code',
454
- 'Extract common logic into a shared utility',
455
- 'Simplify the complex conditional logic in checkout',
456
- ],
457
- confusing_with: ['coder'],
458
- },
459
- optimizer: {
460
- description: 'Performance optimization specialist for improving speed, reducing memory usage, and optimizing queries.',
461
- keywords: ['optimize', 'performance', 'speed', 'memory', 'cache', 'index', 'query', 'latency'],
462
- examples: [
463
- 'Optimize the database queries for the dashboard',
464
- 'Improve the page load time for the homepage',
465
- 'Add caching to reduce API response times',
466
- 'Reduce memory usage in the image processing pipeline',
467
- ],
468
- confusing_with: ['researcher'],
469
- },
470
- devops: {
471
- description: 'DevOps specialist for CI/CD pipelines, deployment automation, and infrastructure management.',
472
- keywords: ['deploy', 'ci/cd', 'pipeline', 'docker', 'kubernetes', 'terraform', 'aws', 'infrastructure'],
473
- examples: [
474
- 'Set up the CI/CD pipeline for the microservices',
475
- 'Configure Docker containers for the application',
476
- 'Deploy the application to the staging environment',
477
- 'Create Terraform scripts for the AWS infrastructure',
478
- ],
479
- confusing_with: [],
480
- },
481
- 'api-docs': {
482
- description: 'API documentation specialist for creating OpenAPI specs, Swagger documentation, and API references.',
483
- keywords: ['openapi', 'swagger', 'api docs', 'endpoint', 'specification', 'schema', 'rest'],
484
- examples: [
485
- 'Generate OpenAPI documentation for the REST API',
486
- 'Create Swagger specs for the user endpoints',
487
- 'Document the API authentication requirements',
488
- 'Update the API reference with new endpoints',
489
- ],
490
- confusing_with: ['documenter'],
491
- },
492
- planner: {
493
- description: 'Project planning specialist for creating task plans, sprint planning, and roadmap development.',
494
- keywords: ['plan', 'roadmap', 'sprint', 'milestone', 'timeline', 'estimate', 'breakdown', 'prioritize'],
495
- examples: [
496
- 'Create a sprint plan for the next two weeks',
497
- 'Break down the feature into smaller tasks',
498
- 'Estimate the effort for the migration project',
499
- 'Prioritize the bug fixes for the release',
500
- ],
501
- confusing_with: ['architect', 'researcher'],
502
- },
503
- };
504
- /**
505
- * Generate training dataset from agent data
506
- */
507
- function generateTrainingDataset() {
508
- const examples = [];
509
- for (const [agent, data] of Object.entries(exports.AGENT_TRAINING_DATA)) {
510
- // Add direct examples
511
- for (const example of data.examples) {
512
- examples.push({
513
- task: example,
514
- agent,
515
- complexity: 'medium',
516
- });
517
- }
518
- // Generate variations with keywords
519
- for (const keyword of data.keywords) {
520
- examples.push({
521
- task: `${keyword} a solution for the authentication system`,
522
- agent,
523
- complexity: 'low',
524
- });
525
- }
526
- // Add confusing pairs for hard negatives
527
- if (data.confusing_with) {
528
- for (const confusingAgent of data.confusing_with) {
529
- for (const example of data.examples.slice(0, 2)) {
530
- examples.push({
531
- task: example,
532
- agent,
533
- complexity: 'hard',
534
- confusing_with: confusingAgent,
535
- });
536
- }
537
- }
538
- }
539
- }
540
- return examples;
541
- }
542
- /**
543
- * Generate contrastive pairs for training
544
- */
545
- function generateContrastivePairs() {
546
- const pairs = [];
547
- const agents = Object.keys(exports.AGENT_TRAINING_DATA);
548
- for (const [agent, data] of Object.entries(exports.AGENT_TRAINING_DATA)) {
549
- for (const example of data.examples) {
550
- // Hard negatives from confusing agents
551
- if (data.confusing_with) {
552
- for (const negAgent of data.confusing_with) {
553
- pairs.push({
554
- anchor: example,
555
- positive: agent,
556
- negative: negAgent,
557
- isHard: true,
558
- });
559
- }
560
- }
561
- // Random negatives
562
- const randomNegs = agents.filter(a => a !== agent).slice(0, 2);
563
- for (const negAgent of randomNegs) {
564
- pairs.push({
565
- anchor: example,
566
- positive: agent,
567
- negative: negAgent,
568
- isHard: false,
569
- });
570
- }
571
- }
572
- }
573
- return pairs;
574
- }
575
- /**
576
- * Get dataset statistics
577
- */
578
- function getDatasetStats() {
579
- const examples = generateTrainingDataset();
580
- const pairs = generateContrastivePairs();
581
- const agents = Object.keys(exports.AGENT_TRAINING_DATA);
582
- return {
583
- totalExamples: examples.length,
584
- contrastivePairs: pairs.length,
585
- agentTypes: agents.length,
586
- agents,
587
- };
588
- }
589
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhc3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29udHJhc3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EyQkc7OztBQTRHSCw0Q0FTQztBQU1ELGtDQVNDO0FBS0Qsa0NBaUJDO0FBS0QsMENBb0JDO0FBbWVELDBEQXNDQztBQUtELDREQXFDQztBQUtELDBDQVdDO0FBcHZCRCwyQkFBMEQ7QUFDMUQsK0JBQTRCO0FBeUY1Qjs7R0FFRztBQUNILE1BQU0sMEJBQTBCLEdBQWdDO0lBQzlELE1BQU0sRUFBRSxFQUFFO0lBQ1YsU0FBUyxFQUFFLEVBQUU7SUFDYixZQUFZLEVBQUUsTUFBTTtJQUNwQixNQUFNLEVBQUUsR0FBRztJQUNYLFdBQVcsRUFBRSxJQUFJO0lBQ2pCLGlCQUFpQixFQUFFLEdBQUc7SUFDdEIsVUFBVSxFQUFFLG1CQUFtQjtDQUNoQyxDQUFDO0FBRUY7O0dBRUc7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxDQUFZLEVBQUUsQ0FBWTtJQUN6RCxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLE1BQU07UUFBRSxPQUFPLENBQUMsQ0FBQztJQUNoRCxJQUFJLEdBQUcsR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ2xDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDbEMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkIsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckIs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QUssR0FBRyx3QkFBd0IsRUFBRSxDQUFDO0lBQ3pDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQW1CLENBQUMsQ0FBQztJQUVoRCxPQUFPO1FBQ0wsYUFBYSxFQUFFLFFBQVEsQ0FBQyxNQUFNO1FBQzlCLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxNQUFNO1FBQzlCLFVBQVUsRUFBRSxNQUFNLENBQUMsTUFBTTtRQUN6QixNQUFNO0tBQ1AsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbnRyYXN0aXZlIEZpbmUtdHVuaW5nIGZvciBSdXZMVFJBIENsYXVkZSBDb2RlIFJvdXRlclxuICpcbiAqIFVzZXMgdHJpcGxldCBsb3NzIHRvIGZpbmUtdHVuZSBlbWJlZGRpbmdzOlxuICogLSBBbmNob3I6IHRhc2sgZGVzY3JpcHRpb25cbiAqIC0gUG9zaXRpdmU6IGNvcnJlY3QgYWdlbnQgZGVzY3JpcHRpb25cbiAqIC0gTmVnYXRpdmU6IHdyb25nIGFnZW50IGRlc2NyaXB0aW9uIChoYXJkIG5lZ2F0aXZlKVxuICpcbiAqIEdvYWw6IG1pbmltaXplIGRpc3RhbmNlKGFuY2hvciwgcG9zaXRpdmUpIGFuZCBtYXhpbWl6ZSBkaXN0YW5jZShhbmNob3IsIG5lZ2F0aXZlKVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBDb250cmFzdGl2ZVRyYWluZXIsIHRyaXBsZXRMb3NzLCBpbmZvTkNFTG9zcyB9IGZyb20gJ0BydXZlY3Rvci9ydXZsbG0nO1xuICpcbiAqIGNvbnN0IHRyYWluZXIgPSBuZXcgQ29udHJhc3RpdmVUcmFpbmVyKHtcbiAqICAgZXBvY2hzOiAxMCxcbiAqICAgYmF0Y2hTaXplOiAxNixcbiAqICAgbWFyZ2luOiAwLjUsXG4gKiB9KTtcbiAqXG4gKiAvLyBBZGQgdHJpcGxldHNcbiAqIHRyYWluZXIuYWRkVHJpcGxldChhbmNob3JFbWIsIHBvc2l0aXZlRW1iLCBuZWdhdGl2ZUVtYiwgdHJ1ZSk7XG4gKlxuICogLy8gVHJhaW4gYW5kIGV4cG9ydFxuICogY29uc3QgcmVzdWx0cyA9IHRyYWluZXIudHJhaW4oKTtcbiAqIHRyYWluZXIuZXhwb3J0VHJhaW5pbmdEYXRhKCcuL291dHB1dCcpO1xuICogYGBgXG4gKi9cblxuaW1wb3J0IHsgd3JpdGVGaWxlU3luYywgbWtkaXJTeW5jLCBleGlzdHNTeW5jIH0gZnJvbSAnZnMnO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgRW1iZWRkaW5nIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogQ29udHJhc3RpdmUgdHJhaW5pbmcgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRyYXN0aXZlQ29uZmlnIHtcbiAgLyoqIE51bWJlciBvZiB0cmFpbmluZyBlcG9jaHMgKGRlZmF1bHQ6IDEwKSAqL1xuICBlcG9jaHM/OiBudW1iZXI7XG4gIC8qKiBCYXRjaCBzaXplIChkZWZhdWx0OiAxNikgKi9cbiAgYmF0Y2hTaXplPzogbnVtYmVyO1xuICAvKiogTGVhcm5pbmcgcmF0ZSAoZGVmYXVsdDogMC4wMDAxKSAqL1xuICBsZWFybmluZ1JhdGU/OiBudW1iZXI7XG4gIC8qKiBUcmlwbGV0IGxvc3MgbWFyZ2luIChkZWZhdWx0OiAwLjUpICovXG4gIG1hcmdpbj86IG51bWJlcjtcbiAgLyoqIEluZm9OQ0UgdGVtcGVyYXR1cmUgKGRlZmF1bHQ6IDAuMDcpICovXG4gIHRlbXBlcmF0dXJlPzogbnVtYmVyO1xuICAvKiogUmF0aW8gb2YgaGFyZCBuZWdhdGl2ZXMgKGRlZmF1bHQ6IDAuNykgKi9cbiAgaGFyZE5lZ2F0aXZlUmF0aW8/OiBudW1iZXI7XG4gIC8qKiBPdXRwdXQgZGlyZWN0b3J5IGZvciB0cmFpbmluZyBkYXRhICovXG4gIG91dHB1dFBhdGg/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVHJhaW5pbmcgdHJpcGxldFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRyYWluaW5nVHJpcGxldCB7XG4gIC8qKiBBbmNob3IgZW1iZWRkaW5nICh0YXNrKSAqL1xuICBhbmNob3I6IHN0cmluZztcbiAgYW5jaG9yRW1iOiBFbWJlZGRpbmc7XG4gIC8qKiBQb3NpdGl2ZSBleGFtcGxlIChjb3JyZWN0IGFnZW50KSAqL1xuICBwb3NpdGl2ZTogc3RyaW5nO1xuICBwb3NpdGl2ZUVtYjogRW1iZWRkaW5nO1xuICAvKiogTmVnYXRpdmUgZXhhbXBsZSAod3JvbmcgYWdlbnQpICovXG4gIG5lZ2F0aXZlOiBzdHJpbmc7XG4gIG5lZ2F0aXZlRW1iOiBFbWJlZGRpbmc7XG4gIC8qKiBXaGV0aGVyIHRoaXMgaXMgYSBoYXJkIG5lZ2F0aXZlICovXG4gIGlzSGFyZDogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBUcmFpbmluZyBoaXN0b3J5IGVudHJ5XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHJhaW5pbmdIaXN0b3J5RW50cnkge1xuICBlcG9jaDogbnVtYmVyO1xuICBsb3NzOiBudW1iZXI7XG59XG5cbi8qKlxuICogQ29udHJhc3RpdmUgdHJhaW5pbmcgcmVzdWx0c1xuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRyYXN0aXZlVHJhaW5pbmdSZXN1bHQge1xuICAvKiogVG90YWwgdHJpcGxldHMgdHJhaW5lZCBvbiAqL1xuICB0cmlwbGV0Q291bnQ6IG51bWJlcjtcbiAgLyoqIEZpbmFsIGxvc3MgdmFsdWUgKi9cbiAgZmluYWxMb3NzOiBudW1iZXI7XG4gIC8qKiBJbml0aWFsIGxvc3MgdmFsdWUgKi9cbiAgaW5pdGlhbExvc3M6IG51bWJlcjtcbiAgLyoqIEltcHJvdmVtZW50IHBlcmNlbnRhZ2UgKi9cbiAgaW1wcm92ZW1lbnQ6IG51bWJlcjtcbiAgLyoqIFRyYWluaW5nIGhpc3RvcnkgKi9cbiAgaGlzdG9yeTogVHJhaW5pbmdIaXN0b3J5RW50cnlbXTtcbiAgLyoqIER1cmF0aW9uIGluIG1zICovXG4gIGR1cmF0aW9uTXM6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBMb1JBIGNvbmZpZ3VyYXRpb24gZm9yIGZpbmUtdHVuaW5nXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTG9SQUV4cG9ydENvbmZpZyB7XG4gIG1vZGVsX3R5cGU6IHN0cmluZztcbiAgYmFzZV9tb2RlbDogc3RyaW5nO1xuICBvdXRwdXRfZGlyOiBzdHJpbmc7XG4gIGxvcmFfcjogbnVtYmVyO1xuICBsb3JhX2FscGhhOiBudW1iZXI7XG4gIGxvcmFfZHJvcG91dDogbnVtYmVyO1xuICB0YXJnZXRfbW9kdWxlczogc3RyaW5nW107XG4gIGxlYXJuaW5nX3JhdGU6IG51bWJlcjtcbiAgbnVtX3RyYWluX2Vwb2NoczogbnVtYmVyO1xuICBwZXJfZGV2aWNlX3RyYWluX2JhdGNoX3NpemU6IG51bWJlcjtcbiAgZ3JhZGllbnRfYWNjdW11bGF0aW9uX3N0ZXBzOiBudW1iZXI7XG4gIHdhcm11cF9yYXRpbzogbnVtYmVyO1xuICBsb3NzX3R5cGU6IHN0cmluZztcbiAgbWFyZ2luOiBudW1iZXI7XG4gIHRlbXBlcmF0dXJlOiBudW1iZXI7XG4gIHRyYWluX2RhdGE6IHN0cmluZztcbiAgZXZhbF9kYXRhOiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGVmYXVsdCBjb250cmFzdGl2ZSBjb25maWdcbiAqL1xuY29uc3QgREVGQVVMVF9DT05UUkFTVElWRV9DT05GSUc6IFJlcXVpcmVkPENvbnRyYXN0aXZlQ29uZmlnPiA9IHtcbiAgZXBvY2hzOiAxMCxcbiAgYmF0Y2hTaXplOiAxNixcbiAgbGVhcm5pbmdSYXRlOiAwLjAwMDEsXG4gIG1hcmdpbjogMC41LFxuICB0ZW1wZXJhdHVyZTogMC4wNyxcbiAgaGFyZE5lZ2F0aXZlUmF0aW86IDAuNyxcbiAgb3V0cHV0UGF0aDogJy4vdHJhaW5pbmctb3V0cHV0Jyxcbn07XG5cbi8qKlxuICogQ29tcHV0ZSBjb3NpbmUgc2ltaWxhcml0eSBiZXR3ZWVuIHR3byBlbWJlZGRpbmdzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3NpbmVTaW1pbGFyaXR5KGE6IEVtYmVkZGluZywgYjogRW1iZWRkaW5nKTogbnVtYmVyIHtcbiAgaWYgKCFhIHx8ICFiIHx8IGEubGVuZ3RoICE9PSBiLmxlbmd0aCkgcmV0dXJuIDA7XG4gIGxldCBkb3QgPSAwLCBub3JtQSA9IDAsIG5vcm1CID0gMDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgZG90ICs9IGFbaV0gKiBiW2ldO1xuICAgIG5vcm1BICs9IGFbaV0gKiBhW2ldO1xuICAgIG5vcm1CICs9IGJbaV0gKiBiW2ldO1xuICB9XG4gIHJldHVybiBkb3QgLyAoTWF0aC5zcXJ0KG5vcm1BKSAqIE1hdGguc3FydChub3JtQikgfHwgMSk7XG59XG5cbi8qKlxuICogQ29tcHV0ZSB0cmlwbGV0IGxvc3NcbiAqIEwgPSBtYXgoMCwgbWFyZ2luICsgZChhbmNob3IsIHBvc2l0aXZlKSAtIGQoYW5jaG9yLCBuZWdhdGl2ZSkpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmlwbGV0TG9zcyhcbiAgYW5jaG9yRW1iOiBFbWJlZGRpbmcsXG4gIHBvc2l0aXZlRW1iOiBFbWJlZGRpbmcsXG4gIG5lZ2F0aXZlRW1iOiBFbWJlZGRpbmcsXG4gIG1hcmdpbjogbnVtYmVyID0gMC41XG4pOiBudW1iZXIge1xuICBjb25zdCBwb3NEaXN0ID0gMSAtIGNvc2luZVNpbWlsYXJpdHkoYW5jaG9yRW1iLCBwb3NpdGl2ZUVtYik7XG4gIGNvbnN0IG5lZ0Rpc3QgPSAxIC0gY29zaW5lU2ltaWxhcml0eShhbmNob3JFbWIsIG5lZ2F0aXZlRW1iKTtcbiAgcmV0dXJuIE1hdGgubWF4KDAsIG1hcmdpbiArIHBvc0Rpc3QgLSBuZWdEaXN0KTtcbn1cblxuLyoqXG4gKiBDb21wdXRlIEluZm9OQ0UgbG9zcyAoY29udHJhc3RpdmUpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmZvTkNFTG9zcyhcbiAgYW5jaG9yRW1iOiBFbWJlZGRpbmcsXG4gIHBvc2l0aXZlRW1iOiBFbWJlZGRpbmcsXG4gIG5lZ2F0aXZlRW1iczogRW1iZWRkaW5nW10sXG4gIHRlbXBlcmF0dXJlOiBudW1iZXIgPSAwLjA3XG4pOiBudW1iZXIge1xuICBjb25zdCBwb3NTaW0gPSBjb3NpbmVTaW1pbGFyaXR5KGFuY2hvckVtYiwgcG9zaXRpdmVFbWIpIC8gdGVtcGVyYXR1cmU7XG4gIGNvbnN0IG5lZ1NpbXMgPSBuZWdhdGl2ZUVtYnMubWFwKG5lZyA9PiBjb3NpbmVTaW1pbGFyaXR5KGFuY2hvckVtYiwgbmVnKSAvIHRlbXBlcmF0dXJlKTtcblxuICAvLyBTb2Z0bWF4IGRlbm9taW5hdG9yXG4gIGNvbnN0IG1heFNpbSA9IE1hdGgubWF4KHBvc1NpbSwgLi4ubmVnU2ltcyk7XG4gIGNvbnN0IGV4cFBvcyA9IE1hdGguZXhwKHBvc1NpbSAtIG1heFNpbSk7XG4gIGNvbnN0IGV4cE5lZ3MgPSBuZWdTaW1zLm1hcChzaW0gPT4gTWF0aC5leHAoc2ltIC0gbWF4U2ltKSk7XG4gIGNvbnN0IGRlbm9taW5hdG9yID0gZXhwUG9zICsgZXhwTmVncy5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcblxuICAvLyBDcm9zcy1lbnRyb3B5IGxvc3NcbiAgcmV0dXJuIC1NYXRoLmxvZyhleHBQb3MgLyBkZW5vbWluYXRvcik7XG59XG5cbi8qKlxuICogQ29tcHV0ZSBncmFkaWVudCBmb3IgZW1iZWRkaW5nIHVwZGF0ZSAoc2ltcGxpZmllZClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVHcmFkaWVudChcbiAgYW5jaG9yRW1iOiBFbWJlZGRpbmcsXG4gIHBvc2l0aXZlRW1iOiBFbWJlZGRpbmcsXG4gIG5lZ2F0aXZlRW1iOiBFbWJlZGRpbmcsXG4gIGxyOiBudW1iZXIgPSAwLjAwMDFcbik6IEVtYmVkZGluZyB7XG4gIGNvbnN0IGRpbSA9IGFuY2hvckVtYi5sZW5ndGg7XG4gIGNvbnN0IGdyYWRpZW50OiBudW1iZXJbXSA9IG5ldyBBcnJheShkaW0pLmZpbGwoMCk7XG5cbiAgLy8gUHVsbCBhbmNob3IgdG93YXJkcyBwb3NpdGl2ZVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbTsgaSsrKSB7XG4gICAgZ3JhZGllbnRbaV0gKz0gbHIgKiAocG9zaXRpdmVFbWJbaV0gLSBhbmNob3JFbWJbaV0pO1xuICB9XG5cbiAgLy8gUHVzaCBhbmNob3IgYXdheSBmcm9tIG5lZ2F0aXZlXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGltOyBpKyspIHtcbiAgICBncmFkaWVudFtpXSAtPSBsciAqIDAuNSAqIChuZWdhdGl2ZUVtYltpXSAtIGFuY2hvckVtYltpXSk7XG4gIH1cblxuICByZXR1cm4gZ3JhZGllbnQ7XG59XG5cbi8qKlxuICogQ29udHJhc3RpdmUgVHJhaW5lciBmb3IgUnV2TFRSQSBtb2RlbHNcbiAqXG4gKiBJbXBsZW1lbnRzIHRyaXBsZXQgbG9zcyBhbmQgSW5mb05DRSBsb3NzIGZvciBlbWJlZGRpbmcgZmluZS10dW5pbmcuXG4gKi9cbmV4cG9ydCBjbGFzcyBDb250cmFzdGl2ZVRyYWluZXIge1xuICBwcml2YXRlIGNvbmZpZzogUmVxdWlyZWQ8Q29udHJhc3RpdmVDb25maWc+O1xuICBwcml2YXRlIHRyaXBsZXRzOiBUcmFpbmluZ1RyaXBsZXRbXSA9IFtdO1xuICBwcml2YXRlIGhpc3Rvcnk6IFRyYWluaW5nSGlzdG9yeUVudHJ5W10gPSBbXTtcbiAgcHJpdmF0ZSBhZ2VudEVtYmVkZGluZ3M6IE1hcDxzdHJpbmcsIEVtYmVkZGluZz4gPSBuZXcgTWFwKCk7XG5cbiAgY29uc3RydWN0b3IoY29uZmlnPzogQ29udHJhc3RpdmVDb25maWcpIHtcbiAgICB0aGlzLmNvbmZpZyA9IHsgLi4uREVGQVVMVF9DT05UUkFTVElWRV9DT05GSUcsIC4uLmNvbmZpZyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIHRyYWluaW5nIHRyaXBsZXRcbiAgICovXG4gIGFkZFRyaXBsZXQoXG4gICAgYW5jaG9yOiBzdHJpbmcsXG4gICAgYW5jaG9yRW1iOiBFbWJlZGRpbmcsXG4gICAgcG9zaXRpdmU6IHN0cmluZyxcbiAgICBwb3NpdGl2ZUVtYjogRW1iZWRkaW5nLFxuICAgIG5lZ2F0aXZlOiBzdHJpbmcsXG4gICAgbmVnYXRpdmVFbWI6IEVtYmVkZGluZyxcbiAgICBpc0hhcmQ6IGJvb2xlYW4gPSBmYWxzZVxuICApOiB2b2lkIHtcbiAgICB0aGlzLnRyaXBsZXRzLnB1c2goe1xuICAgICAgYW5jaG9yLFxuICAgICAgYW5jaG9yRW1iLFxuICAgICAgcG9zaXRpdmUsXG4gICAgICBwb3NpdGl2ZUVtYixcbiAgICAgIG5lZ2F0aXZlLFxuICAgICAgbmVnYXRpdmVFbWIsXG4gICAgICBpc0hhcmQsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGFnZW50IGVtYmVkZGluZyBmb3IgcmVmZXJlbmNlXG4gICAqL1xuICBhZGRBZ2VudEVtYmVkZGluZyhhZ2VudE5hbWU6IHN0cmluZywgZW1iZWRkaW5nOiBFbWJlZGRpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmFnZW50RW1iZWRkaW5ncy5zZXQoYWdlbnROYW1lLCBlbWJlZGRpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgYWdlbnQgZW1iZWRkaW5nc1xuICAgKi9cbiAgZ2V0QWdlbnRFbWJlZGRpbmdzKCk6IE1hcDxzdHJpbmcsIEVtYmVkZGluZz4ge1xuICAgIHJldHVybiB0aGlzLmFnZW50RW1iZWRkaW5ncztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdHJpcGxldCBjb3VudFxuICAgKi9cbiAgZ2V0VHJpcGxldENvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMudHJpcGxldHMubGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIFNpbXVsYXRlIHRyYWluaW5nIChjb21wdXRlIGxvc3NlcyB3aXRob3V0IGFjdHVhbCBiYWNrcHJvcClcbiAgICogSW4gYSBmdWxsIGltcGxlbWVudGF0aW9uLCB0aGlzIHdvdWxkIHVzZSBwcm9wZXIgZ3JhZGllbnQgZGVzY2VudFxuICAgKi9cbiAgdHJhaW4oKTogQ29udHJhc3RpdmVUcmFpbmluZ1Jlc3VsdCB7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCB7IGVwb2NocywgYmF0Y2hTaXplLCBtYXJnaW4gfSA9IHRoaXMuY29uZmlnO1xuXG4gICAgaWYgKHRoaXMudHJpcGxldHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0cmlwbGV0Q291bnQ6IDAsXG4gICAgICAgIGZpbmFsTG9zczogMCxcbiAgICAgICAgaW5pdGlhbExvc3M6IDAsXG4gICAgICAgIGltcHJvdmVtZW50OiAwLFxuICAgICAgICBoaXN0b3J5OiBbXSxcbiAgICAgICAgZHVyYXRpb25NczogMCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZm9yIChsZXQgZXBvY2ggPSAwOyBlcG9jaCA8IGVwb2NoczsgZXBvY2grKykge1xuICAgICAgbGV0IGVwb2NoTG9zcyA9IDA7XG4gICAgICBsZXQgYmF0Y2hDb3VudCA9IDA7XG5cbiAgICAgIC8vIFNodWZmbGUgdHJpcGxldHNcbiAgICAgIGNvbnN0IHNodWZmbGVkID0gWy4uLnRoaXMudHJpcGxldHNdLnNvcnQoKCkgPT4gTWF0aC5yYW5kb20oKSAtIDAuNSk7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2h1ZmZsZWQubGVuZ3RoOyBpICs9IGJhdGNoU2l6ZSkge1xuICAgICAgICBjb25zdCBiYXRjaCA9IHNodWZmbGVkLnNsaWNlKGksIGkgKyBiYXRjaFNpemUpO1xuICAgICAgICBsZXQgYmF0Y2hMb3NzID0gMDtcblxuICAgICAgICBmb3IgKGNvbnN0IHRyaXBsZXQgb2YgYmF0Y2gpIHtcbiAgICAgICAgICBjb25zdCBsb3NzID0gdHJpcGxldExvc3MoXG4gICAgICAgICAgICB0cmlwbGV0LmFuY2hvckVtYixcbiAgICAgICAgICAgIHRyaXBsZXQucG9zaXRpdmVFbWIsXG4gICAgICAgICAgICB0cmlwbGV0Lm5lZ2F0aXZlRW1iLFxuICAgICAgICAgICAgbWFyZ2luXG4gICAgICAgICAgKTtcbiAgICAgICAgICBiYXRjaExvc3MgKz0gbG9zcztcbiAgICAgICAgfVxuXG4gICAgICAgIGVwb2NoTG9zcyArPSBiYXRjaExvc3MgLyBiYXRjaC5sZW5ndGg7XG4gICAgICAgIGJhdGNoQ291bnQrKztcbiAgICAgIH1cblxuICAgICAgY29uc3QgYXZnTG9zcyA9IGVwb2NoTG9zcyAvIGJhdGNoQ291bnQ7XG4gICAgICB0aGlzLmhpc3RvcnkucHVzaCh7IGVwb2NoOiBlcG9jaCArIDEsIGxvc3M6IGF2Z0xvc3MgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgaW5pdGlhbExvc3MgPSB0aGlzLmhpc3RvcnlbMF0/Lmxvc3MgfHwgMDtcbiAgICBjb25zdCBmaW5hbExvc3MgPSB0aGlzLmhpc3RvcnlbdGhpcy5oaXN0b3J5Lmxlbmd0aCAtIDFdPy5sb3NzIHx8IDA7XG4gICAgY29uc3QgaW1wcm92ZW1lbnQgPSBpbml0aWFsTG9zcyA+IDAgPyAoMSAtIGZpbmFsTG9zcyAvIGluaXRpYWxMb3NzKSAqIDEwMCA6IDA7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHJpcGxldENvdW50OiB0aGlzLnRyaXBsZXRzLmxlbmd0aCxcbiAgICAgIGZpbmFsTG9zcyxcbiAgICAgIGluaXRpYWxMb3NzLFxuICAgICAgaW1wcm92ZW1lbnQsXG4gICAgICBoaXN0b3J5OiB0aGlzLmhpc3RvcnksXG4gICAgICBkdXJhdGlvbk1zOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRXhwb3J0IHRyYWluaW5nIGRhdGEgZm9yIGV4dGVybmFsIGZpbmUtdHVuaW5nIHRvb2xzXG4gICAqL1xuICBleHBvcnRUcmFpbmluZ0RhdGEob3V0cHV0UGF0aD86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3Qgb3V0RGlyID0gb3V0cHV0UGF0aCB8fCB0aGlzLmNvbmZpZy5vdXRwdXRQYXRoO1xuXG4gICAgaWYgKCFleGlzdHNTeW5jKG91dERpcikpIHtcbiAgICAgIG1rZGlyU3luYyhvdXREaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIH1cblxuICAgIC8vIEpTT05MIGZvcm1hdCBmb3IgZmluZS10dW5pbmdcbiAgICBjb25zdCBqc29ubERhdGEgPSB0aGlzLnRyaXBsZXRzLm1hcCh0ID0+ICh7XG4gICAgICBhbmNob3I6IHQuYW5jaG9yLFxuICAgICAgcG9zaXRpdmU6IHQucG9zaXRpdmUsXG4gICAgICBuZWdhdGl2ZTogdC5uZWdhdGl2ZSxcbiAgICAgIGlzSGFyZDogdC5pc0hhcmQsXG4gICAgfSkpO1xuXG4gICAgLy8gQ1NWIGZvcm1hdCBmb3IgYW5hbHlzaXNcbiAgICBjb25zdCBjc3ZEYXRhID0gW1xuICAgICAgJ2FuY2hvcixwb3NpdGl2ZSxuZWdhdGl2ZSxpc19oYXJkJyxcbiAgICAgIC4uLnRoaXMudHJpcGxldHMubWFwKHQgPT5cbiAgICAgICAgYFwiJHt0LmFuY2hvci5yZXBsYWNlKC9cIi9nLCAnXCJcIicpfVwiLCR7dC5wb3NpdGl2ZX0sJHt0Lm5lZ2F0aXZlfSwke3QuaXNIYXJkfWBcbiAgICAgICksXG4gICAgXS5qb2luKCdcXG4nKTtcblxuICAgIC8vIEVtYmVkZGluZyBtYXRyaXggZm9yIGRpcmVjdCB0cmFpbmluZ1xuICAgIGNvbnN0IGVtYmVkZGluZ0RhdGEgPSB7XG4gICAgICBhbmNob3JzOiB0aGlzLnRyaXBsZXRzLm1hcCh0ID0+IHQuYW5jaG9yRW1iKSxcbiAgICAgIHBvc2l0aXZlczogdGhpcy50cmlwbGV0cy5tYXAodCA9PiB0LnBvc2l0aXZlRW1iKSxcbiAgICAgIG5lZ2F0aXZlczogdGhpcy50cmlwbGV0cy5tYXAodCA9PiB0Lm5lZ2F0aXZlRW1iKSxcbiAgICAgIGxhYmVsczogdGhpcy50cmlwbGV0cy5tYXAodCA9PiB0LnBvc2l0aXZlKSxcbiAgICB9O1xuXG4gICAgd3JpdGVGaWxlU3luYyhqb2luKG91dERpciwgJ3RyaXBsZXRzLmpzb25sJyksIGpzb25sRGF0YS5tYXAoaXRlbSA9PiBKU09OLnN0cmluZ2lmeShpdGVtKSkuam9pbignXFxuJykpO1xuICAgIHdyaXRlRmlsZVN5bmMoam9pbihvdXREaXIsICd0cmlwbGV0cy5jc3YnKSwgY3N2RGF0YSk7XG4gICAgd3JpdGVGaWxlU3luYyhqb2luKG91dERpciwgJ2VtYmVkZGluZ3MuanNvbicpLCBKU09OLnN0cmluZ2lmeShlbWJlZGRpbmdEYXRhLCBudWxsLCAyKSk7XG5cbiAgICByZXR1cm4gb3V0RGlyO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIExvUkEgYWRhcHRlciBjb25maWd1cmF0aW9uXG4gICAqL1xuICBnZW5lcmF0ZUxvUkFDb25maWcob3V0cHV0UGF0aD86IHN0cmluZyk6IExvUkFFeHBvcnRDb25maWcge1xuICAgIGNvbnN0IG91dERpciA9IG91dHB1dFBhdGggfHwgdGhpcy5jb25maWcub3V0cHV0UGF0aDtcblxuICAgIGNvbnN0IGxvcmFDb25maWc6IExvUkFFeHBvcnRDb25maWcgPSB7XG4gICAgICBtb2RlbF90eXBlOiAncXdlbjInLFxuICAgICAgYmFzZV9tb2RlbDogJ1F3ZW4vUXdlbjIuNS0wLjVCJyxcbiAgICAgIG91dHB1dF9kaXI6IG91dERpcixcbiAgICAgIGxvcmFfcjogOCxcbiAgICAgIGxvcmFfYWxwaGE6IDE2LFxuICAgICAgbG9yYV9kcm9wb3V0OiAwLjA1LFxuICAgICAgdGFyZ2V0X21vZHVsZXM6IFsncV9wcm9qJywgJ3ZfcHJvaicsICdrX3Byb2onLCAnb19wcm9qJ10sXG4gICAgICBsZWFybmluZ19yYXRlOiB0aGlzLmNvbmZpZy5sZWFybmluZ1JhdGUsXG4gICAgICBudW1fdHJhaW5fZXBvY2hzOiB0aGlzLmNvbmZpZy5lcG9jaHMsXG4gICAgICBwZXJfZGV2aWNlX3RyYWluX2JhdGNoX3NpemU6IHRoaXMuY29uZmlnLmJhdGNoU2l6ZSxcbiAgICAgIGdyYWRpZW50X2FjY3VtdWxhdGlvbl9zdGVwczogNCxcbiAgICAgIHdhcm11cF9yYXRpbzogMC4xLFxuICAgICAgbG9zc190eXBlOiAndHJpcGxldCcsXG4gICAgICBtYXJnaW46IHRoaXMuY29uZmlnLm1hcmdpbixcbiAgICAgIHRlbXBlcmF0dXJlOiB0aGlzLmNvbmZpZy50ZW1wZXJhdHVyZSxcbiAgICAgIHRyYWluX2RhdGE6IGpvaW4ob3V0RGlyLCAndHJpcGxldHMuanNvbmwnKSxcbiAgICAgIGV2YWxfZGF0YTogam9pbihvdXREaXIsICdldmFsLmpzb25sJyksXG4gICAgfTtcblxuICAgIGlmICghZXhpc3RzU3luYyhvdXREaXIpKSB7XG4gICAgICBta2RpclN5bmMob3V0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB9XG5cbiAgICB3cml0ZUZpbGVTeW5jKGpvaW4ob3V0RGlyLCAnbG9yYV9jb25maWcuanNvbicpLCBKU09OLnN0cmluZ2lmeShsb3JhQ29uZmlnLCBudWxsLCAyKSk7XG4gICAgcmV0dXJuIGxvcmFDb25maWc7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgdHJhaW5pbmcgc2NyaXB0IGZvciBleHRlcm5hbCB0b29sc1xuICAgKi9cbiAgZ2VuZXJhdGVUcmFpbmluZ1NjcmlwdChvdXRwdXRQYXRoPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBvdXREaXIgPSBvdXRwdXRQYXRoIHx8IHRoaXMuY29uZmlnLm91dHB1dFBhdGg7XG5cbiAgICBjb25zdCBzY3JpcHQgPSBgIyEvYmluL2Jhc2hcbiMgUnV2TFRSQSBGaW5lLXR1bmluZyBTY3JpcHRcbiMgUHJlcmVxdWlzaXRlczogcGlwIGluc3RhbGwgdHJhbnNmb3JtZXJzIHBlZnQgYWNjZWxlcmF0ZVxuXG5zZXQgLWVcblxuTU9ERUxfUEFUSD1cIiR7b3V0RGlyfVwiXG5CQVNFX01PREVMPVwiUXdlbi9Rd2VuMi41LTAuNUJcIlxuXG5lY2hvIFwiPT09IFJ1dkxUUkEgQ29udHJhc3RpdmUgRmluZS10dW5pbmcgPT09XCJcbmVjaG8gXCJCYXNlIG1vZGVsOiAkQkFTRV9NT0RFTFwiXG5lY2hvIFwiT3V0cHV0OiAkTU9ERUxfUEFUSFwiXG5cbiMgQ2hlY2sgZm9yIHRyYWluaW5nIGRhdGFcbmlmIFsgISAtZiBcIiRNT0RFTF9QQVRIL3RyaXBsZXRzLmpzb25sXCIgXTsgdGhlblxuICBlY2hvIFwiRXJyb3I6IFRyYWluaW5nIGRhdGEgbm90IGZvdW5kIGF0ICRNT0RFTF9QQVRIL3RyaXBsZXRzLmpzb25sXCJcbiAgZXhpdCAxXG5maVxuXG4jIEluc3RhbGwgZGVwZW5kZW5jaWVzIGlmIG5lZWRlZFxucHl0aG9uMyAtYyBcImltcG9ydCB0cmFuc2Zvcm1lcnMsIHBlZnRcIiAyPi9kZXYvbnVsbCB8fCB7XG4gIGVjaG8gXCJJbnN0YWxsaW5nIGRlcGVuZGVuY2llcy4uLlwiXG4gIHBpcCBpbnN0YWxsIHRyYW5zZm9ybWVycyBwZWZ0IGFjY2VsZXJhdGUgc2VudGVuY2VwaWVjZVxufVxuXG4jIEZpbmUtdHVuZSB3aXRoIExvUkFcbnB5dGhvbjMgPDwgJ1BZVEhPTidcbmltcG9ydCBqc29uXG5pbXBvcnQgdG9yY2hcbmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aFxuZnJvbSB0cmFuc2Zvcm1lcnMgaW1wb3J0IEF1dG9Nb2RlbEZvckNhdXNhbExNLCBBdXRvVG9rZW5pemVyXG5mcm9tIHBlZnQgaW1wb3J0IExvcmFDb25maWcsIGdldF9wZWZ0X21vZGVsLCBUYXNrVHlwZVxuXG4jIExvYWQgY29uZmlnXG5jb25maWdfcGF0aCA9IFBhdGgoXCIke291dERpcn0vbG9yYV9jb25maWcuanNvblwiKVxud2l0aCBvcGVuKGNvbmZpZ19wYXRoKSBhcyBmOlxuICAgIGNvbmZpZyA9IGpzb24ubG9hZChmKVxuXG5wcmludChmXCJMb2FkaW5nIGJhc2UgbW9kZWw6IHtjb25maWdbJ2Jhc2VfbW9kZWwnXX1cIilcblxuIyBMb2FkIG1vZGVsIGFuZCB0b2tlbml6ZXJcbnRva2VuaXplciA9IEF1dG9Ub2tlbml6ZXIuZnJvbV9wcmV0cmFpbmVkKGNvbmZpZ1snYmFzZV9tb2RlbCddKVxubW9kZWwgPSBBdXRvTW9kZWxGb3JDYXVzYWxMTS5mcm9tX3ByZXRyYWluZWQoXG4gICAgY29uZmlnWydiYXNlX21vZGVsJ10sXG4gICAgdG9yY2hfZHR5cGU9dG9yY2guZmxvYXQxNixcbiAgICBkZXZpY2VfbWFwPSdhdXRvJ1xuKVxuXG4jIENvbmZpZ3VyZSBMb1JBXG5sb3JhX2NvbmZpZyA9IExvcmFDb25maWcoXG4gICAgcj1jb25maWdbJ2xvcmFfciddLFxuICAgIGxvcmFfYWxwaGE9Y29uZmlnWydsb3JhX2FscGhhJ10sXG4gICAgbG9yYV9kcm9wb3V0PWNvbmZpZ1snbG9yYV9kcm9wb3V0J10sXG4gICAgdGFyZ2V0X21vZHVsZXM9Y29uZmlnWyd0YXJnZXRfbW9kdWxlcyddLFxuICAgIHRhc2tfdHlwZT1UYXNrVHlwZS5DQVVTQUxfTE0sXG4pXG5cbm1vZGVsID0gZ2V0X3BlZnRfbW9kZWwobW9kZWwsIGxvcmFfY29uZmlnKVxubW9kZWwucHJpbnRfdHJhaW5hYmxlX3BhcmFtZXRlcnMoKVxuXG5wcmludChcIk1vZGVsIHJlYWR5IGZvciBmaW5lLXR1bmluZyFcIilcbnByaW50KGZcIlRyYWluaW5nIGRhdGE6IHtjb25maWdbJ3RyYWluX2RhdGEnXX1cIilcbnByaW50KFwiTm90ZTogRnVsbCB0cmFpbmluZyByZXF1aXJlcyBHUFUuIFRoaXMgc2NyaXB0IHZhbGlkYXRlcyB0aGUgc2V0dXAuXCIpXG5QWVRIT05cblxuZWNobyBcIlwiXG5lY2hvIFwiPT09IFNldHVwIENvbXBsZXRlID09PVwiXG5lY2hvIFwiVG8gdHJhaW4gb24gR1BVLCBydW4gdGhlIGZ1bGwgdHJhaW5pbmcgcGlwZWxpbmUuXCJcbmVjaG8gXCJUcmFpbmluZyBkYXRhIGV4cG9ydGVkIHRvOiAkTU9ERUxfUEFUSC90cmlwbGV0cy5qc29ubFwiXG5gO1xuXG4gICAgaWYgKCFleGlzdHNTeW5jKG91dERpcikpIHtcbiAgICAgIG1rZGlyU3luYyhvdXREaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IHNjcmlwdFBhdGggPSBqb2luKG91dERpciwgJ3RyYWluLnNoJyk7XG4gICAgd3JpdGVGaWxlU3luYyhzY3JpcHRQYXRoLCBzY3JpcHQpO1xuXG4gICAgcmV0dXJuIHNjcmlwdFBhdGg7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRyYWluaW5nIGhpc3RvcnlcbiAgICovXG4gIGdldEhpc3RvcnkoKTogVHJhaW5pbmdIaXN0b3J5RW50cnlbXSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLmhpc3RvcnldO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRyYWluZXJcbiAgICovXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMudHJpcGxldHMgPSBbXTtcbiAgICB0aGlzLmhpc3RvcnkgPSBbXTtcbiAgfVxufVxuXG4vKipcbiAqIEFnZW50IFRyYWluaW5nIERhdGEgSW50ZXJmYWNlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWdlbnRUcmFpbmluZ0RhdGEge1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICBrZXl3b3Jkczogc3RyaW5nW107XG4gIGV4YW1wbGVzOiBzdHJpbmdbXTtcbiAgY29uZnVzaW5nX3dpdGg/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUcmFpbmluZyBFeGFtcGxlIEludGVyZmFjZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRyYWluaW5nRXhhbXBsZSB7XG4gIHRhc2s6IHN0cmluZztcbiAgYWdlbnQ6IHN0cmluZztcbiAgY29tcGxleGl0eT86IHN0cmluZztcbiAgY29uZnVzaW5nX3dpdGg/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGF0YXNldCBTdGF0aXN0aWNzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YXNldFN0YXRzIHtcbiAgdG90YWxFeGFtcGxlczogbnVtYmVyO1xuICBjb250cmFzdGl2ZVBhaXJzOiBudW1iZXI7XG4gIGFnZW50VHlwZXM6IG51bWJlcjtcbiAgYWdlbnRzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBBZ2VudCBUcmFpbmluZyBEYXRhIGZvciBDbGF1ZGUgQ29kZSBSb3V0ZXJcbiAqL1xuZXhwb3J0IGNvbnN0IEFHRU5UX1RSQUlOSU5HX0RBVEE6IFJlY29yZDxzdHJpbmcsIEFnZW50VHJhaW5pbmdEYXRhPiA9IHtcbiAgY29kZXI6IHtcbiAgICBkZXNjcmlwdGlvbjogJ0ltcGxlbWVudGF0aW9uIHNwZWNpYWxpc3QgZm9yIHdyaXRpbmcgY2xlYW4sIGVmZmljaWVudCBjb2RlLiBIYW5kbGVzIGNvZGluZyB0YXNrcywgZmVhdHVyZSBpbXBsZW1lbnRhdGlvbiwgYW5kIGNvZGUgZ2VuZXJhdGlvbi4nLFxuICAgIGtleXdvcmRzOiBbJ2ltcGxlbWVudCcsICdjb2RlJywgJ3dyaXRlJywgJ2J1aWxkJywgJ2NyZWF0ZScsICdkZXZlbG9wJywgJ2Z1bmN0aW9uJywgJ2NsYXNzJywgJ2NvbXBvbmVudCcsICdmZWF0dXJlJ10sXG4gICAgZXhhbXBsZXM6IFtcbiAgICAgICdJbXBsZW1lbnQgYSBiaW5hcnkgc2VhcmNoIGZ1bmN0aW9uJyxcbiAgICAgICdXcml0ZSBhIFJlYWN0IGNvbXBvbmVudCBmb3IgdXNlciByZWdpc3RyYXRpb24nLFxuICAgICAgJ0NyZWF0ZSBhIFJFU1QgQVBJIGVuZHBvaW50IGZvciB1c2VyIGF1dGhlbnRpY2F0aW9uJyxcbiAgICAgICdCdWlsZCBhIGNhY2hpbmcgbGF5ZXIgZm9yIHRoZSBkYXRhYmFzZSBxdWVyaWVzJyxcbiAgICBdLFxuICAgIGNvbmZ1c2luZ193aXRoOiBbJ3JlZmFjdG9yZXInLCAnZGVidWdnZXInXSxcbiAgfSxcbiAgdGVzdGVyOiB7XG4gICAgZGVzY3JpcHRpb246ICdUZXN0aW5nIHNwZWNpYWxpc3QgZm9yIHdyaXRpbmcgYW5kIG1haW50YWluaW5nIHRlc3RzLiBDcmVhdGVzIHVuaXQgdGVzdHMsIGludGVncmF0aW9uIHRlc3RzLCBhbmQgZW5zdXJlcyBjb2RlIHF1YWxpdHkgdGhyb3VnaCB0ZXN0aW5nLicsXG4gICAga2V5d29yZHM6IFsndGVzdCcsICd1bml0IHRlc3QnLCAnaW50ZWdyYXRpb24gdGVzdCcsICdjb3ZlcmFnZScsICdtb2NrJywgJ2Fzc2VydGlvbicsICdzcGVjJywgJ2plc3QnLCAncHl0ZXN0J10sXG4gICAgZXhhbXBsZXM6IFtcbiAgICAgICdXcml0ZSB1bml0IHRlc3RzIGZvciB0aGUgYXV0aGVudGljYXRpb24gbW9kdWxlJyxcbiAgICAgICdBZGQgaW50ZWdyYXRpb24gdGVzdHMgZm9yIHRoZSBwYXltZW50IGdhdGV3YXknLFxuICAgICAgJ0NyZWF0ZSB0ZXN0IGNvdmVyYWdlIGZvciB0aGUgdXNlciBzZXJ2aWNlJyxcbiAgICAgICdXcml0ZSBlMmUgdGVzdHMgZm9yIHRoZSBjaGVja291dCBmbG93JyxcbiAgICBdLFxuICAgIGNvbmZ1c2luZ193aXRoOiBbJ3Jldmlld2VyJ10sXG4gIH0sXG4gIHJldmlld2VyOiB7XG4gICAgZGVzY3JpcHRpb246ICdDb2RlIHJldmlldyBzcGVjaWFsaXN0IGZvciBhbmFseXppbmcgY29kZSBxdWFsaXR5LCBpZGVudGlmeWluZyBpc3N1ZXMsIGFuZCBzdWdnZXN0aW5nIGltcHJvdmVtZW50cy4nLFxuICAgIGtleXdvcmRzOiBbJ3JldmlldycsICdhbmFseXplJywgJ2NoZWNrJywgJ2luc3BlY3QnLCAnYXVkaXQnLCAnZXZhbHVhdGUnLCAnYXNzZXNzJywgJ2NyaXRpcXVlJ10sXG4gICAgZXhhbXBsZXM6IFtcbiAgICAgICdSZXZpZXcgdGhlIHB1bGwgcmVxdWVzdCBmb3IgY29kZSBxdWFsaXR5JyxcbiAgICAgICdDaGVjayB0aGUgY29kZSBmb3IgcG90ZW50aWFsIHNlY3VyaXR5IHZ1bG5lcmFiaWxpdGllcycsXG4gICAgICAnQW5hbHl6ZSB0aGUgaW1wbGVtZW50YXRpb24gZm9yIGJlc3QgcHJhY3RpY2VzJyxcbiAgICAgICdFdmFsdWF0ZSB0aGUgYXJjaGl0ZWN0dXJlIGRlY2lzaW9ucyBpbiB0aGlzIFBSJyxcbiAgICBdLFxuICAgIGNvbmZ1c2luZ193aXRoOiBbJ3Rlc3RlcicsICdzZWN1cml0eS1hcmNoaXRlY3QnXSxcbiAgfSxcbiAgcmVzZWFyY2hlcjoge1xuICAgIGRlc2NyaXB0aW9uOiAnUmVzZWFyY2ggc3BlY2lhbGlzdCBmb3IgaW52ZXN0aWdhdGluZyB0ZWNobm9sb2dpZXMsIGdhdGhlcmluZyBpbmZvcm1hdGlvbiwgYW5kIGFuYWx5emluZyBvcHRpb25zLicsXG4gICAga2V5d29yZHM6IFsncmVzZWFyY2gnLCAnaW52ZXN0aWdhdGUnLCAnZXhwbG9yZScsICdhbmFseXplJywgJ3N0dWR5JywgJ2NvbXBhcmUnLCAnZXZhbHVhdGUnLCAnbGVhcm4nXSxcbiAgICBleGFtcGxlczogW1xuICAgICAgJ1Jlc2VhcmNoIGJlc3QgcHJhY3RpY2VzIGZvciBSZWFjdCBzdGF0ZSBtYW5hZ2VtZW50JyxcbiAgICAgICdJbnZlc3RpZ2F0ZSB0aGUgcGVyZm9ybWFuY2UgaXNzdWVzIGluIHRoZSBkYXNoYm9hcmQnLFxuICAgICAgJ0NvbXBhcmUgZGlmZmVyZW50IGF1dGhlbnRpY2F0aW9uIHN0cmF0ZWdpZXMnLFxuICAgICAgJ1N0dWR5IHRoZSBjb2RlYmFzZSBhcmNoaXRlY3R1cmUgZm9yIHRoZSBuZXcgZmVhdHVyZScsXG4gICAgXSxcbiAgICBjb25mdXNpbmdfd2l0aDogWydwbGFubmVyJ10sXG4gIH0sXG4gIGFyY2hpdGVjdDoge1xuICAgIGRlc2NyaXB0aW9uOiAnU3lzdGVtIGFyY2hpdGVjdCBmb3IgZGVzaWduaW5nIHNvZnR3YXJlIGFyY2hpdGVjdHVyZSwgbWFraW5nIHRlY2huaWNhbCBkZWNpc2lvbnMsIGFuZCBwbGFubmluZyBzeXN0ZW0gc3RydWN0dXJlLicsXG4gICAga2V5d29yZHM6IFsnZGVzaWduJywgJ2FyY2hpdGVjdCcsICdzdHJ1Y3R1cmUnLCAncGxhbicsICdzY2hlbWEnLCAnbW9kZWwnLCAncGF0dGVybicsICdzeXN0ZW0nXSxcbiAgICBleGFtcGxlczogW1xuICAgICAgJ0Rlc2lnbiB0aGUgZGF0YWJhc2Ugc2NoZW1hIGZvciB1c2VyIHByb2ZpbGVzJyxcbiAgICAgICdQbGFuIHRoZSBhcmNoaXRlY3R1cmUgZm9yIHJlYWwtdGltZSBub3RpZmljYXRpb25zJyxcbiAgICAgICdDcmVhdGUgYSBzeXN0ZW0gZGVzaWduIGZvciB0aGUgbWljcm9zZXJ2aWNlcyBtaWdyYXRpb24nLFxuICAgICAgJ0Rlc2lnbiB0aGUgQVBJIHN0cnVjdHVyZSBmb3IgdGhlIG5ldyBwcm9kdWN0IGNhdGFsb2cnLFxuICAgIF0sXG4gICAgY29uZnVzaW5nX3dpdGg6IFsncGxhbm5lciddLFxuICB9LFxuICBkZWJ1Z2dlcjoge1xuICAgIGRlc2NyaXB0aW9uOiAnRGVidWdnaW5nIHNwZWNpYWxpc3QgZm9yIGZpbmRpbmcgYW5kIGZpeGluZyBidWdzLCBhbmFseXppbmcgZXJyb3JzLCBhbmQgdHJvdWJsZXNob290aW5nIGlzc3Vlcy4nLFxuICAgIGtleXdvcmRzOiBbJ2RlYnVnJywgJ2ZpeCcsICdidWcnLCAnZXJyb3InLCAnaXNzdWUnLCAnY3Jhc2gnLCAnZXhjZXB0aW9uJywgJ3Ryb3VibGVzaG9vdCddLFxuICAgIGV4YW1wbGVzOiBbXG4gICAgICAnRml4IHRoZSBudWxsIHBvaW50ZXIgZXhjZXB0aW9uIGluIHRoZSBsb2dpbiBoYW5kbGVyJyxcbiAgICAgICdEZWJ1ZyB0aGUgbWVtb3J5IGxlYWsgaW4gdGhlIFdlYlNvY2tldCBoYW5kbGVyJyxcbiAgICAgICdUcm91Ymxlc2hvb3QgdGhlIHJhY2UgY29uZGl0aW9uIGluIHRoZSBwYXltZW50IHByb2Nlc3NvcicsXG4gICAgICAnRmluZCB0aGUgcm9vdCBjYXVzZSBvZiB0aGUgaW50ZXJtaXR0ZW50IHRlc3QgZmFpbHVyZXMnLFxuICAgIF0sXG4gICAgY29uZnVzaW5nX3dpdGg6IFsnY29kZXInXSxcbiAgfSxcbiAgJ3NlY3VyaXR5LWFyY2hpdGVjdCc6IHtcbiAgICBkZXNjcmlwdGlvbjogJ1NlY3VyaXR5IHNwZWNpYWxpc3QgZm9yIGF1ZGl0aW5nIGNvZGUgc2VjdXJpdHksIGlkZW50aWZ5aW5nIHZ1bG5lcmFiaWxpdGllcywgYW5kIGltcGxlbWVudGluZyBzZWN1cml0eSBtZWFzdXJlcy4nLFxuICAgIGtleXdvcmRzOiBbJ3NlY3VyaXR5JywgJ3Z1bG5lcmFiaWxpdHknLCAneHNzJywgJ3NxbCBpbmplY3Rpb24nLCAnYXV0aCcsICdlbmNyeXB0aW9uJywgJ2F1ZGl0JywgJ3BlbmV0cmF0aW9uJ10sXG4gICAgZXhhbXBsZXM6IFtcbiAgICAgICdBdWRpdCB0aGUgQVBJIGVuZHBvaW50cyBmb3IgWFNTIHZ1bG5lcmFiaWxpdGllcycsXG4gICAgICAnUmV2aWV3IHRoZSBhdXRoZW50aWNhdGlvbiBmbG93IGZvciBzZWN1cml0eSBpc3N1ZXMnLFxuICAgICAgJ0ltcGxlbWVudCBpbnB1dCB2YWxpZGF0aW9uIGZvciB0aGUgdXNlciBmb3JtcycsXG4gICAgICAnQ2hlY2sgZm9yIFNRTCBpbmplY3Rpb24gdnVsbmVyYWJpbGl0aWVzIGluIHRoZSBzZWFyY2gnLFxuICAgIF0sXG4gICAgY29uZnVzaW5nX3dpdGg6IFsncmV2aWV3ZXInXSxcbiAgfSxcbiAgZG9jdW1lbnRlcjoge1xuICAgIGRlc2NyaXB0aW9uOiAnRG9jdW1lbnRhdGlvbiBzcGVjaWFsaXN0IGZvciB3cml0aW5nIHRlY2huaWNhbCBkb2N1bWVudGF0aW9uLCBjb21tZW50cywgYW5kIEFQSSBkb2NzLicsXG4gICAga2V5d29yZHM6IFsnZG9jdW1lbnQnLCAnY29tbWVudCcsICdqc2RvYycsICdyZWFkbWUnLCAnZG9jcycsICdleHBsYWluJywgJ2Rlc2NyaWJlJywgJ2Fubm90YXRlJ10sXG4gICAgZXhhbXBsZXM6IFtcbiAgICAgICdXcml0ZSBKU0RvYyBjb21tZW50cyBmb3IgdGhlIHV0aWxpdHkgZnVuY3Rpb25zJyxcbiAgICAgICdDcmVhdGUgUkVBRE1FIGRvY3VtZW50YXRpb24gZm9yIHRoZSBuZXcgbW9kdWxlJyxcbiAgICAgICdEb2N1bWVudCB0aGUgQVBJIGVuZHBvaW50cyB3aXRoIGV4YW1wbGVzJyxcbiAgICAgICdBZGQgaW5saW5lIGNvbW1lbnRzIGV4cGxhaW5pbmcgdGhlIGFsZ29yaXRobScsXG4gICAgXSxcbiAgICBjb25mdXNpbmdfd2l0aDogWydhcGktZG9jcyddLFxuICB9LFxuICByZWZhY3RvcmVyOiB7XG4gICAgZGVzY3JpcHRpb246ICdSZWZhY3RvcmluZyBzcGVjaWFsaXN0IGZvciBpbXByb3ZpbmcgY29kZSBzdHJ1Y3R1cmUsIGNsZWFuaW5nIHVwIHRlY2huaWNhbCBkZWJ0LCBhbmQgbW9kZXJuaXppbmcgY29kZWJhc2VzLicsXG4gICAga2V5d29yZHM6IFsncmVmYWN0b3InLCAnY2xlYW4nLCAncmVzdHJ1Y3R1cmUnLCAnbW9kZXJuaXplJywgJ2ltcHJvdmUnLCAnc2ltcGxpZnknLCAnZXh0cmFjdCcsICdyZW5hbWUnXSxcbiAgICBleGFtcGxlczogW1xuICAgICAgJ1JlZmFjdG9yIHRoZSBwYXltZW50IG1vZHVsZSB0byB1c2UgYXN5bmMvYXdhaXQnLFxuICAgICAgJ0NsZWFuIHVwIHRoZSBsZWdhY3kgYXV0aGVudGljYXRpb24gY29kZScsXG4gICAgICAnRXh0cmFjdCBjb21tb24gbG9naWMgaW50byBhIHNoYXJlZCB1dGlsaXR5JyxcbiAgICAgICdTaW1wbGlmeSB0aGUgY29tcGxleCBjb25kaXRpb25hbCBsb2dpYyBpbiBjaGVja291dCcsXG4gICAgXSxcbiAgICBjb25mdXNpbmdfd2l0aDogWydjb2RlciddLFxuICB9LFxuICBvcHRpbWl6ZXI6IHtcbiAgICBkZXNjcmlwdGlvbjogJ1BlcmZvcm1hbmNlIG9wdGltaXphdGlvbiBzcGVjaWFsaXN0IGZvciBpbXByb3Zpbmcgc3BlZWQsIHJlZHVjaW5nIG1lbW9yeSB1c2FnZSwgYW5kIG9wdGltaXppbmcgcXVlcmllcy4nLFxuICAgIGtleXdvcmRzOiBbJ29wdGltaXplJywgJ3BlcmZvcm1hbmNlJywgJ3NwZWVkJywgJ21lbW9yeScsICdjYWNoZScsICdpbmRleCcsICdxdWVyeScsICdsYXRlbmN5J10sXG4gICAgZXhhbXBsZXM6IFtcbiAgICAgICdPcHRpbWl6ZSB0aGUgZGF0YWJhc2UgcXVlcmllcyBmb3IgdGhlIGRhc2hib2FyZCcsXG4gICAgICAnSW1wcm92ZSB0aGUgcGFnZSBsb2FkIHRpbWUgZm9yIHRoZSBob21lcGFnZScsXG4gICAgICAnQWRkIGNhY2hpbmcgdG8gcmVkdWNlIEFQSSByZXNwb25zZSB0aW1lcycsXG4gICAgICAnUmVkdWNlIG1lbW9yeSB1c2FnZSBpbiB0aGUgaW1hZ2UgcHJvY2Vzc2luZyBwaXBlbGluZScsXG4gICAgXSxcbiAgICBjb25mdXNpbmdfd2l0aDogWydyZXNlYXJjaGVyJ10sXG4gIH0sXG4gIGRldm9wczoge1xuICAgIGRlc2NyaXB0aW9uOiAnRGV2T3BzIHNwZWNpYWxpc3QgZm9yIENJL0NEIHBpcGVsaW5lcywgZGVwbG95bWVudCBhdXRvbWF0aW9uLCBhbmQgaW5mcmFzdHJ1Y3R1cmUgbWFuYWdlbWVudC4nLFxuICAgIGtleXdvcmRzOiBbJ2RlcGxveScsICdjaS9jZCcsICdwaXBlbGluZScsICdkb2NrZXInLCAna3ViZXJuZXRlcycsICd0ZXJyYWZvcm0nLCAnYXdzJywgJ2luZnJhc3RydWN0dXJlJ10sXG4gICAgZXhhbXBsZXM6IFtcbiAgICAgICdTZXQgdXAgdGhlIENJL0NEIHBpcGVsaW5lIGZvciB0aGUgbWljcm9zZXJ2aWNlcycsXG4gICAgICAnQ29uZmlndXJlIERvY2tlciBjb250YWluZXJzIGZvciB0aGUgYXBwbGljYXRpb24nLFxuICAgICAgJ0RlcGxveSB0aGUgYXBwbGljYXRpb24gdG8gdGhlIHN0YWdpbmcgZW52aXJvbm1lbnQnLFxuICAgICAgJ0NyZWF0ZSBUZXJyYWZvcm0gc2NyaXB0cyBmb3IgdGhlIEFXUyBpbmZyYXN0cnVjdHVyZScsXG4gICAgXSxcbiAgICBjb25mdXNpbmdfd2l0aDogW10sXG4gIH0sXG4gICdhcGktZG9jcyc6IHtcbiAgICBkZXNjcmlwdGlvbjogJ0FQSSBkb2N1bWVudGF0aW9uIHNwZWNpYWxpc3QgZm9yIGNyZWF0aW5nIE9wZW5BUEkgc3BlY3MsIFN3YWdnZXIgZG9jdW1lbnRhdGlvbiwgYW5kIEFQSSByZWZlcmVuY2VzLicsXG4gICAga2V5d29yZHM6IFsnb3BlbmFwaScsICdzd2FnZ2VyJywgJ2FwaSBkb2NzJywgJ2VuZHBvaW50JywgJ3NwZWNpZmljYXRpb24nLCAnc2NoZW1hJywgJ3Jlc3QnXSxcbiAgICBleGFtcGxlczogW1xuICAgICAgJ0dlbmVyYXRlIE9wZW5BUEkgZG9jdW1lbnRhdGlvbiBmb3IgdGhlIFJFU1QgQVBJJyxcbiAgICAgICdDcmVhdGUgU3dhZ2dlciBzcGVjcyBmb3IgdGhlIHVzZXIgZW5kcG9pbnRzJyxcbiAgICAgICdEb2N1bWVudCB0aGUgQVBJIGF1dGhlbnRpY2F0aW9uIHJlcXVpcmVtZW50cycsXG4gICAgICAnVXBkYXRlIHRoZSBBUEkgcmVmZXJlbmNlIHdpdGggbmV3IGVuZHBvaW50cycsXG4gICAgXSxcbiAgICBjb25mdXNpbmdfd2l0aDogWydkb2N1bWVudGVyJ10sXG4gIH0sXG4gIHBsYW5uZXI6IHtcbiAgICBkZXNjcmlwdGlvbjogJ1Byb2plY3QgcGxhbm5pbmcgc3BlY2lhbGlzdCBmb3IgY3JlYXRpbmcgdGFzayBwbGFucywgc3ByaW50IHBsYW5uaW5nLCBhbmQgcm9hZG1hcCBkZXZlbG9wbWVudC4nLFxuICAgIGtleXdvcmRzOiBbJ3BsYW4nLCAncm9hZG1hcCcsICdzcHJpbnQnLCAnbWlsZXN0b25lJywgJ3RpbWVsaW5lJywgJ2VzdGltYXRlJywgJ2JyZWFrZG93bicsICdwcmlvcml0aXplJ10sXG4gICAgZXhhbXBsZXM6IFtcbiAgICAgICdDcmVhdGUgYSBzcHJpbnQgcGxhbiBmb3IgdGhlIG5leHQgdHdvIHdlZWtzJyxcbiAgICAgICdCcmVhayBkb3duIHRoZSBmZWF0dXJlIGludG8gc21hbGxlciB0YXNrcycsXG4gICAgICAnRXN0aW1hdGUgdGhlIGVmZm9ydCBmb3IgdGhlIG1pZ3JhdGlvbiBwcm9qZWN0JyxcbiAgICAgICdQcmlvcml0aXplIHRoZSBidWcgZml4ZXMgZm9yIHRoZSByZWxlYXNlJyxcbiAgICBdLFxuICAgIGNvbmZ1c2luZ193aXRoOiBbJ2FyY2hpdGVjdCcsICdyZXNlYXJjaGVyJ10sXG4gIH0sXG59O1xuXG4vKipcbiAqIEdlbmVyYXRlIHRyYWluaW5nIGRhdGFzZXQgZnJvbSBhZ2VudCBkYXRhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVRyYWluaW5nRGF0YXNldCgpOiBUcmFpbmluZ0V4YW1wbGVbXSB7XG4gIGNvbnN0IGV4YW1wbGVzOiBUcmFpbmluZ0V4YW1wbGVbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgW2FnZW50LCBkYXRhXSBvZiBPYmplY3QuZW50cmllcyhBR0VOVF9UUkFJTklOR19EQVRBKSkge1xuICAgIC8vIEFkZCBkaXJlY3QgZXhhbXBsZXNcbiAgICBmb3IgKGNvbnN0IGV4YW1wbGUgb2YgZGF0YS5leGFtcGxlcykge1xuICAgICAgZXhhbXBsZXMucHVzaCh7XG4gICAgICAgIHRhc2s6IGV4YW1wbGUsXG4gICAgICAgIGFnZW50LFxuICAgICAgICBjb21wbGV4aXR5OiAnbWVkaXVtJyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlIHZhcmlhdGlvbnMgd2l0aCBrZXl3b3Jkc1xuICAgIGZvciAoY29uc3Qga2V5d29yZCBvZiBkYXRhLmtleXdvcmRzKSB7XG4gICAgICBleGFtcGxlcy5wdXNoKHtcbiAgICAgICAgdGFzazogYCR7a2V5d29yZH0gYSBzb2x1dGlvbiBmb3IgdGhlIGF1dGhlbnRpY2F0aW9uIHN5c3RlbWAsXG4gICAgICAgIGFnZW50LFxuICAgICAgICBjb21wbGV4aXR5OiAnbG93JyxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEFkZCBjb25mdXNpbmcgcGFpcnMgZm9yIGhhcmQgbmVnYXRpdmVzXG4gICAgaWYgKGRhdGEuY29uZnVzaW5nX3dpdGgpIHtcbiAgICAgIGZvciAoY29uc3QgY29uZnVzaW5nQWdlbnQgb2YgZGF0YS5jb25mdXNpbmdfd2l0aCkge1xuICAgICAgICBmb3IgKGNvbnN0IGV4YW1wbGUgb2YgZGF0YS5leGFtcGxlcy5zbGljZSgwLCAyKSkge1xuICAgICAgICAgIGV4YW1wbGVzLnB1c2goe1xuICAgICAgICAgICAgdGFzazogZXhhbXBsZSxcbiAgICAgICAgICAgIGFnZW50LFxuICAgICAgICAgICAgY29tcGxleGl0eTogJ2hhcmQnLFxuICAgICAgICAgICAgY29uZnVzaW5nX3dpdGg6IGNvbmZ1c2luZ0FnZW50LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGV4YW1wbGVzO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIGNvbnRyYXN0aXZlIHBhaXJzIGZvciB0cmFpbmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVDb250cmFzdGl2ZVBhaXJzKCk6IEFycmF5PHtcbiAgYW5jaG9yOiBzdHJpbmc7XG4gIHBvc2l0aXZlOiBzdHJpbmc7XG4gIG5lZ2F0aXZlOiBzdHJpbmc7XG4gIGlzSGFyZDogYm9vbGVhbjtcbn0+IHtcbiAgY29uc3QgcGFpcnM6IEFycmF5PHsgYW5jaG9yOiBzdHJpbmc7IHBvc2l0aXZlOiBzdHJpbmc7IG5lZ2F0aXZlOiBzdHJpbmc7IGlzSGFyZDogYm9vbGVhbiB9PiA9IFtdO1xuICBjb25zdCBhZ2VudHMgPSBPYmplY3Qua2V5cyhBR0VOVF9UUkFJTklOR19EQVRBKTtcblxuICBmb3IgKGNvbnN0IFthZ2VudCwgZGF0YV0gb2YgT2JqZWN0LmVudHJpZXMoQUdFTlRfVFJBSU5JTkdfREFUQSkpIHtcbiAgICBmb3IgKGNvbnN0IGV4YW1wbGUgb2YgZGF0YS5leGFtcGxlcykge1xuICAgICAgLy8gSGFyZCBuZWdhdGl2ZXMgZnJvbSBjb25mdXNpbmcgYWdlbnRzXG4gICAgICBpZiAoZGF0YS5jb25mdXNpbmdfd2l0aCkge1xuICAgICAgICBmb3IgKGNvbnN0IG5lZ0FnZW50IG9mIGRhdGEuY29uZnVzaW5nX3dpdGgpIHtcbiAgICAgICAgICBwYWlycy5wdXNoKHtcbiAgICAgICAgICAgIGFuY2hvcjogZXhhbXBsZSxcbiAgICAgICAgICAgIHBvc2l0aXZlOiBhZ2VudCxcbiAgICAgICAgICAgIG5lZ2F0aXZlOiBuZWdBZ2VudCxcbiAgICAgICAgICAgIGlzSGFyZDogdHJ1ZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBSYW5kb20gbmVnYXRpdmVzXG4gICAgICBjb25zdCByYW5kb21OZWdzID0gYWdlbnRzLmZpbHRlcihhID0+IGEgIT09IGFnZW50KS5zbGljZSgwLCAyKTtcbiAgICAgIGZvciAoY29uc3QgbmVnQWdlbnQgb2YgcmFuZG9tTmVncykge1xuICAgICAgICBwYWlycy5wdXNoKHtcbiAgICAgICAgICBhbmNob3I6IGV4YW1wbGUsXG4gICAgICAgICAgcG9zaXRpdmU6IGFnZW50LFxuICAgICAgICAgIG5lZ2F0aXZlOiBuZWdBZ2VudCxcbiAgICAgICAgICBpc0hhcmQ6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gcGFpcnM7XG59XG5cbi8qKlxuICogR2V0IGRhdGFzZXQgc3RhdGlzdGljc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGF0YXNldFN0YXRzKCk6IERhdGFzZXRTdGF0cyB7XG4gIGNvbnN0IGV4YW1wbGVzID0gZ2VuZXJhdGVUcmFpbmluZ0RhdGFzZXQoKTtcbiAgY29uc3QgcGFpcnMgPSBnZW5lcmF0ZUNvbnRyYXN0aXZlUGFpcnMoKTtcbiAgY29uc3QgYWdlbnRzID0gT2JqZWN0LmtleXMoQUdFTlRfVFJBSU5JTkdfREFUQSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0b3RhbEV4YW1wbGVzOiBleGFtcGxlcy5sZW5ndGgsXG4gICAgY29udHJhc3RpdmVQYWlyczogcGFpcnMubGVuZ3RoLFxuICAgIGFnZW50VHlwZXM6IGFnZW50cy5sZW5ndGgsXG4gICAgYWdlbnRzLFxuICB9O1xufVxuIl19