@ruvector/ruvllm 3.0.0 → 4.0.1

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 +159 -360
  5. package/examples/gpu-loop.example.json +26 -0
  6. package/package.json +50 -121
  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 -1040
  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 -160
  34. package/dist/cjs/engine.d.ts.map +0 -1
  35. package/dist/cjs/engine.js +0 -552
  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 -140
  55. package/dist/cjs/native.d.ts.map +0 -1
  56. package/dist/cjs/native.js +0 -98
  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 -696
  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 -160
  91. package/dist/esm/engine.d.ts.map +0 -1
  92. package/dist/esm/engine.js +0 -548
  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 -140
  112. package/dist/esm/native.d.ts.map +0 -1
  113. package/dist/esm/native.js +0 -93
  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 -696
  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,434 +0,0 @@
1
- /**
2
- * Model Comparison Benchmark
3
- *
4
- * Head-to-head comparison between:
5
- * - Qwen2.5-0.5B-Instruct (base model)
6
- * - RuvLTRA Claude Code 0.5B (fine-tuned for Claude Code)
7
- *
8
- * Tests routing accuracy and embedding quality for Claude Code use cases.
9
- */
10
- import { existsSync, mkdirSync, createWriteStream, statSync } from 'fs';
11
- import { join } from 'path';
12
- import { homedir } from 'os';
13
- import { runRoutingBenchmark, } from './routing-benchmark.js';
14
- import { runEmbeddingBenchmark, } from './embedding-benchmark.js';
15
- /** Comparison models */
16
- export const COMPARISON_MODELS = {
17
- 'qwen-base': {
18
- id: 'qwen-base',
19
- name: 'Qwen2.5-0.5B-Instruct',
20
- url: 'https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct-GGUF/resolve/main/qwen2.5-0.5b-instruct-q4_k_m.gguf',
21
- filename: 'qwen2.5-0.5b-instruct-q4_k_m.gguf',
22
- sizeBytes: 491000000,
23
- description: 'Base Qwen 0.5B model (Q4_K_M quantized)',
24
- },
25
- 'ruvltra-claude-code': {
26
- id: 'ruvltra-claude-code',
27
- name: 'RuvLTRA Claude Code 0.5B',
28
- url: 'https://huggingface.co/ruv/ruvltra/resolve/main/ruvltra-claude-code-0.5b-q4_k_m.gguf',
29
- filename: 'ruvltra-claude-code-0.5b-q4_k_m.gguf',
30
- sizeBytes: 398000000,
31
- description: 'RuvLTRA fine-tuned for Claude Code workflows',
32
- },
33
- };
34
- /**
35
- * Get models directory
36
- */
37
- export function getModelsDir() {
38
- return join(homedir(), '.ruvllm', 'models');
39
- }
40
- /**
41
- * Check if model is downloaded
42
- */
43
- export function isModelDownloaded(modelId) {
44
- const model = COMPARISON_MODELS[modelId];
45
- if (!model)
46
- return false;
47
- const path = join(getModelsDir(), model.filename);
48
- if (!existsSync(path))
49
- return false;
50
- const stats = statSync(path);
51
- return stats.size >= model.sizeBytes * 0.9; // Allow 10% variance
52
- }
53
- /**
54
- * Download a model with progress
55
- */
56
- export async function downloadModel(modelId, onProgress) {
57
- const model = COMPARISON_MODELS[modelId];
58
- if (!model) {
59
- throw new Error(`Unknown model: ${modelId}`);
60
- }
61
- const modelsDir = getModelsDir();
62
- if (!existsSync(modelsDir)) {
63
- mkdirSync(modelsDir, { recursive: true });
64
- }
65
- const destPath = join(modelsDir, model.filename);
66
- if (isModelDownloaded(modelId)) {
67
- return destPath;
68
- }
69
- console.log(`Downloading ${model.name}...`);
70
- console.log(` From: ${model.url}`);
71
- console.log(` Size: ${(model.sizeBytes / 1024 / 1024).toFixed(0)} MB`);
72
- const tempPath = `${destPath}.tmp`;
73
- let downloaded = 0;
74
- let lastTime = Date.now();
75
- let lastDownloaded = 0;
76
- const response = await fetch(model.url, {
77
- headers: { 'User-Agent': 'RuvLLM/2.3.0' },
78
- });
79
- if (!response.ok) {
80
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
81
- }
82
- const contentLength = parseInt(response.headers.get('content-length') || String(model.sizeBytes));
83
- const fileStream = createWriteStream(tempPath);
84
- const reader = response.body?.getReader();
85
- if (!reader) {
86
- throw new Error('Response body not readable');
87
- }
88
- while (true) {
89
- const { done, value } = await reader.read();
90
- if (done)
91
- break;
92
- downloaded += value.length;
93
- fileStream.write(value);
94
- if (onProgress) {
95
- const now = Date.now();
96
- const elapsed = (now - lastTime) / 1000;
97
- if (elapsed >= 0.5) {
98
- const speed = (downloaded - lastDownloaded) / elapsed;
99
- onProgress(Math.round((downloaded / contentLength) * 100), speed);
100
- lastTime = now;
101
- lastDownloaded = downloaded;
102
- }
103
- }
104
- }
105
- fileStream.end();
106
- await new Promise((resolve, reject) => {
107
- fileStream.on('finish', resolve);
108
- fileStream.on('error', reject);
109
- });
110
- // Rename temp to final
111
- const { renameSync, unlinkSync } = await import('fs');
112
- if (existsSync(destPath)) {
113
- unlinkSync(destPath);
114
- }
115
- renameSync(tempPath, destPath);
116
- return destPath;
117
- }
118
- /**
119
- * Agent type keywords for routing classification
120
- */
121
- const AGENT_KEYWORDS = {
122
- coder: ['implement', 'create', 'write', 'build', 'add', 'code', 'function', 'class', 'component'],
123
- researcher: ['research', 'find', 'investigate', 'analyze', 'explore', 'search', 'look'],
124
- reviewer: ['review', 'check', 'evaluate', 'assess', 'inspect', 'examine'],
125
- tester: ['test', 'unit', 'integration', 'e2e', 'coverage', 'mock', 'assertion'],
126
- architect: ['design', 'architecture', 'schema', 'system', 'adr', 'structure', 'plan'],
127
- 'security-architect': ['security', 'vulnerability', 'xss', 'injection', 'audit', 'cve', 'auth'],
128
- debugger: ['debug', 'fix', 'bug', 'error', 'issue', 'broken', 'crash', 'exception'],
129
- documenter: ['document', 'readme', 'jsdoc', 'comment', 'explain', 'describe'],
130
- refactorer: ['refactor', 'extract', 'rename', 'consolidate', 'clean', 'restructure'],
131
- optimizer: ['optimize', 'performance', 'slow', 'fast', 'cache', 'speed', 'memory'],
132
- devops: ['deploy', 'ci', 'cd', 'kubernetes', 'docker', 'pipeline', 'container'],
133
- 'api-docs': ['openapi', 'swagger', 'api doc', 'graphql', 'endpoint doc'],
134
- planner: ['plan', 'estimate', 'prioritize', 'sprint', 'roadmap', 'schedule'],
135
- };
136
- /**
137
- * Enhanced keyword router with weighted scoring
138
- */
139
- function enhancedKeywordRouter(task) {
140
- const taskLower = task.toLowerCase();
141
- const scores = {};
142
- for (const [agent, keywords] of Object.entries(AGENT_KEYWORDS)) {
143
- scores[agent] = 0;
144
- for (const keyword of keywords) {
145
- if (taskLower.includes(keyword)) {
146
- // Weight by keyword position (earlier = more important)
147
- const pos = taskLower.indexOf(keyword);
148
- const weight = 1 + (1 - pos / taskLower.length) * 0.5;
149
- scores[agent] += weight;
150
- }
151
- }
152
- }
153
- // Find best match
154
- let bestAgent = 'coder';
155
- let bestScore = 0;
156
- for (const [agent, score] of Object.entries(scores)) {
157
- if (score > bestScore) {
158
- bestScore = score;
159
- bestAgent = agent;
160
- }
161
- }
162
- return {
163
- agent: bestAgent,
164
- confidence: Math.min(bestScore / 3, 1),
165
- };
166
- }
167
- /**
168
- * Simple embedding using character n-grams
169
- * This simulates what a model would do but with deterministic hashing
170
- */
171
- function simpleEmbedding(text, dim = 384) {
172
- const embedding = new Array(dim).fill(0);
173
- const normalized = text.toLowerCase().replace(/[^a-z0-9 ]/g, '');
174
- const words = normalized.split(/\s+/);
175
- // Word-level features
176
- for (let i = 0; i < words.length; i++) {
177
- const word = words[i];
178
- for (let j = 0; j < word.length; j++) {
179
- const idx = (word.charCodeAt(j) * 31 + j * 17 + i * 7) % dim;
180
- embedding[idx] += 1 / (i + 1); // Earlier words weighted more
181
- }
182
- // Bigrams
183
- if (i < words.length - 1) {
184
- const bigram = words[i] + words[i + 1];
185
- const bigramHash = bigram.split('').reduce((h, c) => (h * 31 + c.charCodeAt(0)) % 1000000, 0);
186
- const idx = bigramHash % dim;
187
- embedding[idx] += 0.5;
188
- }
189
- }
190
- // Normalize to unit vector
191
- const norm = Math.sqrt(embedding.reduce((s, x) => s + x * x, 0));
192
- if (norm > 0) {
193
- for (let i = 0; i < dim; i++) {
194
- embedding[i] /= norm;
195
- }
196
- }
197
- return embedding;
198
- }
199
- /**
200
- * Cosine similarity
201
- */
202
- function cosineSimilarity(a, b) {
203
- let dot = 0, normA = 0, normB = 0;
204
- for (let i = 0; i < a.length; i++) {
205
- dot += a[i] * b[i];
206
- normA += a[i] * a[i];
207
- normB += b[i] * b[i];
208
- }
209
- return dot / (Math.sqrt(normA) * Math.sqrt(normB) || 1);
210
- }
211
- /**
212
- * Simulate model-based routing using embedding similarity
213
- */
214
- function createModelRouter(embedder) {
215
- // Create agent embeddings from descriptions
216
- const agentDescriptions = {
217
- coder: 'implement create write build add new code function class component feature api endpoint',
218
- researcher: 'research find investigate analyze explore search look discover examine study',
219
- reviewer: 'review check evaluate assess inspect examine code quality pull request',
220
- tester: 'test unit integration e2e coverage mock assertion test case spec',
221
- architect: 'design architecture schema system structure plan adr database api contract',
222
- 'security-architect': 'security vulnerability xss sql injection audit cve authentication authorization',
223
- debugger: 'debug fix bug error issue broken crash exception trace stack',
224
- documenter: 'document readme jsdoc comment explain describe documentation guide tutorial',
225
- refactorer: 'refactor extract rename consolidate clean restructure simplify modularize',
226
- optimizer: 'optimize performance slow fast cache speed memory latency throughput',
227
- devops: 'deploy ci cd kubernetes docker pipeline container infrastructure cloud',
228
- 'api-docs': 'openapi swagger api documentation graphql schema endpoint specification',
229
- planner: 'plan estimate prioritize sprint roadmap schedule milestone task breakdown',
230
- };
231
- const agentEmbeddings = {};
232
- for (const [agent, desc] of Object.entries(agentDescriptions)) {
233
- agentEmbeddings[agent] = embedder(desc);
234
- }
235
- return (task) => {
236
- const taskEmbedding = embedder(task);
237
- let bestAgent = 'coder';
238
- let bestSimilarity = -1;
239
- for (const [agent, agentEmb] of Object.entries(agentEmbeddings)) {
240
- const sim = cosineSimilarity(taskEmbedding, agentEmb);
241
- if (sim > bestSimilarity) {
242
- bestSimilarity = sim;
243
- bestAgent = agent;
244
- }
245
- }
246
- return {
247
- agent: bestAgent,
248
- confidence: Math.max(0, bestSimilarity),
249
- };
250
- };
251
- }
252
- /**
253
- * Run comparison for a single model
254
- */
255
- export function runModelComparison(modelId, modelName, embedder) {
256
- const router = createModelRouter(embedder);
257
- const routing = runRoutingBenchmark(router);
258
- const embedding = runEmbeddingBenchmark(embedder, cosineSimilarity);
259
- // Calculate overall score
260
- const routingWeight = 0.4;
261
- const embeddingWeight = 0.6;
262
- const embeddingScore = (embedding.similarityAccuracy * 0.4 +
263
- embedding.searchMRR * 0.3 +
264
- embedding.clusterPurity * 0.3);
265
- const overallScore = routing.accuracy * routingWeight + embeddingScore * embeddingWeight;
266
- return {
267
- modelId,
268
- modelName,
269
- routing,
270
- embedding,
271
- overallScore,
272
- };
273
- }
274
- /**
275
- * Format comparison results
276
- */
277
- export function formatComparisonResults(results) {
278
- const lines = [];
279
- lines.push('');
280
- lines.push('╔═══════════════════════════════════════════════════════════════════════════════════╗');
281
- lines.push('║ MODEL COMPARISON RESULTS ║');
282
- lines.push('║ Qwen2.5-0.5B (Base) vs RuvLTRA Claude Code ║');
283
- lines.push('╠═══════════════════════════════════════════════════════════════════════════════════╣');
284
- lines.push(`║ Timestamp: ${results.timestamp.padEnd(70)}║`);
285
- lines.push('╚═══════════════════════════════════════════════════════════════════════════════════╝');
286
- // Comparison table
287
- lines.push('');
288
- lines.push('┌─────────────────────────────┬───────────────┬───────────────┬───────────────┐');
289
- lines.push('│ Metric │ Baseline │ Qwen Base │ RuvLTRA │');
290
- lines.push('├─────────────────────────────┼───────────────┼───────────────┼───────────────┤');
291
- const baseline = results.baseline;
292
- const qwen = results.models.find(m => m.modelId === 'qwen-base');
293
- const ruvltra = results.models.find(m => m.modelId === 'ruvltra-claude-code');
294
- const metrics = [
295
- { name: 'Routing Accuracy', b: baseline.routing.accuracy, q: qwen?.routing.accuracy || 0, r: ruvltra?.routing.accuracy || 0 },
296
- { name: 'Similarity Detection', b: baseline.embedding.similarityAccuracy, q: qwen?.embedding.similarityAccuracy || 0, r: ruvltra?.embedding.similarityAccuracy || 0 },
297
- { name: 'Search MRR', b: baseline.embedding.searchMRR, q: qwen?.embedding.searchMRR || 0, r: ruvltra?.embedding.searchMRR || 0 },
298
- { name: 'Search NDCG', b: baseline.embedding.searchNDCG, q: qwen?.embedding.searchNDCG || 0, r: ruvltra?.embedding.searchNDCG || 0 },
299
- { name: 'Cluster Purity', b: baseline.embedding.clusterPurity, q: qwen?.embedding.clusterPurity || 0, r: ruvltra?.embedding.clusterPurity || 0 },
300
- { name: 'Overall Score', b: baseline.overallScore, q: qwen?.overallScore || 0, r: ruvltra?.overallScore || 0 },
301
- ];
302
- for (const m of metrics) {
303
- const bStr = `${(m.b * 100).toFixed(1)}%`;
304
- const qStr = `${(m.q * 100).toFixed(1)}%`;
305
- const rStr = `${(m.r * 100).toFixed(1)}%`;
306
- // Highlight winner
307
- const qWin = m.q > m.b && m.q >= m.r ? '✓' : ' ';
308
- const rWin = m.r > m.b && m.r >= m.q ? '✓' : ' ';
309
- lines.push(`│ ${m.name.padEnd(27)} │ ${bStr.padStart(11)} │ ${qWin}${qStr.padStart(10)} │ ${rWin}${rStr.padStart(10)} │`);
310
- }
311
- lines.push('└─────────────────────────────┴───────────────┴───────────────┴───────────────┘');
312
- // Winner announcement
313
- lines.push('');
314
- lines.push('═══════════════════════════════════════════════════════════════════════════════════');
315
- lines.push(` WINNER: ${results.winner}`);
316
- lines.push('═══════════════════════════════════════════════════════════════════════════════════');
317
- lines.push('');
318
- lines.push(results.summary);
319
- // Detailed breakdown
320
- lines.push('');
321
- lines.push('─────────────────────────────────────────────────────────────────────────────────');
322
- lines.push('ROUTING ACCURACY BY CATEGORY');
323
- lines.push('─────────────────────────────────────────────────────────────────────────────────');
324
- const categories = Object.keys(baseline.routing.accuracyByCategory);
325
- lines.push('Category'.padEnd(20) + 'Baseline'.padStart(12) + 'Qwen'.padStart(12) + 'RuvLTRA'.padStart(12) + 'Best'.padStart(10));
326
- for (const cat of categories) {
327
- const b = baseline.routing.accuracyByCategory[cat] || 0;
328
- const q = qwen?.routing.accuracyByCategory[cat] || 0;
329
- const r = ruvltra?.routing.accuracyByCategory[cat] || 0;
330
- const best = r > q && r > b ? 'RuvLTRA' : q > b ? 'Qwen' : 'Baseline';
331
- lines.push(cat.padEnd(20) +
332
- `${(b * 100).toFixed(0)}%`.padStart(12) +
333
- `${(q * 100).toFixed(0)}%`.padStart(12) +
334
- `${(r * 100).toFixed(0)}%`.padStart(12) +
335
- best.padStart(10));
336
- }
337
- return lines.join('\n');
338
- }
339
- /**
340
- * Run full comparison
341
- */
342
- export async function runFullComparison() {
343
- console.log('\n╔═══════════════════════════════════════════════════════════════════════════════════╗');
344
- console.log('║ RUVLTRA vs QWEN MODEL COMPARISON ║');
345
- console.log('║ Testing for Claude Code Use Cases ║');
346
- console.log('╚═══════════════════════════════════════════════════════════════════════════════════╝\n');
347
- // Run baseline (keyword-based)
348
- console.log('Running baseline (keyword router + simple embeddings)...');
349
- const baselineRouter = enhancedKeywordRouter;
350
- const baselineEmbedder = (text) => simpleEmbedding(text, 384);
351
- const baselineRouting = runRoutingBenchmark(baselineRouter);
352
- const baselineEmbedding = runEmbeddingBenchmark(baselineEmbedder, cosineSimilarity);
353
- const baselineScore = (baselineRouting.accuracy * 0.4 +
354
- (baselineEmbedding.similarityAccuracy * 0.4 + baselineEmbedding.searchMRR * 0.3 + baselineEmbedding.clusterPurity * 0.3) * 0.6);
355
- const baseline = {
356
- modelId: 'baseline',
357
- modelName: 'Keyword + Hash Baseline',
358
- routing: baselineRouting,
359
- embedding: baselineEmbedding,
360
- overallScore: baselineScore,
361
- };
362
- console.log(` Baseline routing: ${(baselineRouting.accuracy * 100).toFixed(1)}%`);
363
- // Simulate Qwen model (using n-gram embeddings with different config)
364
- console.log('\nRunning Qwen2.5-0.5B simulation...');
365
- const qwenEmbedder = (text) => simpleEmbedding(text, 512); // Qwen uses 512 dim
366
- const qwenResult = runModelComparison('qwen-base', 'Qwen2.5-0.5B-Instruct', qwenEmbedder);
367
- console.log(` Qwen routing: ${(qwenResult.routing.accuracy * 100).toFixed(1)}%`);
368
- // Simulate RuvLTRA model (enhanced embeddings simulating fine-tuning)
369
- console.log('\nRunning RuvLTRA Claude Code simulation...');
370
- // RuvLTRA embedder - enhanced with Claude Code specific terms
371
- const claudeCodeTerms = [
372
- 'agent', 'spawn', 'swarm', 'coordinate', 'task', 'route', 'orchestrate',
373
- 'coder', 'tester', 'reviewer', 'architect', 'researcher', 'debugger',
374
- 'implement', 'refactor', 'optimize', 'security', 'performance', 'deploy',
375
- ];
376
- const ruvltraEmbedder = (text) => {
377
- const base = simpleEmbedding(text, 384);
378
- // Boost dimensions for Claude Code specific terms
379
- const textLower = text.toLowerCase();
380
- for (let i = 0; i < claudeCodeTerms.length; i++) {
381
- if (textLower.includes(claudeCodeTerms[i])) {
382
- const idx = (i * 31) % 384;
383
- base[idx] += 0.3; // Boost for Claude Code terms
384
- }
385
- }
386
- // Re-normalize
387
- const norm = Math.sqrt(base.reduce((s, x) => s + x * x, 0));
388
- for (let i = 0; i < base.length; i++) {
389
- base[i] /= norm;
390
- }
391
- return base;
392
- };
393
- const ruvltraResult = runModelComparison('ruvltra-claude-code', 'RuvLTRA Claude Code 0.5B', ruvltraEmbedder);
394
- console.log(` RuvLTRA routing: ${(ruvltraResult.routing.accuracy * 100).toFixed(1)}%`);
395
- // Determine winner
396
- const scores = [
397
- { name: 'Baseline', score: baseline.overallScore },
398
- { name: 'Qwen2.5-0.5B', score: qwenResult.overallScore },
399
- { name: 'RuvLTRA Claude Code', score: ruvltraResult.overallScore },
400
- ].sort((a, b) => b.score - a.score);
401
- const winner = scores[0].name;
402
- const improvement = ((scores[0].score - baseline.overallScore) / baseline.overallScore * 100).toFixed(1);
403
- let summary = '';
404
- if (winner === 'RuvLTRA Claude Code') {
405
- summary = `RuvLTRA Claude Code outperforms Qwen base by ${((ruvltraResult.overallScore - qwenResult.overallScore) * 100).toFixed(1)} percentage points.\n`;
406
- summary += ` This demonstrates the value of fine-tuning for Claude Code specific tasks.\n`;
407
- summary += ` Key advantages: Better agent routing and task-specific embedding quality.`;
408
- }
409
- else if (winner === 'Qwen2.5-0.5B') {
410
- summary = `Qwen base slightly outperforms RuvLTRA on general metrics.\n`;
411
- summary += ` However, RuvLTRA may still be better for specific Claude Code workflows.\n`;
412
- summary += ` Consider task-specific evaluation for your use case.`;
413
- }
414
- else {
415
- summary = `Baseline keyword matching remains competitive.\n`;
416
- summary += ` For simple routing, keyword-based approaches may be sufficient.\n`;
417
- summary += ` Model-based approaches add value for semantic understanding.`;
418
- }
419
- return {
420
- timestamp: new Date().toISOString(),
421
- baseline,
422
- models: [qwenResult, ruvltraResult],
423
- winner,
424
- summary,
425
- };
426
- }
427
- export default {
428
- COMPARISON_MODELS,
429
- runFullComparison,
430
- formatComparisonResults,
431
- downloadModel,
432
- isModelDownloaded,
433
- };
434
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwtY29tcGFyaXNvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iZW5jaG1hcmtzL21vZGVsLWNvbXBhcmlzb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7O0dBUUc7QUFHSCxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxRQUFRLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDeEUsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM1QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBRzdCLE9BQU8sRUFDTCxtQkFBbUIsR0FNcEIsTUFBTSxxQkFBcUIsQ0FBQztBQUU3QixPQUFPLEVBQ0wscUJBQXFCLEdBR3RCLE1BQU0sdUJBQXVCLENBQUM7QUFZL0Isd0JBQXdCO0FBQ3hCLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFnQztJQUM1RCxXQUFXLEVBQUU7UUFDWCxFQUFFLEVBQUUsV0FBVztRQUNmLElBQUksRUFBRSx1QkFBdUI7UUFDN0IsR0FBRyxFQUFFLHVHQUF1RztRQUM1RyxRQUFRLEVBQUUsbUNBQW1DO1FBQzdDLFNBQVMsRUFBRSxTQUFXO1FBQ3RCLFdBQVcsRUFBRSx5Q0FBeUM7S0FDdkQ7SUFDRCxxQkFBcUIsRUFBRTtRQUNyQixFQUFFLEVBQUUscUJBQXFCO1FBQ3pCLElBQUksRUFBRSwwQkFBMEI7UUFDaEMsR0FBRyxFQUFFLHNGQUFzRjtRQUMzRixRQUFRLEVBQUUsc0NBQXNDO1FBQ2hELFNBQVMsRUFBRSxTQUFXO1FBQ3RCLFdBQVcsRUFBRSw4Q0FBOEM7S0FDNUQ7Q0FDRixDQUFDO0FBb0JGOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFlBQVk7SUFDMUIsT0FBTyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFB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TyxHQUFHLEVBQUUsQ0FBQztJQUNqQixJQUFJLE1BQU0sS0FBSyxxQkFBcUIsRUFBRSxDQUFDO1FBQ3JDLE9BQU8sR0FBRyxnREFBZ0QsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxZQUFZLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsdUJBQXVCLENBQUM7UUFDM0osT0FBTyxJQUFJLGdGQUFnRixDQUFDO1FBQzVGLE9BQU8sSUFBSSw2RUFBNkUsQ0FBQztJQUMzRixDQUFDO1NBQU0sSUFBSSxNQUFNLEtBQUssY0FBYyxFQUFFLENBQUM7UUFDckMsT0FBTyxHQUFHLDhEQUE4RCxDQUFDO1FBQ3pFLE9BQU8sSUFBSSw4RUFBOEUsQ0FBQztRQUMxRixPQUFPLElBQUksd0RBQXdELENBQUM7SUFDdEUsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLEdBQUcsa0RBQWtELENBQUM7UUFDN0QsT0FBTyxJQUFJLHFFQUFxRSxDQUFDO1FBQ2pGLE9BQU8sSUFBSSxnRUFBZ0UsQ0FBQztJQUM5RSxDQUFDO0lBRUQsT0FBTztRQUNMLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTtRQUNuQyxRQUFRO1FBQ1IsTUFBTSxFQUFFLENBQUMsVUFBVSxFQUFFLGFBQWEsQ0FBQztRQUNuQyxNQUFNO1FBQ04sT0FBTztLQUNSLENBQUM7QUFDSixDQUFDO0FBRUQsZUFBZTtJQUNiLGlCQUFpQjtJQUNqQixpQkFBaUI7SUFDakIsdUJBQXVCO0lBQ3ZCLGFBQWE7SUFDYixpQkFBaUI7Q0FDbEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTW9kZWwgQ29tcGFyaXNvbiBCZW5jaG1hcmtcbiAqXG4gKiBIZWFkLXRvLWhlYWQgY29tcGFyaXNvbiBiZXR3ZWVuOlxuICogLSBRd2VuMi41LTAuNUItSW5zdHJ1Y3QgKGJhc2UgbW9kZWwpXG4gKiAtIFJ1dkxUUkEgQ2xhdWRlIENvZGUgMC41QiAoZmluZS10dW5lZCBmb3IgQ2xhdWRlIENvZGUpXG4gKlxuICogVGVzdHMgcm91dGluZyBhY2N1cmFjeSBhbmQgZW1iZWRkaW5nIHF1YWxpdHkgZm9yIENsYXVkZSBDb2RlIHVzZSBjYXNlcy5cbiAqL1xuXG5pbXBvcnQgeyBzcGF3biB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgZXhpc3RzU3luYywgbWtkaXJTeW5jLCBjcmVhdGVXcml0ZVN0cmVhbSwgc3RhdFN5bmMgfSBmcm9tICdmcyc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBob21lZGlyIH0gZnJvbSAnb3MnO1xuaW1wb3J0IHsgcGlwZWxpbmUgfSBmcm9tICdzdHJlYW0vcHJvbWlzZXMnO1xuXG5pbXBvcnQge1xuICBydW5Sb3V0aW5nQmVuY2htYXJrLFxuICBmb3JtYXRSb3V0aW5nUmVzdWx0cyxcbiAgYmFzZWxpbmVLZXl3b3JkUm91dGVyLFxuICBST1VUSU5HX1RFU1RfQ0FTRVMsXG4gIEFHRU5UX1RZUEVTLFxuICB0eXBlIFJvdXRpbmdCZW5jaG1hcmtSZXN1bHRzLFxufSBmcm9tICcuL3JvdXRpbmctYmVuY2htYXJrJztcblxuaW1wb3J0IHtcbiAgcnVuRW1iZWRkaW5nQmVuY2htYXJrLFxuICBmb3JtYXRFbWJlZGRpbmdSZXN1bHRzLFxuICB0eXBlIEVtYmVkZGluZ0JlbmNobWFya1Jlc3VsdHMsXG59IGZyb20gJy4vZW1iZWRkaW5nLWJlbmNobWFyayc7XG5cbi8qKiBNb2RlbCBjb25maWd1cmF0aW9uICovXG5leHBvcnQgaW50ZXJmYWNlIE1vZGVsQ29uZmlnIHtcbiAgaWQ6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICB1cmw6IHN0cmluZztcbiAgZmlsZW5hbWU6IHN0cmluZztcbiAgc2l6ZUJ5dGVzOiBudW1iZXI7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG59XG5cbi8qKiBDb21wYXJpc29uIG1vZGVscyAqL1xuZXhwb3J0IGNvbnN0IENPTVBBUklTT05fTU9ERUxTOiBSZWNvcmQ8c3RyaW5nLCBNb2RlbENvbmZpZz4gPSB7XG4gICdxd2VuLWJhc2UnOiB7XG4gICAgaWQ6ICdxd2VuLWJhc2UnLFxuICAgIG5hbWU6ICdRd2VuMi41LTAuNUItSW5zdHJ1Y3QnLFxuICAgIHVybDogJ2h0dHBzOi8vaHVnZ2luZ2ZhY2UuY28vUXdlbi9Rd2VuMi41LTAuNUItSW5zdHJ1Y3QtR0dVRi9yZXNvbHZlL21haW4vcXdlbjIuNS0wLjViLWluc3RydWN0LXE0X2tfbS5nZ3VmJyxcbiAgICBmaWxlbmFtZTogJ3F3ZW4yLjUtMC41Yi1pbnN0cnVjdC1xNF9rX20uZ2d1ZicsXG4gICAgc2l6ZUJ5dGVzOiA0OTFfMDAwXzAwMCxcbiAgICBkZXNjcmlwdGlvbjogJ0Jhc2UgUXdlbiAwLjVCIG1vZGVsIChRNF9LX00gcXVhbnRpemVkKScsXG4gIH0sXG4gICdydXZsdHJhLWNsYXVkZS1jb2RlJzoge1xuICAgIGlkOiAncnV2bHRyYS1jbGF1ZGUtY29kZScsXG4gICAgbmFtZTogJ1J1dkxUUkEgQ2xhdWRlIENvZGUgMC41QicsXG4gICAgdXJsOiAnaHR0cHM6Ly9odWdnaW5nZmFjZS5jby9ydXYvcnV2bHRyYS9yZXNvbHZlL21haW4vcnV2bHRyYS1jbGF1ZGUtY29kZS0wLjViLXE0X2tfbS5nZ3VmJyxcbiAgICBmaWxlbmFtZTogJ3J1dmx0cmEtY2xhdWRlLWNvZGUtMC41Yi1xNF9rX20uZ2d1ZicsXG4gICAgc2l6ZUJ5dGVzOiAzOThfMDAwXzAwMCxcbiAgICBkZXNjcmlwdGlvbjogJ1J1dkxUUkEgZmluZS10dW5lZCBmb3IgQ2xhdWRlIENvZGUgd29ya2Zsb3dzJyxcbiAgfSxcbn07XG5cbi8qKiBDb21wYXJpc29uIHJlc3VsdCAqL1xuZXhwb3J0IGludGVyZmFjZSBDb21wYXJpc29uUmVzdWx0IHtcbiAgbW9kZWxJZDogc3RyaW5nO1xuICBtb2RlbE5hbWU6IHN0cmluZztcbiAgcm91dGluZzogUm91dGluZ0JlbmNobWFya1Jlc3VsdHM7XG4gIGVtYmVkZGluZzogRW1iZWRkaW5nQmVuY2htYXJrUmVzdWx0cztcbiAgb3ZlcmFsbFNjb3JlOiBudW1iZXI7XG59XG5cbi8qKiBGdWxsIGNvbXBhcmlzb24gcmVzdWx0cyAqL1xuZXhwb3J0IGludGVyZmFjZSBGdWxsQ29tcGFyaXNvblJlc3VsdHMge1xuICB0aW1lc3RhbXA6IHN0cmluZztcbiAgYmFzZWxpbmU6IENvbXBhcmlzb25SZXN1bHQ7XG4gIG1vZGVsczogQ29tcGFyaXNvblJlc3VsdFtdO1xuICB3aW5uZXI6IHN0cmluZztcbiAgc3VtbWFyeTogc3RyaW5nO1xufVxuXG4vKipcbiAqIEdldCBtb2RlbHMgZGlyZWN0b3J5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNb2RlbHNEaXIoKTogc3RyaW5nIHtcbiAgcmV0dXJuIGpvaW4oaG9tZWRpcigpLCAnLnJ1dmxsbScsICdtb2RlbHMnKTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBtb2RlbCBpcyBkb3dubG9hZGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc01vZGVsRG93bmxvYWRlZChtb2RlbElkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgbW9kZWwgPSBDT01QQVJJU09OX01PREVMU1ttb2RlbElkXTtcbiAgaWYgKCFtb2RlbCkgcmV0dXJuIGZhbHNlO1xuXG4gIGNvbnN0IHBhdGggPSBqb2luKGdldE1vZGVsc0RpcigpLCBtb2RlbC5maWxlbmFtZSk7XG4gIGlmICghZXhpc3RzU3luYyhwYXRoKSkgcmV0dXJuIGZhbHNlO1xuXG4gIGNvbnN0IHN0YXRzID0gc3RhdFN5bmMocGF0aCk7XG4gIHJldHVybiBzdGF0cy5zaXplID49IG1vZGVsLnNpemVCeXRlcyAqIDAuOTsgLy8gQWxsb3cgMTAlIHZhcmlhbmNlXG59XG5cbi8qKlxuICogRG93bmxvYWQgYSBtb2RlbCB3aXRoIHByb2dyZXNzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb3dubG9hZE1vZGVsKFxuICBtb2RlbElkOiBzdHJpbmcsXG4gIG9uUHJvZ3Jlc3M/OiAocGVyY2VudDogbnVtYmVyLCBzcGVlZDogbnVtYmVyKSA9PiB2b2lkXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBtb2RlbCA9IENPTVBBUklTT05fTU9ERUxTW21vZGVsSWRdO1xuICBpZiAoIW1vZGVsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIG1vZGVsOiAke21vZGVsSWR9YCk7XG4gIH1cblxuICBjb25zdCBtb2RlbHNEaXIgPSBnZXRNb2RlbHNEaXIoKTtcbiAgaWYgKCFleGlzdHNTeW5jKG1vZGVsc0RpcikpIHtcbiAgICBta2RpclN5bmMobW9kZWxzRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIGNvbnN0IGRlc3RQYXRoID0gam9pbihtb2RlbHNEaXIsIG1vZGVsLmZpbGVuYW1lKTtcblxuICBpZiAoaXNNb2RlbERvd25sb2FkZWQobW9kZWxJZCkpIHtcbiAgICByZXR1cm4gZGVzdFBhdGg7XG4gIH1cblxuICBjb25zb2xlLmxvZyhgRG93bmxvYWRpbmcgJHttb2RlbC5uYW1lfS4uLmApO1xuICBjb25zb2xlLmxvZyhgICBGcm9tOiAke21vZGVsLnVybH1gKTtcbiAgY29uc29sZS5sb2coYCAgU2l6ZTogJHsobW9kZWwuc2l6ZUJ5dGVzIC8gMTAyNCAvIDEwMjQpLnRvRml4ZWQoMCl9IE1CYCk7XG5cbiAgY29uc3QgdGVtcFBhdGggPSBgJHtkZXN0UGF0aH0udG1wYDtcbiAgbGV0IGRvd25sb2FkZWQgPSAwO1xuICBsZXQgbGFzdFRpbWUgPSBEYXRlLm5vdygpO1xuICBsZXQgbGFzdERvd25sb2FkZWQgPSAwO1xuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2gobW9kZWwudXJsLCB7XG4gICAgaGVhZGVyczogeyAnVXNlci1BZ2VudCc6ICdSdXZMTE0vMi4zLjAnIH0sXG4gIH0pO1xuXG4gIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEhUVFAgJHtyZXNwb25zZS5zdGF0dXN9OiAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gIH1cblxuICBjb25zdCBjb250ZW50TGVuZ3RoID0gcGFyc2VJbnQocmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtbGVuZ3RoJykgfHwgU3RyaW5nKG1vZGVsLnNpemVCeXRlcykpO1xuICBjb25zdCBmaWxlU3RyZWFtID0gY3JlYXRlV3JpdGVTdHJlYW0odGVtcFBhdGgpO1xuICBjb25zdCByZWFkZXIgPSByZXNwb25zZS5ib2R5Py5nZXRSZWFkZXIoKTtcblxuICBpZiAoIXJlYWRlcikge1xuICAgIHRocm93IG5ldyBFcnJvcignUmVzcG9uc2UgYm9keSBub3QgcmVhZGFibGUnKTtcbiAgfVxuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgY29uc3QgeyBkb25lLCB2YWx1ZSB9ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICBpZiAoZG9uZSkgYnJlYWs7XG5cbiAgICBkb3dubG9hZGVkICs9IHZhbHVlLmxlbmd0aDtcbiAgICBmaWxlU3RyZWFtLndyaXRlKHZhbHVlKTtcblxuICAgIGlmIChvblByb2dyZXNzKSB7XG4gICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3QgZWxhcHNlZCA9IChub3cgLSBsYXN0VGltZSkgLyAxMDAwO1xuICAgICAgaWYgKGVsYXBzZWQgPj0gMC41KSB7XG4gICAgICAgIGNvbnN0IHNwZWVkID0gKGRvd25sb2FkZWQgLSBsYXN0RG93bmxvYWRlZCkgLyBlbGFwc2VkO1xuICAgICAgICBvblByb2dyZXNzKE1hdGgucm91bmQoKGRvd25sb2FkZWQgLyBjb250ZW50TGVuZ3RoKSAqIDEwMCksIHNwZWVkKTtcbiAgICAgICAgbGFzdFRpbWUgPSBub3c7XG4gICAgICAgIGxhc3REb3dubG9hZGVkID0gZG93bmxvYWRlZDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmaWxlU3RyZWFtLmVuZCgpO1xuICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgZmlsZVN0cmVhbS5vbignZmluaXNoJywgcmVzb2x2ZSk7XG4gICAgZmlsZVN0cmVhbS5vbignZXJyb3InLCByZWplY3QpO1xuICB9KTtcblxuICAvLyBSZW5hbWUgdGVtcCB0byBmaW5hbFxuICBjb25zdCB7IHJlbmFtZVN5bmMsIHVubGlua1N5bmMgfSA9IGF3YWl0IGltcG9ydCgnZnMnKTtcbiAgaWYgKGV4aXN0c1N5bmMoZGVzdFBhdGgpKSB7XG4gICAgdW5saW5rU3luYyhkZXN0UGF0aCk7XG4gIH1cbiAgcmVuYW1lU3luYyh0ZW1wUGF0aCwgZGVzdFBhdGgpO1xuXG4gIHJldHVybiBkZXN0UGF0aDtcbn1cblxuLyoqXG4gKiBBZ2VudCB0eXBlIGtleXdvcmRzIGZvciByb3V0aW5nIGNsYXNzaWZpY2F0aW9uXG4gKi9cbmNvbnN0IEFHRU5UX0tFWVdPUkRTOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT4gPSB7XG4gIGNvZGVyOiBbJ2ltcGxlbWVudCcsICdjcmVhdGUnLCAnd3JpdGUnLCAnYnVpbGQnLCAnYWRkJywgJ2NvZGUnLCAnZnVuY3Rpb24nLCAnY2xhc3MnLCAnY29tcG9uZW50J10sXG4gIHJlc2VhcmNoZXI6IFsncmVzZWFyY2gnLCAnZmluZCcsICdpbnZlc3RpZ2F0ZScsICdhbmFseXplJywgJ2V4cGxvcmUnLCAnc2VhcmNoJywgJ2xvb2snXSxcbiAgcmV2aWV3ZXI6IFsncmV2aWV3JywgJ2NoZWNrJywgJ2V2YWx1YXRlJywgJ2Fzc2VzcycsICdpbnNwZWN0JywgJ2V4YW1pbmUnXSxcbiAgdGVzdGVyOiBbJ3Rlc3QnLCAndW5pdCcsICdpbnRlZ3JhdGlvbicsICdlMmUnLCAnY292ZXJhZ2UnLCAnbW9jaycsICdhc3NlcnRpb24nXSxcbiAgYXJjaGl0ZWN0OiBbJ2Rlc2lnbicsICdhcmNoaXRlY3R1cmUnLCAnc2NoZW1hJywgJ3N5c3RlbScsICdhZHInLCAnc3RydWN0dXJlJywgJ3BsYW4nXSxcbiAgJ3NlY3VyaXR5LWFyY2hpdGVjdCc6IFsnc2VjdXJpdHknLCAndnVsbmVyYWJpbGl0eScsICd4c3MnLCAnaW5qZWN0aW9uJywgJ2F1ZGl0JywgJ2N2ZScsICdhdXRoJ10sXG4gIGRlYnVnZ2VyOiBbJ2RlYnVnJywgJ2ZpeCcsICdidWcnLCAnZXJyb3InLCAnaXNzdWUnLCAnYnJva2VuJywgJ2NyYXNoJywgJ2V4Y2VwdGlvbiddLFxuICBkb2N1bWVudGVyOiBbJ2RvY3VtZW50JywgJ3JlYWRtZScsICdqc2RvYycsICdjb21tZW50JywgJ2V4cGxhaW4nLCAnZGVzY3JpYmUnXSxcbiAgcmVmYWN0b3JlcjogWydyZWZhY3RvcicsICdleHRyYWN0JywgJ3JlbmFtZScsICdjb25zb2xpZGF0ZScsICdjbGVhbicsICdyZXN0cnVjdHVyZSddLFxuICBvcHRpbWl6ZXI6IFsnb3B0aW1pemUnLCAncGVyZm9ybWFuY2UnLCAnc2xvdycsICdmYXN0JywgJ2NhY2hlJywgJ3NwZWVkJywgJ21lbW9yeSddLFxuICBkZXZvcHM6IFsnZGVwbG95JywgJ2NpJywgJ2NkJywgJ2t1YmVybmV0ZXMnLCAnZG9ja2VyJywgJ3BpcGVsaW5lJywgJ2NvbnRhaW5lciddLFxuICAnYXBpLWRvY3MnOiBbJ29wZW5hcGknLCAnc3dhZ2dlcicsICdhcGkgZG9jJywgJ2dyYXBocWwnLCAnZW5kcG9pbnQgZG9jJ10sXG4gIHBsYW5uZXI6IFsncGxhbicsICdlc3RpbWF0ZScsICdwcmlvcml0aXplJywgJ3NwcmludCcsICdyb2FkbWFwJywgJ3NjaGVkdWxlJ10sXG59O1xuXG4vKipcbiAqIEVuaGFuY2VkIGtleXdvcmQgcm91dGVyIHdpdGggd2VpZ2h0ZWQgc2NvcmluZ1xuICovXG5mdW5jdGlvbiBlbmhhbmNlZEtleXdvcmRSb3V0ZXIodGFzazogc3RyaW5nKTogeyBhZ2VudDogc3RyaW5nOyBjb25maWRlbmNlOiBudW1iZXIgfSB7XG4gIGNvbnN0IHRhc2tMb3dlciA9IHRhc2sudG9Mb3dlckNhc2UoKTtcbiAgY29uc3Qgc2NvcmVzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge307XG5cbiAgZm9yIChjb25zdCBbYWdlbnQsIGtleXdvcmRzXSBvZiBPYmplY3QuZW50cmllcyhBR0VOVF9LRVlXT1JEUykpIHtcbiAgICBzY29yZXNbYWdlbnRdID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICAgIGlmICh0YXNrTG93ZXIuaW5jbHVkZXMoa2V5d29yZCkpIHtcbiAgICAgICAgLy8gV2VpZ2h0IGJ5IGtleXdvcmQgcG9zaXRpb24gKGVhcmxpZXIgPSBtb3JlIGltcG9ydGFudClcbiAgICAgICAgY29uc3QgcG9zID0gdGFza0xvd2VyLmluZGV4T2Yoa2V5d29yZCk7XG4gICAgICAgIGNvbnN0IHdlaWdodCA9IDEgKyAoMSAtIHBvcyAvIHRhc2tMb3dlci5sZW5ndGgpICogMC41O1xuICAgICAgICBzY29yZXNbYWdlbnRdICs9IHdlaWdodDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBGaW5kIGJlc3QgbWF0Y2hcbiAgbGV0IGJlc3RBZ2VudCA9ICdjb2Rlcic7XG4gIGxldCBiZXN0U2NvcmUgPSAwO1xuICBmb3IgKGNvbnN0IFthZ2VudCwgc2NvcmVdIG9mIE9iamVjdC5lbnRyaWVzKHNjb3JlcykpIHtcbiAgICBpZiAoc2NvcmUgPiBiZXN0U2NvcmUpIHtcbiAgICAgIGJlc3RTY29yZSA9IHNjb3JlO1xuICAgICAgYmVzdEFnZW50ID0gYWdlbnQ7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBhZ2VudDogYmVzdEFnZW50LFxuICAgIGNvbmZpZGVuY2U6IE1hdGgubWluKGJlc3RTY29yZSAvIDMsIDEpLFxuICB9O1xufVxuXG4vKipcbiAqIFNpbXBsZSBlbWJlZGRpbmcgdXNpbmcgY2hhcmFjdGVyIG4tZ3JhbXNcbiAqIFRoaXMgc2ltdWxhdGVzIHdoYXQgYSBtb2RlbCB3b3VsZCBkbyBidXQgd2l0aCBkZXRlcm1pbmlzdGljIGhhc2hpbmdcbiAqL1xuZnVuY3Rpb24gc2ltcGxlRW1iZWRkaW5nKHRleHQ6IHN0cmluZywgZGltOiBudW1iZXIgPSAzODQpOiBudW1iZXJbXSB7XG4gIGNvbnN0IGVtYmVkZGluZyA9IG5ldyBBcnJheShkaW0pLmZpbGwoMCk7XG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSB0ZXh0LnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvW15hLXowLTkgXS9nLCAnJyk7XG4gIGNvbnN0IHdvcmRzID0gbm9ybWFsaXplZC5zcGxpdCgvXFxzKy8pO1xuXG4gIC8vIFdvcmQtbGV2ZWwgZmVhdHVyZXNcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB3b3Jkcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IHdvcmQgPSB3b3Jkc1tpXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IHdvcmQubGVuZ3RoOyBqKyspIHtcbiAgICAgIGNvbnN0IGlkeCA9ICh3b3JkLmNoYXJDb2RlQXQoaikgKiAzMSArIGogKiAxNyArIGkgKiA3KSAlIGRpbTtcbiAgICAgIGVtYmVkZGluZ1tpZHhdICs9IDEgLyAoaSArIDEpOyAvLyBFYXJsaWVyIHdvcmRzIHdlaWdodGVkIG1vcmVcbiAgICB9XG5cbiAgICAvLyBCaWdyYW1zXG4gICAgaWYgKGkgPCB3b3Jkcy5sZW5ndGggLSAxKSB7XG4gICAgICBjb25zdCBiaWdyYW0gPSB3b3Jkc1tpXSArIHdvcmRzW2kgKyAxXTtcbiAgICAgIGNvbnN0IGJpZ3JhbUhhc2ggPSBiaWdyYW0uc3BsaXQoJycpLnJlZHVjZSgoaCwgYykgPT4gKGggKiAzMSArIGMuY2hhckNvZGVBdCgwKSkgJSAxMDAwMDAwLCAwKTtcbiAgICAgIGNvbnN0IGlkeCA9IGJpZ3JhbUhhc2ggJSBkaW07XG4gICAgICBlbWJlZGRpbmdbaWR4XSArPSAwLjU7XG4gICAgfVxuICB9XG5cbiAgLy8gTm9ybWFsaXplIHRvIHVuaXQgdmVjdG9yXG4gIGNvbnN0IG5vcm0gPSBNYXRoLnNxcnQoZW1iZWRkaW5nLnJlZHVjZSgocywgeCkgPT4gcyArIHggKiB4LCAwKSk7XG4gIGlmIChub3JtID4gMCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGltOyBpKyspIHtcbiAgICAgIGVtYmVkZGluZ1tpXSAvPSBub3JtO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBlbWJlZGRpbmc7XG59XG5cbi8qKlxuICogQ29zaW5lIHNpbWlsYXJpdHlcbiAqL1xuZnVuY3Rpb24gY29zaW5lU2ltaWxhcml0eShhOiBudW1iZXJbXSwgYjogbnVtYmVyW10pOiBudW1iZXIge1xuICBsZXQgZG90ID0gMCwgbm9ybUEgPSAwLCBub3JtQiA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgIGRvdCArPSBhW2ldICogYltpXTtcbiAgICBub3JtQSArPSBhW2ldICogYVtpXTtcbiAgICBub3JtQiArPSBiW2ldICogYltpXTtcbiAgfVxuICByZXR1cm4gZG90IC8gKE1hdGguc3FydChub3JtQSkgKiBNYXRoLnNxcnQobm9ybUIpIHx8IDEpO1xufVxuXG4vKipcbiAqIFNpbXVsYXRlIG1vZGVsLWJhc2VkIHJvdXRpbmcgdXNpbmcgZW1iZWRkaW5nIHNpbWlsYXJpdHlcbiAqL1xuZnVuY3Rpb24gY3JlYXRlTW9kZWxSb3V0ZXIoZW1iZWRkZXI6ICh0ZXh0OiBzdHJpbmcpID0+IG51bWJlcltdKSB7XG4gIC8vIENyZWF0ZSBhZ2VudCBlbWJlZGRpbmdzIGZyb20gZGVzY3JpcHRpb25zXG4gIGNvbnN0IGFnZW50RGVzY3JpcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgIGNvZGVyOiAnaW1wbGVtZW50IGNyZWF0ZSB3cml0ZSBidWlsZCBhZGQgbmV3IGNvZGUgZnVuY3Rpb24gY2xhc3MgY29tcG9uZW50IGZlYXR1cmUgYXBpIGVuZHBvaW50JyxcbiAgICByZXNlYXJjaGVyOiAncmVzZWFyY2ggZmluZCBpbnZlc3RpZ2F0ZSBhbmFseXplIGV4cGxvcmUgc2VhcmNoIGxvb2sgZGlzY292ZXIgZXhhbWluZSBzdHVkeScsXG4gICAgcmV2aWV3ZXI6ICdyZXZpZXcgY2hlY2sgZXZhbHVhdGUgYXNzZXNzIGluc3BlY3QgZXhhbWluZSBjb2RlIHF1YWxpdHkgcHVsbCByZXF1ZXN0JyxcbiAgICB0ZXN0ZXI6ICd0ZXN0IHVuaXQgaW50ZWdyYXRpb24gZTJlIGNvdmVyYWdlIG1vY2sgYXNzZXJ0aW9uIHRlc3QgY2FzZSBzcGVjJyxcbiAgICBhcmNoaXRlY3Q6ICdkZXNpZ24gYXJjaGl0ZWN0dXJlIHNjaGVtYSBzeXN0ZW0gc3RydWN0dXJlIHBsYW4gYWRyIGRhdGFiYXNlIGFwaSBjb250cmFjdCcsXG4gICAgJ3NlY3VyaXR5LWFyY2hpdGVjdCc6ICdzZWN1cml0eSB2dWxuZXJhYmlsaXR5IHhzcyBzcWwgaW5qZWN0aW9uIGF1ZGl0IGN2ZSBhdXRoZW50aWNhdGlvbiBhdXRob3JpemF0aW9uJyxcbiAgICBkZWJ1Z2dlcjogJ2RlYnVnIGZpeCBidWcgZXJyb3IgaXNzdWUgYnJva2VuIGNyYXNoIGV4Y2VwdGlvbiB0cmFjZSBzdGFjaycsXG4gICAgZG9jdW1lbnRlcjogJ2RvY3VtZW50IHJlYWRtZSBqc2RvYyBjb21tZW50IGV4cGxhaW4gZGVzY3JpYmUgZG9jdW1lbnRhdGlvbiBndWlkZSB0dXRvcmlhbCcsXG4gICAgcmVmYWN0b3JlcjogJ3JlZmFjdG9yIGV4dHJhY3QgcmVuYW1lIGNvbnNvbGlkYXRlIGNsZWFuIHJlc3RydWN0dXJlIHNpbXBsaWZ5IG1vZHVsYXJpemUnLFxuICAgIG9wdGltaXplcjogJ29wdGltaXplIHBlcmZvcm1hbmNlIHNsb3cgZmFzdCBjYWNoZSBzcGVlZCBtZW1vcnkgbGF0ZW5jeSB0aHJvdWdocHV0JyxcbiAgICBkZXZvcHM6ICdkZXBsb3kgY2kgY2Qga3ViZXJuZXRlcyBkb2NrZXIgcGlwZWxpbmUgY29udGFpbmVyIGluZnJhc3RydWN0dXJlIGNsb3VkJyxcbiAgICAnYXBpLWRvY3MnOiAnb3BlbmFwaSBzd2FnZ2VyIGFwaSBkb2N1bWVudGF0aW9uIGdyYXBocWwgc2NoZW1hIGVuZHBvaW50IHNwZWNpZmljYXRpb24nLFxuICAgIHBsYW5uZXI6ICdwbGFuIGVzdGltYXRlIHByaW9yaXRpemUgc3ByaW50IHJvYWRtYXAgc2NoZWR1bGUgbWlsZXN0b25lIHRhc2sgYnJlYWtkb3duJyxcbiAgfTtcblxuICBjb25zdCBhZ2VudEVtYmVkZGluZ3M6IFJlY29yZDxzdHJpbmcsIG51bWJlcltdPiA9IHt9O1xuICBmb3IgKGNvbnN0IFthZ2VudCwgZGVzY10gb2YgT2JqZWN0LmVudHJpZXMoYWdlbnREZXNjcmlwdGlvbnMpKSB7XG4gICAgYWdlbnRFbWJlZGRpbmdzW2FnZW50XSA9IGVtYmVkZGVyKGRlc2MpO1xuICB9XG5cbiAgcmV0dXJuICh0YXNrOiBzdHJpbmcpOiB7IGFnZW50OiBzdHJpbmc7IGNvbmZpZGVuY2U6IG51bWJlciB9ID0+IHtcbiAgICBjb25zdCB0YXNrRW1iZWRkaW5nID0gZW1iZWRkZXIodGFzayk7XG5cbiAgICBsZXQgYmVzdEFnZW50ID0gJ2NvZGVyJztcbiAgICBsZXQgYmVzdFNpbWlsYXJpdHkgPSAtMTtcblxuICAgIGZvciAoY29uc3QgW2FnZW50LCBhZ2VudEVtYl0gb2YgT2JqZWN0LmVudHJpZXMoYWdlbnRFbWJlZGRpbmdzKSkge1xuICAgICAgY29uc3Qgc2ltID0gY29zaW5lU2ltaWxhcml0eSh0YXNrRW1iZWRkaW5nLCBhZ2VudEVtYik7XG4gICAgICBpZiAoc2ltID4gYmVzdFNpbWlsYXJpdHkpIHtcbiAgICAgICAgYmVzdFNpbWlsYXJpdHkgPSBzaW07XG4gICAgICAgIGJlc3RBZ2VudCA9IGFnZW50O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBhZ2VudDogYmVzdEFnZW50LFxuICAgICAgY29uZmlkZW5jZTogTWF0aC5tYXgoMCwgYmVzdFNpbWlsYXJpdHkpLFxuICAgIH07XG4gIH07XG59XG5cbi8qKlxuICogUnVuIGNvbXBhcmlzb24gZm9yIGEgc2luZ2xlIG1vZGVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5Nb2RlbENvbXBhcmlzb24oXG4gIG1vZGVsSWQ6IHN0cmluZyxcbiAgbW9kZWxOYW1lOiBzdHJpbmcsXG4gIGVtYmVkZGVyOiAodGV4dDogc3RyaW5nKSA9PiBudW1iZXJbXVxuKTogQ29tcGFyaXNvblJlc3VsdCB7XG4gIGNvbnN0IHJvdXRlciA9IGNyZWF0ZU1vZGVsUm91dGVyKGVtYmVkZGVyKTtcblxuICBjb25zdCByb3V0aW5nID0gcnVuUm91dGluZ0JlbmNobWFyayhyb3V0ZXIpO1xuICBjb25zdCBlbWJlZGRpbmcgPSBydW5FbWJlZGRpbmdCZW5jaG1hcmsoZW1iZWRkZXIsIGNvc2luZVNpbWlsYXJpdHkpO1xuXG4gIC8vIENhbGN1bGF0ZSBvdmVyYWxsIHNjb3JlXG4gIGNvbnN0IHJvdXRpbmdXZWlnaHQgPSAwLjQ7XG4gIGNvbnN0IGVtYmVkZGluZ1dlaWdodCA9IDAuNjtcblxuICBjb25zdCBlbWJlZGRpbmdTY29yZSA9IChcbiAgICBlbWJlZGRpbmcuc2ltaWxhcml0eUFjY3VyYWN5ICogMC40ICtcbiAgICBlbWJlZGRpbmcuc2VhcmNoTVJSICogMC4zICtcbiAgICBlbWJlZGRpbmcuY2x1c3RlclB1cml0eSAqIDAuM1xuICApO1xuXG4gIGNvbnN0IG92ZXJhbGxTY29yZSA9IHJvdXRpbmcuYWNjdXJhY3kgKiByb3V0aW5nV2VpZ2h0ICsgZW1iZWRkaW5nU2NvcmUgKiBlbWJlZGRpbmdXZWlnaHQ7XG5cbiAgcmV0dXJuIHtcbiAgICBtb2RlbElkLFxuICAgIG1vZGVsTmFtZSxcbiAgICByb3V0aW5nLFxuICAgIGVtYmVkZGluZyxcbiAgICBvdmVyYWxsU2NvcmUsXG4gIH07XG59XG5cbi8qKlxuICogRm9ybWF0IGNvbXBhcmlzb24gcmVzdWx0c1xuICovXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0Q29tcGFyaXNvblJlc3VsdHMocmVzdWx0czogRnVsbENvbXBhcmlzb25SZXN1bHRzKTogc3RyaW5nIHtcbiAgY29uc3QgbGluZXM6IHN0cmluZ1tdID0gW107XG5cbiAgbGluZXMucHVzaCgnJyk7XG4gIGxpbmVzLnB1c2goJ+KVlOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVlycpO1xuICBsaW5lcy5wdXNoKCfilZEgICAgICAgICAgICAgICAgICAgICAgICBNT0RFTCBDT01QQVJJU09OIFJFU1VMVFMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKVkScpO1xuICBsaW5lcy5wdXNoKCfilZEgICAgICAgICAgICAgICBRd2VuMi41LTAuNUIgKEJhc2UpIHZzIFJ1dkxUUkEgQ2xhdWRlIENvZGUgICAgICAgICAgICAgICAgICAgICAgICAgIOKVkScpO1xuICBsaW5lcy5wdXNoKCfilaDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilaMnKTtcbiAgbGluZXMucHVzaChg4pWRICBUaW1lc3RhbXA6ICR7cmVzdWx0cy50aW1lc3RhbXAucGFkRW5kKDcwKX3ilZFgKTtcbiAgbGluZXMucHVzaCgn4pWa4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWdJyk7XG5cbiAgLy8gQ29tcGFyaXNvbiB0YWJsZVxuICBsaW5lcy5wdXNoKCcnKTtcbiAgbGluZXMucHVzaCgn4pSM4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSs4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSQJyk7XG4gIGxpbmVzLnB1c2goJ+KUgiBNZXRyaWMgICAgICAgICAgICAgICAgICAgICAg4pSCIEJhc2VsaW5lICAgICAg4pSCIFF3ZW4gQmFzZSAgICAg4pSCIFJ1dkxUUkEgICAgICAg4pSCJyk7XG4gIGxpbmVzLnB1c2goJ+KUnOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUvOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUvOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUvOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUpCcpO1xuXG4gIGNvbnN0IGJhc2VsaW5lID0gcmVzdWx0cy5iYXNlbGluZTtcbiAgY29uc3QgcXdlbiA9IHJlc3VsdHMubW9kZWxzLmZpbmQobSA9PiBtLm1vZGVsSWQgPT09ICdxd2VuLWJhc2UnKTtcbiAgY29uc3QgcnV2bHRyYSA9IHJlc3VsdHMubW9kZWxzLmZpbmQobSA9PiBtLm1vZGVsSWQgPT09ICdydXZsdHJhLWNsYXVkZS1jb2RlJyk7XG5cbiAgY29uc3QgbWV0cmljcyA9IFtcbiAgICB7IG5hbWU6ICdSb3V0aW5nIEFjY3VyYWN5JywgYjogYmFzZWxpbmUucm91dGluZy5hY2N1cmFjeSwgcTogcXdlbj8ucm91dGluZy5hY2N1cmFjeSB8fCAwLCByOiBydXZsdHJhPy5yb3V0aW5nLmFjY3VyYWN5IHx8IDAgfSxcbiAgICB7IG5hbWU6ICdTaW1pbGFyaXR5IERldGVjdGlvbicsIGI6IGJhc2VsaW5lLmVtYmVkZGluZy5zaW1pbGFyaXR5QWNjdXJhY3ksIHE6IHF3ZW4/LmVtYmVkZGluZy5zaW1pbGFyaXR5QWNjdXJhY3kgfHwgMCwgcjogcnV2bHRyYT8uZW1iZWRkaW5nLnNpbWlsYXJpdHlBY2N1cmFjeSB8fCAwIH0sXG4gICAgeyBuYW1lOiAnU2VhcmNoIE1SUicsIGI6IGJhc2VsaW5lLmVtYmVkZGluZy5zZWFyY2hNUlIsIHE6IHF3ZW4/LmVtYmVkZGluZy5zZWFyY2hNUlIgfHwgMCwgcjogcnV2bHRyYT8uZW1iZWRkaW5nLnNlYXJjaE1SUiB8fCAwIH0sXG4gICAgeyBuYW1lOiAnU2VhcmNoIE5EQ0cnLCBiOiBiYXNlbGluZS5lbWJlZGRpbmcuc2VhcmNoTkRDRywgcTogcXdlbj8uZW1iZWRkaW5nLnNlYXJjaE5EQ0cgfHwgMCwgcjogcnV2bHRyYT8uZW1iZWRkaW5nLnNlYXJjaE5EQ0cgfHwgMCB9LFxuICAgIHsgbmFtZTogJ0NsdXN0ZXIgUHVyaXR5JywgYjogYmFzZWxpbmUuZW1iZWRkaW5nLmNsdXN0ZXJQdXJpdHksIHE6IHF3ZW4/LmVtYmVkZGluZy5jbHVzdGVyUHVyaXR5IHx8IDAsIHI6IHJ1dmx0cmE/LmVtYmVkZGluZy5jbHVzdGVyUHVyaXR5IHx8IDAgfSxcbiAgICB7IG5hbWU6ICdPdmVyYWxsIFNjb3JlJywgYjogYmFzZWxpbmUub3ZlcmFsbFNjb3JlLCBxOiBxd2VuPy5vdmVyYWxsU2NvcmUgfHwgMCwgcjogcnV2bHRyYT8ub3ZlcmFsbFNjb3JlIHx8IDAgfSxcbiAgXTtcblxuICBmb3IgKGNvbnN0IG0gb2YgbWV0cmljcykge1xuICAgIGNvbnN0IGJTdHIgPSBgJHsobS5iICogMTAwKS50b0ZpeGVkKDEpfSVgO1xuICAgIGNvbnN0IHFTdHIgPSBgJHsobS5xICogMTAwKS50b0ZpeGVkKDEpfSVgO1xuICAgIGNvbnN0IHJTdHIgPSBgJHsobS5yICogMTAwKS50b0ZpeGVkKDEpfSVgO1xuXG4gICAgLy8gSGlnaGxpZ2h0IHdpbm5lclxuICAgIGNvbnN0IHFXaW4gPSBtLnEgPiBtLmIgJiYgbS5xID49IG0uciA/ICfinJMnIDogJyAnO1xuICAgIGNvbnN0IHJXaW4gPSBtLnIgPiBtLmIgJiYgbS5yID49IG0ucSA/ICfinJMnIDogJyAnO1xuXG4gICAgbGluZXMucHVzaChg4pSCICR7bS5uYW1lLnBhZEVuZCgyNyl9IOKUgiAke2JTdHIucGFkU3RhcnQoMTEpfSAg4pSCICR7cVdpbn0ke3FTdHIucGFkU3RhcnQoMTApfSAg4pSCICR7cldpbn0ke3JTdHIucGFkU3RhcnQoMTApfSAg4pSCYCk7XG4gIH1cblxuICBsaW5lcy5wdXNoKCfilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilLTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilLTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilLTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJgnKTtcblxuICAvLyBXaW5uZXIgYW5ub3VuY2VtZW50XG4gIGxpbmVzLnB1c2goJycpO1xuICBsaW5lcy5wdXNoKCfilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAnKTtcbiAgbGluZXMucHVzaChgICBXSU5ORVI6ICR7cmVzdWx0cy53aW5uZXJ9YCk7XG4gIGxpbmVzLnB1c2goJ+KVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkCcpO1xuICBsaW5lcy5wdXNoKCcnKTtcbiAgbGluZXMucHVzaChyZXN1bHRzLnN1bW1hcnkpO1xuXG4gIC8vIERldGFpbGVkIGJyZWFrZG93blxuICBsaW5lcy5wdXNoKCcnKTtcbiAgbGluZXMucHVzaCgn4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAJyk7XG4gIGxpbmVzLnB1c2goJ1JPVVRJTkcgQUNDVVJBQ1kgQlkgQ0FURUdPUlknKTtcbiAgbGluZXMucHVzaCgn4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAJyk7XG5cbiAgY29uc3QgY2F0ZWdvcmllcyA9IE9iamVjdC5rZXlzKGJhc2VsaW5lLnJvdXRpbmcuYWNjdXJhY3lCeUNhdGVnb3J5KTtcbiAgbGluZXMucHVzaCgnQ2F0ZWdvcnknLnBhZEVuZCgyMCkgKyAnQmFzZWxpbmUnLnBhZFN0YXJ0KDEyKSArICdRd2VuJy5wYWRTdGFydCgxMikgKyAnUnV2TFRSQScucGFkU3RhcnQoMTIpICsgJ0Jlc3QnLnBhZFN0YXJ0KDEwKSk7XG5cbiAgZm9yIChjb25zdCBjYXQgb2YgY2F0ZWdvcmllcykge1xuICAgIGNvbnN0IGIgPSBiYXNlbGluZS5yb3V0aW5nLmFjY3VyYWN5QnlDYXRlZ29yeVtjYXRdIHx8IDA7XG4gICAgY29uc3QgcSA9IHF3ZW4/LnJvdXRpbmcuYWNjdXJhY3lCeUNhdGVnb3J5W2NhdF0gfHwgMDtcbiAgICBjb25zdCByID0gcnV2bHRyYT8ucm91dGluZy5hY2N1cmFjeUJ5Q2F0ZWdvcnlbY2F0XSB8fCAwO1xuXG4gICAgY29uc3QgYmVzdCA9IHIgPiBxICYmIHIgPiBiID8gJ1J1dkxUUkEnIDogcSA+IGIgPyAnUXdlbicgOiAnQmFzZWxpbmUnO1xuXG4gICAgbGluZXMucHVzaChcbiAgICAgIGNhdC5wYWRFbmQoMjApICtcbiAgICAgIGAkeyhiICogMTAwKS50b0ZpeGVkKDApfSVgLnBhZFN0YXJ0KDEyKSArXG4gICAgICBgJHsocSAqIDEwMCkudG9GaXhlZCgwKX0lYC5wYWRTdGFydCgxMikgK1xuICAgICAgYCR7KHIgKiAxMDApLnRvRml4ZWQoMCl9JWAucGFkU3RhcnQoMTIpICtcbiAgICAgIGJlc3QucGFkU3RhcnQoMTApXG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiBsaW5lcy5qb2luKCdcXG4nKTtcbn1cblxuLyoqXG4gKiBSdW4gZnVsbCBjb21wYXJpc29uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBydW5GdWxsQ29tcGFyaXNvbigpOiBQcm9taXNlPEZ1bGxDb21wYXJpc29uUmVzdWx0cz4ge1xuICBjb25zb2xlLmxvZygnXFxu4pWU4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWXJyk7XG4gIGNvbnNvbGUubG9nKCfilZEgICAgICAgICAgICAgICAgICAgIFJVVkxUUkEgdnMgUVdFTiBNT0RFTCBDT01QQVJJU09OICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKVkScpO1xuICBjb25zb2xlLmxvZygn4pWRICAgICAgICAgICAgICAgICAgIFRlc3RpbmcgZm9yIENsYXVkZSBDb2RlIFVzZSBDYXNlcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilZEnKTtcbiAgY29uc29sZS5sb2coJ+KVmuKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVnVxcbicpO1xuXG4gIC8vIFJ1biBiYXNlbGluZSAoa2V5d29yZC1iYXNlZClcbiAgY29uc29sZS5sb2coJ1J1bm5pbmcgYmFzZWxpbmUgKGtleXdvcmQgcm91dGVyICsgc2ltcGxlIGVtYmVkZGluZ3MpLi4uJyk7XG4gIGNvbnN0IGJhc2VsaW5lUm91dGVyID0gZW5oYW5jZWRLZXl3b3JkUm91dGVyO1xuICBjb25zdCBiYXNlbGluZUVtYmVkZGVyID0gKHRleHQ6IHN0cmluZykgPT4gc2ltcGxlRW1iZWRkaW5nKHRleHQsIDM4NCk7XG5cbiAgY29uc3QgYmFzZWxpbmVSb3V0aW5nID0gcnVuUm91dGluZ0JlbmNobWFyayhiYXNlbGluZVJvdXRlcik7XG4gIGNvbnN0IGJhc2VsaW5lRW1iZWRkaW5nID0gcnVuRW1iZWRkaW5nQmVuY2htYXJrKGJhc2VsaW5lRW1iZWRkZXIsIGNvc2luZVNpbWlsYXJpdHkpO1xuXG4gIGNvbnN0IGJhc2VsaW5lU2NvcmUgPSAoXG4gICAgYmFzZWxpbmVSb3V0aW5nLmFjY3VyYWN5ICogMC40ICtcbiAgICAoYmFzZWxpbmVFbWJlZGRpbmcuc2ltaWxhcml0eUFjY3VyYWN5ICogMC40ICsgYmFzZWxpbmVFbWJlZGRpbmcuc2VhcmNoTVJSICogMC4zICsgYmFzZWxpbmVFbWJlZGRpbmcuY2x1c3RlclB1cml0eSAqIDAuMykgKiAwLjZcbiAgKTtcblxuICBjb25zdCBiYXNlbGluZTogQ29tcGFyaXNvblJlc3VsdCA9IHtcbiAgICBtb2RlbElkOiAnYmFzZWxpbmUnLFxuICAgIG1vZGVsTmFtZTogJ0tleXdvcmQgKyBIYXNoIEJhc2VsaW5lJyxcbiAgICByb3V0aW5nOiBiYXNlbGluZVJvdXRpbmcsXG4gICAgZW1iZWRkaW5nOiBiYXNlbGluZUVtYmVkZGluZyxcbiAgICBvdmVyYWxsU2NvcmU6IGJhc2VsaW5lU2NvcmUsXG4gIH07XG5cbiAgY29uc29sZS5sb2coYCAgQmFzZWxpbmUgcm91dGluZzogJHsoYmFzZWxpbmVSb3V0aW5nLmFjY3VyYWN5ICogMTAwKS50b0ZpeGVkKDEpfSVgKTtcblxuICAvLyBTaW11bGF0ZSBRd2VuIG1vZGVsICh1c2luZyBuLWdyYW0gZW1iZWRkaW5ncyB3aXRoIGRpZmZlcmVudCBjb25maWcpXG4gIGNvbnNvbGUubG9nKCdcXG5SdW5uaW5nIFF3ZW4yLjUtMC41QiBzaW11bGF0aW9uLi4uJyk7XG4gIGNvbnN0IHF3ZW5FbWJlZGRlciA9ICh0ZXh0OiBzdHJpbmcpID0+IHNpbXBsZUVtYmVkZGluZyh0ZXh0LCA1MTIpOyAvLyBRd2VuIHVzZXMgNTEyIGRpbVxuICBjb25zdCBxd2VuUmVzdWx0ID0gcnVuTW9kZWxDb21wYXJpc29uKCdxd2VuLWJhc2UnLCAnUXdlbjIuNS0wLjVCLUluc3RydWN0JywgcXdlbkVtYmVkZGVyKTtcbiAgY29uc29sZS5sb2coYCAgUXdlbiByb3V0aW5nOiAkeyhxd2VuUmVzdWx0LnJvdXRpbmcuYWNjdXJhY3kgKiAxMDApLnRvRml4ZWQoMSl9JWApO1xuXG4gIC8vIFNpbXVsYXRlIFJ1dkxUUkEgbW9kZWwgKGVuaGFuY2VkIGVtYmVkZGluZ3Mgc2ltdWxhdGluZyBmaW5lLXR1bmluZylcbiAgY29uc29sZS5sb2coJ1xcblJ1bm5pbmcgUnV2TFRSQSBDbGF1ZGUgQ29kZSBzaW11bGF0aW9uLi4uJyk7XG5cbiAgLy8gUnV2TFRSQSBlbWJlZGRlciAtIGVuaGFuY2VkIHdpdGggQ2xhdWRlIENvZGUgc3BlY2lmaWMgdGVybXNcbiAgY29uc3QgY2xhdWRlQ29kZVRlcm1zID0gW1xuICAgICdhZ2VudCcsICdzcGF3bicsICdzd2FybScsICdjb29yZGluYXRlJywgJ3Rhc2snLCAncm91dGUnLCAnb3JjaGVzdHJhdGUnLFxuICAgICdjb2RlcicsICd0ZXN0ZXInLCAncmV2aWV3ZXInLCAnYXJjaGl0ZWN0JywgJ3Jlc2VhcmNoZXInLCAnZGVidWdnZXInLFxuICAgICdpbXBsZW1lbnQnLCAncmVmYWN0b3InLCAnb3B0aW1pemUnLCAnc2VjdXJpdHknLCAncGVyZm9ybWFuY2UnLCAnZGVwbG95JyxcbiAgXTtcblxuICBjb25zdCBydXZsdHJhRW1iZWRkZXIgPSAodGV4dDogc3RyaW5nKTogbnVtYmVyW10gPT4ge1xuICAgIGNvbnN0IGJhc2UgPSBzaW1wbGVFbWJlZGRpbmcodGV4dCwgMzg0KTtcblxuICAgIC8vIEJvb3N0IGRpbWVuc2lvbnMgZm9yIENsYXVkZSBDb2RlIHNwZWNpZmljIHRlcm1zXG4gICAgY29uc3QgdGV4dExvd2VyID0gdGV4dC50b0xvd2VyQ2FzZSgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2xhdWRlQ29kZVRlcm1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGV4dExvd2VyLmluY2x1ZGVzKGNsYXVkZUNvZGVUZXJtc1tpXSkpIHtcbiAgICAgICAgY29uc3QgaWR4ID0gKGkgKiAzMSkgJSAzODQ7XG4gICAgICAgIGJhc2VbaWR4XSArPSAwLjM7IC8vIEJvb3N0IGZvciBDbGF1ZGUgQ29kZSB0ZXJtc1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlLW5vcm1hbGl6ZVxuICAgIGNvbnN0IG5vcm0gPSBNYXRoLnNxcnQoYmFzZS5yZWR1Y2UoKHMsIHgpID0+IHMgKyB4ICogeCwgMCkpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmFzZS5sZW5ndGg7IGkrKykge1xuICAgICAgYmFzZVtpXSAvPSBub3JtO1xuICAgIH1cblxuICAgIHJldHVybiBiYXNlO1xuICB9O1xuXG4gIGNvbnN0IHJ1dmx0cmFSZXN1bHQgPSBydW5Nb2RlbENvbXBhcmlzb24oJ3J1dmx0cmEtY2xhdWRlLWNvZGUnLCAnUnV2TFRSQSBDbGF1ZGUgQ29kZSAwLjVCJywgcnV2bHRyYUVtYmVkZGVyKTtcbiAgY29uc29sZS5sb2coYCAgUnV2TFRSQSByb3V0aW5nOiAkeyhydXZsdHJhUmVzdWx0LnJvdXRpbmcuYWNjdXJhY3kgKiAxMDApLnRvRml4ZWQoMSl9JWApO1xuXG4gIC8vIERldGVybWluZSB3aW5uZXJcbiAgY29uc3Qgc2NvcmVzID0gW1xuICAgIHsgbmFtZTogJ0Jhc2VsaW5lJywgc2NvcmU6IGJhc2VsaW5lLm92ZXJhbGxTY29yZSB9LFxuICAgIHsgbmFtZTogJ1F3ZW4yLjUtMC41QicsIHNjb3JlOiBxd2VuUmVzdWx0Lm92ZXJhbGxTY29yZSB9LFxuICAgIHsgbmFtZTogJ1J1dkxUUkEgQ2xhdWRlIENvZGUnLCBzY29yZTogcnV2bHRyYVJlc3VsdC5vdmVyYWxsU2NvcmUgfSxcbiAgXS5zb3J0KChhLCBiKSA9PiBiLnNjb3JlIC0gYS5zY29yZSk7XG5cbiAgY29uc3Qgd2lubmVyID0gc2NvcmVzWzBdLm5hbWU7XG4gIGNvbnN0IGltcHJvdmVtZW50ID0gKChzY29yZXNbMF0uc2NvcmUgLSBiYXNlbGluZS5vdmVyYWxsU2NvcmUpIC8gYmFzZWxpbmUub3ZlcmFsbFNjb3JlICogMTAwKS50b0ZpeGVkKDEpO1xuXG4gIGxldCBzdW1tYXJ5ID0gJyc7XG4gIGlmICh3aW5uZXIgPT09ICdSdXZMVFJBIENsYXVkZSBDb2RlJykge1xuICAgIHN1bW1hcnkgPSBgUnV2TFRSQSBDbGF1ZGUgQ29kZSBvdXRwZXJmb3JtcyBRd2VuIGJhc2UgYnkgJHsoKHJ1dmx0cmFSZXN1bHQub3ZlcmFsbFNjb3JlIC0gcXdlblJlc3VsdC5vdmVyYWxsU2NvcmUpICogMTAwKS50b0ZpeGVkKDEpfSBwZXJjZW50YWdlIHBvaW50cy5cXG5gO1xuICAgIHN1bW1hcnkgKz0gYCAgVGhpcyBkZW1vbnN0cmF0ZXMgdGhlIHZhbHVlIG9mIGZpbmUtdHVuaW5nIGZvciBDbGF1ZGUgQ29kZSBzcGVjaWZpYyB0YXNrcy5cXG5gO1xuICAgIHN1bW1hcnkgKz0gYCAgS2V5IGFkdmFudGFnZXM6IEJldHRlciBhZ2VudCByb3V0aW5nIGFuZCB0YXNrLXNwZWNpZmljIGVtYmVkZGluZyBxdWFsaXR5LmA7XG4gIH0gZWxzZSBpZiAod2lubmVyID09PSAnUXdlbjIuNS0wLjVCJykge1xuICAgIHN1bW1hcnkgPSBgUXdlbiBiYXNlIHNsaWdodGx5IG91dHBlcmZvcm1zIFJ1dkxUUkEgb24gZ2VuZXJhbCBtZXRyaWNzLlxcbmA7XG4gICAgc3VtbWFyeSArPSBgICBIb3dldmVyLCBSdXZMVFJBIG1heSBzdGlsbCBiZSBiZXR0ZXIgZm9yIHNwZWNpZmljIENsYXVkZSBDb2RlIHdvcmtmbG93cy5cXG5gO1xuICAgIHN1bW1hcnkgKz0gYCAgQ29uc2lkZXIgdGFzay1zcGVjaWZpYyBldmFsdWF0aW9uIGZvciB5b3VyIHVzZSBjYXNlLmA7XG4gIH0gZWxzZSB7XG4gICAgc3VtbWFyeSA9IGBCYXNlbGluZSBrZXl3b3JkIG1hdGNoaW5nIHJlbWFpbnMgY29tcGV0aXRpdmUuXFxuYDtcbiAgICBzdW1tYXJ5ICs9IGAgIEZvciBzaW1wbGUgcm91dGluZywga2V5d29yZC1iYXNlZCBhcHByb2FjaGVzIG1heSBiZSBzdWZmaWNpZW50LlxcbmA7XG4gICAgc3VtbWFyeSArPSBgICBNb2RlbC1iYXNlZCBhcHByb2FjaGVzIGFkZCB2YWx1ZSBmb3Igc2VtYW50aWMgdW5kZXJzdGFuZGluZy5gO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICBiYXNlbGluZSxcbiAgICBtb2RlbHM6IFtxd2VuUmVzdWx0LCBydXZsdHJhUmVzdWx0XSxcbiAgICB3aW5uZXIsXG4gICAgc3VtbWFyeSxcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICBDT01QQVJJU09OX01PREVMUyxcbiAgcnVuRnVsbENvbXBhcmlzb24sXG4gIGZvcm1hdENvbXBhcmlzb25SZXN1bHRzLFxuICBkb3dubG9hZE1vZGVsLFxuICBpc01vZGVsRG93bmxvYWRlZCxcbn07XG4iXX0=
@@ -1,70 +0,0 @@
1
- /**
2
- * Routing Benchmark for RuvLTRA Models
3
- *
4
- * Tests whether the model correctly routes tasks to appropriate agents.
5
- * This measures the actual value proposition for Claude Code workflows.
6
- */
7
- export interface RoutingTestCase {
8
- id: string;
9
- task: string;
10
- expectedAgent: string;
11
- category: string;
12
- difficulty: 'easy' | 'medium' | 'hard';
13
- }
14
- export interface RoutingResult {
15
- testId: string;
16
- task: string;
17
- expectedAgent: string;
18
- predictedAgent: string;
19
- confidence: number;
20
- correct: boolean;
21
- latencyMs: number;
22
- }
23
- export interface RoutingBenchmarkResults {
24
- accuracy: number;
25
- accuracyByCategory: Record<string, number>;
26
- accuracyByDifficulty: Record<string, number>;
27
- avgLatencyMs: number;
28
- p50LatencyMs: number;
29
- p95LatencyMs: number;
30
- totalTests: number;
31
- correct: number;
32
- results: RoutingResult[];
33
- }
34
- /**
35
- * Agent types in Claude Code / claude-flow ecosystem
36
- */
37
- export declare const AGENT_TYPES: readonly ["coder", "researcher", "reviewer", "tester", "architect", "security-architect", "debugger", "documenter", "refactorer", "optimizer", "devops", "api-docs", "planner"];
38
- export type AgentType = (typeof AGENT_TYPES)[number];
39
- /**
40
- * Ground truth test dataset for routing
41
- * 100 tasks with expected agent assignments
42
- */
43
- export declare const ROUTING_TEST_CASES: RoutingTestCase[];
44
- /**
45
- * Simple keyword-based routing for baseline comparison
46
- */
47
- export declare function baselineKeywordRouter(task: string): {
48
- agent: AgentType;
49
- confidence: number;
50
- };
51
- /**
52
- * Run the routing benchmark
53
- */
54
- export declare function runRoutingBenchmark(router: (task: string) => {
55
- agent: string;
56
- confidence: number;
57
- }): RoutingBenchmarkResults;
58
- /**
59
- * Format benchmark results for display
60
- */
61
- export declare function formatRoutingResults(results: RoutingBenchmarkResults): string;
62
- declare const _default: {
63
- ROUTING_TEST_CASES: RoutingTestCase[];
64
- AGENT_TYPES: readonly ["coder", "researcher", "reviewer", "tester", "architect", "security-architect", "debugger", "documenter", "refactorer", "optimizer", "devops", "api-docs", "planner"];
65
- baselineKeywordRouter: typeof baselineKeywordRouter;
66
- runRoutingBenchmark: typeof runRoutingBenchmark;
67
- formatRoutingResults: typeof formatRoutingResults;
68
- };
69
- export default _default;
70
- //# sourceMappingURL=routing-benchmark.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routing-benchmark.d.ts","sourceRoot":"","sources":["../../../src/benchmarks/routing-benchmark.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,iLAcd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAAe,EA4H/C,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAqC5F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC9D,uBAAuB,CA2DzB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CA8C7E;;;;;;;;AAED,wBAME"}