@thinkhive/sdk 2.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.
package/dist/index.js ADDED
@@ -0,0 +1,639 @@
1
+ "use strict";
2
+ /**
3
+ * ThinkHive TypeScript SDK
4
+ * OpenTelemetry-based observability for AI agents with Explainer integration
5
+ *
6
+ * @version 2.0.0
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.analytics = exports.quality = exports.feedback = exports.explainer = void 0;
10
+ exports.init = init;
11
+ exports.getTracer = getTracer;
12
+ exports.isInitialized = isInitialized;
13
+ exports.traceLLM = traceLLM;
14
+ exports.traceRetrieval = traceRetrieval;
15
+ exports.traceTool = traceTool;
16
+ exports.traceChain = traceChain;
17
+ exports.createAndAnalyze = createAndAnalyze;
18
+ const api_1 = require("@opentelemetry/api");
19
+ const exporter_trace_otlp_proto_1 = require("@opentelemetry/exporter-trace-otlp-proto");
20
+ const resources_1 = require("@opentelemetry/resources");
21
+ const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
22
+ const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
23
+ // ============================================================================
24
+ // GLOBAL STATE
25
+ // ============================================================================
26
+ let tracer = null;
27
+ let initialized = false;
28
+ let config;
29
+ const DEFAULT_ENDPOINT = "https://thinkhivemind-h25z7pvd3q-uc.a.run.app";
30
+ // ============================================================================
31
+ // HTTP CLIENT
32
+ // ============================================================================
33
+ async function apiRequest(path, options = {}) {
34
+ const { method = 'GET', body, headers = {} } = options;
35
+ const url = `${config.endpoint}/api/v1${path}`;
36
+ const requestHeaders = {
37
+ 'Content-Type': 'application/json',
38
+ ...headers,
39
+ };
40
+ if (config.apiKey) {
41
+ requestHeaders['Authorization'] = `Bearer ${config.apiKey}`;
42
+ }
43
+ else if (config.agentId) {
44
+ requestHeaders['X-Agent-ID'] = config.agentId;
45
+ }
46
+ const response = await fetch(url, {
47
+ method,
48
+ headers: requestHeaders,
49
+ body: body ? JSON.stringify(body) : undefined,
50
+ });
51
+ if (!response.ok) {
52
+ const error = await response.text();
53
+ throw new Error(`ThinkHive API error: ${response.status} - ${error}`);
54
+ }
55
+ return response.json();
56
+ }
57
+ // ============================================================================
58
+ // INITIALIZATION
59
+ // ============================================================================
60
+ /**
61
+ * Initialize ThinkHive SDK
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * import { init } from '@thinkhive/sdk';
66
+ *
67
+ * init({
68
+ * apiKey: 'th_your_api_key',
69
+ * serviceName: 'my-ai-agent',
70
+ * autoInstrument: true,
71
+ * frameworks: ['langchain', 'openai'],
72
+ * });
73
+ * ```
74
+ */
75
+ function init(options = {}) {
76
+ if (initialized) {
77
+ if (options.debug) {
78
+ console.log('ThinkHive SDK already initialized');
79
+ }
80
+ return;
81
+ }
82
+ const apiKey = options.apiKey || process.env.THINKHIVE_API_KEY;
83
+ const agentId = options.agentId || process.env.THINKHIVE_AGENT_ID;
84
+ if (!apiKey && !agentId) {
85
+ throw new Error("Either apiKey or agentId must be provided (or set THINKHIVE_API_KEY env var)");
86
+ }
87
+ config = {
88
+ apiKey: apiKey || '',
89
+ agentId: agentId || '',
90
+ endpoint: options.endpoint || process.env.THINKHIVE_ENDPOINT || DEFAULT_ENDPOINT,
91
+ serviceName: options.serviceName || process.env.THINKHIVE_SERVICE_NAME || 'my-ai-agent',
92
+ autoInstrument: options.autoInstrument ?? false,
93
+ frameworks: options.frameworks || ['langchain', 'openai'],
94
+ debug: options.debug ?? false,
95
+ };
96
+ // Configure OTLP exporter
97
+ const exporterHeaders = {};
98
+ if (config.apiKey) {
99
+ exporterHeaders["Authorization"] = `Bearer ${config.apiKey}`;
100
+ }
101
+ else if (config.agentId) {
102
+ exporterHeaders["X-Agent-ID"] = config.agentId;
103
+ }
104
+ const exporter = new exporter_trace_otlp_proto_1.OTLPTraceExporter({
105
+ url: `${config.endpoint}/v1/traces`,
106
+ headers: exporterHeaders,
107
+ });
108
+ // Create OpenTelemetry resource
109
+ const resource = resources_1.Resource.default().merge(new resources_1.Resource({
110
+ "service.name": config.serviceName,
111
+ "thinkhive.sdk.version": "2.0.0",
112
+ "thinkhive.sdk.language": "typescript",
113
+ }));
114
+ // Create provider with span processor
115
+ const provider = new sdk_trace_node_1.NodeTracerProvider({
116
+ resource,
117
+ spanProcessors: [new sdk_trace_base_1.BatchSpanProcessor(exporter)],
118
+ });
119
+ // Register provider
120
+ provider.register();
121
+ // Get tracer
122
+ tracer = api_1.trace.getTracer("thinkhive", "2.0.0");
123
+ initialized = true;
124
+ if (config.debug) {
125
+ console.log(`✅ ThinkHive SDK initialized`);
126
+ console.log(` Endpoint: ${config.endpoint}`);
127
+ console.log(` Service: ${config.serviceName}`);
128
+ console.log(` Auto-instrument: ${config.autoInstrument}`);
129
+ }
130
+ // Setup auto-instrumentation if enabled
131
+ if (config.autoInstrument) {
132
+ setupAutoInstrumentation(config.frameworks);
133
+ }
134
+ }
135
+ /**
136
+ * Get the global tracer
137
+ */
138
+ function getTracer() {
139
+ if (!initialized || !tracer) {
140
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
141
+ }
142
+ return tracer;
143
+ }
144
+ /**
145
+ * Check if SDK is initialized
146
+ */
147
+ function isInitialized() {
148
+ return initialized;
149
+ }
150
+ // ============================================================================
151
+ // TRACING FUNCTIONS
152
+ // ============================================================================
153
+ /**
154
+ * Trace an LLM call
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * const response = await traceLLM({
159
+ * name: 'chat_completion',
160
+ * modelName: 'gpt-4',
161
+ * provider: 'openai',
162
+ * }, async () => {
163
+ * return await openai.chat.completions.create({ ... });
164
+ * });
165
+ * ```
166
+ */
167
+ function traceLLM(options, fn) {
168
+ const t = getTracer();
169
+ return t.startActiveSpan(options.name, {
170
+ attributes: {
171
+ "openinference.span.kind": "LLM",
172
+ "llm.model_name": options.modelName,
173
+ "llm.provider": options.provider,
174
+ "input.value": options.input ? JSON.stringify(options.input).substring(0, 10000) : undefined,
175
+ },
176
+ }, async (span) => {
177
+ const startTime = Date.now();
178
+ try {
179
+ const result = await fn();
180
+ span.setAttribute("output.value", JSON.stringify(result).substring(0, 10000));
181
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
182
+ return result;
183
+ }
184
+ catch (error) {
185
+ const message = error instanceof Error ? error.message : String(error);
186
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message });
187
+ span.recordException(error);
188
+ throw error;
189
+ }
190
+ finally {
191
+ span.setAttribute("duration_ms", Date.now() - startTime);
192
+ span.end();
193
+ }
194
+ });
195
+ }
196
+ /**
197
+ * Trace a retrieval operation
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * const docs = await traceRetrieval({
202
+ * name: 'vector_search',
203
+ * query: 'What is the return policy?',
204
+ * }, async () => {
205
+ * return await vectorStore.similaritySearch(query, 5);
206
+ * });
207
+ * ```
208
+ */
209
+ function traceRetrieval(options, fn) {
210
+ const t = getTracer();
211
+ return t.startActiveSpan(options.name, {
212
+ attributes: {
213
+ "openinference.span.kind": "RETRIEVER",
214
+ "retrieval.query": options.query,
215
+ "retrieval.top_k": options.topK,
216
+ },
217
+ }, async (span) => {
218
+ const startTime = Date.now();
219
+ try {
220
+ const result = await fn();
221
+ // Try to extract document count from result
222
+ if (Array.isArray(result)) {
223
+ span.setAttribute("retrieval.document_count", result.length);
224
+ }
225
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
226
+ return result;
227
+ }
228
+ catch (error) {
229
+ const message = error instanceof Error ? error.message : String(error);
230
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message });
231
+ span.recordException(error);
232
+ throw error;
233
+ }
234
+ finally {
235
+ span.setAttribute("duration_ms", Date.now() - startTime);
236
+ span.end();
237
+ }
238
+ });
239
+ }
240
+ /**
241
+ * Trace a tool call
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * const result = await traceTool({
246
+ * name: 'search_orders',
247
+ * toolName: 'OrderLookup',
248
+ * parameters: { orderId: '12345' },
249
+ * }, async () => {
250
+ * return await orderService.lookup('12345');
251
+ * });
252
+ * ```
253
+ */
254
+ function traceTool(options, fn) {
255
+ const t = getTracer();
256
+ return t.startActiveSpan(options.toolName || options.name, {
257
+ attributes: {
258
+ "openinference.span.kind": "TOOL",
259
+ "tool.name": options.toolName || options.name,
260
+ "tool.parameters": options.parameters ? JSON.stringify(options.parameters) : undefined,
261
+ },
262
+ }, async (span) => {
263
+ const startTime = Date.now();
264
+ try {
265
+ const result = await fn();
266
+ span.setAttribute("tool.output", JSON.stringify(result).substring(0, 10000));
267
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
268
+ return result;
269
+ }
270
+ catch (error) {
271
+ const message = error instanceof Error ? error.message : String(error);
272
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message });
273
+ span.recordException(error);
274
+ throw error;
275
+ }
276
+ finally {
277
+ span.setAttribute("duration_ms", Date.now() - startTime);
278
+ span.end();
279
+ }
280
+ });
281
+ }
282
+ /**
283
+ * Trace a chain/workflow
284
+ *
285
+ * @example
286
+ * ```typescript
287
+ * const result = await traceChain({
288
+ * name: 'customer_support_chain',
289
+ * }, async () => {
290
+ * // Multiple LLM calls, tools, etc.
291
+ * });
292
+ * ```
293
+ */
294
+ function traceChain(options, fn) {
295
+ const t = getTracer();
296
+ return t.startActiveSpan(options.name, {
297
+ attributes: {
298
+ "openinference.span.kind": "CHAIN",
299
+ "input.value": options.input ? JSON.stringify(options.input).substring(0, 10000) : undefined,
300
+ },
301
+ }, async (span) => {
302
+ const startTime = Date.now();
303
+ try {
304
+ const result = await fn();
305
+ span.setAttribute("output.value", JSON.stringify(result).substring(0, 10000));
306
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
307
+ return result;
308
+ }
309
+ catch (error) {
310
+ const message = error instanceof Error ? error.message : String(error);
311
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message });
312
+ span.recordException(error);
313
+ throw error;
314
+ }
315
+ finally {
316
+ span.setAttribute("duration_ms", Date.now() - startTime);
317
+ span.end();
318
+ }
319
+ });
320
+ }
321
+ // ============================================================================
322
+ // EXPLAINER CLIENT
323
+ // ============================================================================
324
+ /**
325
+ * Explainer API client for trace analysis
326
+ */
327
+ exports.explainer = {
328
+ /**
329
+ * Analyze a trace and get explainability insights
330
+ *
331
+ * @example
332
+ * ```typescript
333
+ * const result = await explainer.analyze({
334
+ * userMessage: 'Help me with my order #12345',
335
+ * agentResponse: 'I found your order...',
336
+ * outcome: 'success',
337
+ * spans: [
338
+ * { name: 'order_lookup', type: 'tool', durationMs: 150 },
339
+ * { name: 'gpt-4', type: 'llm', durationMs: 2500, model: 'gpt-4' },
340
+ * ],
341
+ * });
342
+ * ```
343
+ */
344
+ async analyze(trace, options = {}) {
345
+ if (!initialized) {
346
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
347
+ }
348
+ const payload = {
349
+ trace: {
350
+ userMessage: trace.userMessage,
351
+ agentResponse: trace.agentResponse,
352
+ userIntent: trace.userIntent,
353
+ outcome: trace.outcome || 'success',
354
+ duration: trace.duration,
355
+ sessionId: trace.sessionId,
356
+ conversationHistory: trace.conversationHistory,
357
+ metadata: trace.metadata,
358
+ },
359
+ spans: trace.spans,
360
+ businessContext: trace.businessContext,
361
+ options: {
362
+ tier: options.tier,
363
+ includeRagEvaluation: options.includeRagEvaluation ?? true,
364
+ includeHallucinationCheck: options.includeHallucinationCheck ?? true,
365
+ },
366
+ };
367
+ if (options.waitForResult === false && options.webhookUrl) {
368
+ // Async analysis with webhook
369
+ return apiRequest('/explainer/analyze-async', {
370
+ method: 'POST',
371
+ body: { ...payload, webhookUrl: options.webhookUrl },
372
+ });
373
+ }
374
+ return apiRequest('/explainer/analyze', {
375
+ method: 'POST',
376
+ body: payload,
377
+ });
378
+ },
379
+ /**
380
+ * Batch analyze multiple traces
381
+ *
382
+ * @example
383
+ * ```typescript
384
+ * const results = await explainer.analyzeBatch([
385
+ * { userMessage: 'Q1', agentResponse: 'A1' },
386
+ * { userMessage: 'Q2', agentResponse: 'A2' },
387
+ * ]);
388
+ * ```
389
+ */
390
+ async analyzeBatch(traces, options = {}) {
391
+ if (!initialized) {
392
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
393
+ }
394
+ return apiRequest('/explainer/analyze-batch', {
395
+ method: 'POST',
396
+ body: {
397
+ traces: traces.map(t => ({
398
+ userMessage: t.userMessage,
399
+ agentResponse: t.agentResponse,
400
+ userIntent: t.userIntent,
401
+ outcome: t.outcome || 'success',
402
+ spans: t.spans,
403
+ businessContext: t.businessContext,
404
+ metadata: t.metadata,
405
+ })),
406
+ options,
407
+ },
408
+ });
409
+ },
410
+ /**
411
+ * Get a previously analyzed trace
412
+ */
413
+ async get(traceId) {
414
+ if (!initialized) {
415
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
416
+ }
417
+ return apiRequest(`/explainer/${traceId}`);
418
+ },
419
+ /**
420
+ * Search traces semantically
421
+ *
422
+ * @example
423
+ * ```typescript
424
+ * const results = await explainer.search({
425
+ * query: 'order refund issues',
426
+ * filters: { outcome: 'failure' },
427
+ * limit: 10,
428
+ * });
429
+ * ```
430
+ */
431
+ async search(params) {
432
+ if (!initialized) {
433
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
434
+ }
435
+ return apiRequest('/explainer/search', {
436
+ method: 'POST',
437
+ body: params,
438
+ });
439
+ },
440
+ };
441
+ // ============================================================================
442
+ // FEEDBACK CLIENT
443
+ // ============================================================================
444
+ /**
445
+ * Feedback API for improving analysis quality
446
+ */
447
+ exports.feedback = {
448
+ /**
449
+ * Submit feedback for a trace
450
+ *
451
+ * @example
452
+ * ```typescript
453
+ * await feedback.submit({
454
+ * traceId: 'trace_123',
455
+ * rating: 5,
456
+ * wasHelpful: true,
457
+ * });
458
+ * ```
459
+ */
460
+ async submit(options) {
461
+ if (!initialized) {
462
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
463
+ }
464
+ return apiRequest('/feedback', {
465
+ method: 'POST',
466
+ body: options,
467
+ });
468
+ },
469
+ };
470
+ // ============================================================================
471
+ // QUALITY METRICS CLIENT
472
+ // ============================================================================
473
+ /**
474
+ * Quality metrics API for RAG evaluation and hallucination detection
475
+ */
476
+ exports.quality = {
477
+ /**
478
+ * Get RAG evaluation scores for a trace
479
+ */
480
+ async getRagScores(traceId) {
481
+ if (!initialized) {
482
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
483
+ }
484
+ return apiRequest(`/quality/rag-scores/${traceId}`);
485
+ },
486
+ /**
487
+ * Get hallucination report for a trace
488
+ */
489
+ async getHallucinationReport(traceId) {
490
+ if (!initialized) {
491
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
492
+ }
493
+ return apiRequest(`/quality/hallucination-report/${traceId}`);
494
+ },
495
+ /**
496
+ * Evaluate RAG quality for custom input
497
+ */
498
+ async evaluateRag(input) {
499
+ if (!initialized) {
500
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
501
+ }
502
+ return apiRequest('/quality/evaluate-rag', {
503
+ method: 'POST',
504
+ body: input,
505
+ });
506
+ },
507
+ };
508
+ // ============================================================================
509
+ // ROI ANALYTICS CLIENT
510
+ // ============================================================================
511
+ /**
512
+ * ROI analytics API for business impact tracking
513
+ */
514
+ exports.analytics = {
515
+ /**
516
+ * Get ROI summary for the account
517
+ */
518
+ async getRoiSummary() {
519
+ if (!initialized) {
520
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
521
+ }
522
+ return apiRequest('/analytics/roi/summary');
523
+ },
524
+ /**
525
+ * Get ROI by agent
526
+ */
527
+ async getRoiByAgent(agentId) {
528
+ if (!initialized) {
529
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
530
+ }
531
+ return apiRequest(`/analytics/roi/by-agent/${agentId}`);
532
+ },
533
+ /**
534
+ * Get correlation analysis
535
+ */
536
+ async getCorrelations() {
537
+ if (!initialized) {
538
+ throw new Error("ThinkHive SDK not initialized. Call init() first.");
539
+ }
540
+ return apiRequest('/analytics/correlations');
541
+ },
542
+ };
543
+ // ============================================================================
544
+ // AUTO-INSTRUMENTATION
545
+ // ============================================================================
546
+ /**
547
+ * Setup auto-instrumentation for AI frameworks
548
+ */
549
+ function setupAutoInstrumentation(frameworks) {
550
+ if (config.debug) {
551
+ console.log(`Setting up auto-instrumentation for: ${frameworks.join(', ')}`);
552
+ }
553
+ // Note: Full auto-instrumentation requires framework-specific patches
554
+ // This is a placeholder for the instrumentation setup
555
+ // In production, use @opentelemetry/instrumentation-* packages
556
+ for (const framework of frameworks) {
557
+ try {
558
+ switch (framework) {
559
+ case 'openai':
560
+ instrumentOpenAI();
561
+ break;
562
+ case 'langchain':
563
+ instrumentLangChain();
564
+ break;
565
+ case 'anthropic':
566
+ instrumentAnthropic();
567
+ break;
568
+ case 'llamaindex':
569
+ instrumentLlamaIndex();
570
+ break;
571
+ }
572
+ }
573
+ catch (error) {
574
+ if (config.debug) {
575
+ console.warn(`Failed to instrument ${framework}:`, error);
576
+ }
577
+ }
578
+ }
579
+ }
580
+ function instrumentOpenAI() {
581
+ // Placeholder - would patch OpenAI client
582
+ if (config.debug) {
583
+ console.log('OpenAI instrumentation ready');
584
+ }
585
+ }
586
+ function instrumentLangChain() {
587
+ // Placeholder - would use LangChain callbacks
588
+ if (config.debug) {
589
+ console.log('LangChain instrumentation ready');
590
+ }
591
+ }
592
+ function instrumentAnthropic() {
593
+ // Placeholder - would patch Anthropic client
594
+ if (config.debug) {
595
+ console.log('Anthropic instrumentation ready');
596
+ }
597
+ }
598
+ function instrumentLlamaIndex() {
599
+ // Placeholder - would use LlamaIndex callbacks
600
+ if (config.debug) {
601
+ console.log('LlamaIndex instrumentation ready');
602
+ }
603
+ }
604
+ // ============================================================================
605
+ // CONVENIENCE FUNCTIONS
606
+ // ============================================================================
607
+ /**
608
+ * Create a trace and analyze it in one call
609
+ *
610
+ * @example
611
+ * ```typescript
612
+ * const { trace, analysis } = await createAndAnalyze({
613
+ * userMessage: 'Help me track my order',
614
+ * agentResponse: 'Your order is on the way...',
615
+ * });
616
+ * ```
617
+ */
618
+ async function createAndAnalyze(traceData, options = {}) {
619
+ const analysis = await exports.explainer.analyze(traceData, options);
620
+ return { trace: traceData, analysis };
621
+ }
622
+ // ============================================================================
623
+ // EXPORTS
624
+ // ============================================================================
625
+ exports.default = {
626
+ init,
627
+ getTracer,
628
+ isInitialized,
629
+ traceLLM,
630
+ traceRetrieval,
631
+ traceTool,
632
+ traceChain,
633
+ explainer: exports.explainer,
634
+ feedback: exports.feedback,
635
+ quality: exports.quality,
636
+ analytics: exports.analytics,
637
+ createAndAnalyze,
638
+ };
639
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7OztHQUtHOzs7QUFnT0gsb0JBdUVDO0FBS0QsOEJBS0M7QUFLRCxzQ0FFQztBQW9CRCw0QkF1Q0M7QUFlRCx3Q0EwQ0M7QUFnQkQsOEJBcUNDO0FBY0QsZ0NBbUNDO0FBOFpELDRDQVNDO0FBdjdCRCw0Q0FBc0Y7QUFDdEYsd0ZBQTZFO0FBQzdFLHdEQUFvRDtBQUNwRCxrRUFBbUU7QUFDbkUsa0VBQW1FO0FBb0puRSwrRUFBK0U7QUFDL0UsZUFBZTtBQUNmLCtFQUErRTtBQUUvRSxJQUFJLE1BQU0sR0FBOEMsSUFBSSxDQUFDO0FBQzdELElBQUksV0FBVyxHQUFHLEtBQUssQ0FBQztBQUN4QixJQUFJLE1BQTZCLENBQUM7QUFFbEMsTUFBTSxnQkFBZ0IsR0FBRywrQ0FBK0MsQ0FBQztBQUV6RSwrRUFBK0U7QUFDL0UsY0FBYztBQUNkLCtFQUErRTtBQUUvRSxLQUFLLFVBQVUsVUFBVSxDQUN2QixJQUFZLEVBQ1osVUFJSSxFQUFFO0lBRU4sTUFBTSxFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQUUsSUFBSSxFQUFFLE9BQU8sR0FBRyxFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUM7SUFFdkQsTUFBTSxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUMsUUFBUSxVQUFVLElBQUksRUFBRSxDQUFDO0lBRS9DLE1BQU0sY0FBYyxHQUEyQjtRQUM3QyxjQUFjLEVBQUUsa0JBQWtCO1FBQ2xDLEdBQUcsT0FBTztLQUNYLENBQUM7SUFFRixJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNsQixjQUFjLENBQUMsZUFBZSxDQUFDLEdBQUcsVUFBVSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDOUQsQ0FBQztTQUFNLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzFCLGNBQWMsQ0FBQyxZQUFZLENBQUMs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LE9BQU8sRUFBUCxlQUFPO0lBQ1AsU0FBUyxFQUFULGlCQUFTO0lBQ1QsZ0JBQWdCO0NBQ2pCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFRoaW5rSGl2ZSBUeXBlU2NyaXB0IFNES1xuICogT3BlblRlbGVtZXRyeS1iYXNlZCBvYnNlcnZhYmlsaXR5IGZvciBBSSBhZ2VudHMgd2l0aCBFeHBsYWluZXIgaW50ZWdyYXRpb25cbiAqXG4gKiBAdmVyc2lvbiAyLjAuMFxuICovXG5cbmltcG9ydCB7IHRyYWNlLCBjb250ZXh0LCBTcGFuU3RhdHVzQ29kZSwgU3BhbiBhcyBPVGVsU3BhbiB9IGZyb20gXCJAb3BlbnRlbGVtZXRyeS9hcGlcIjtcbmltcG9ydCB7IE9UTFBUcmFjZUV4cG9ydGVyIH0gZnJvbSBcIkBvcGVudGVsZW1ldHJ5L2V4cG9ydGVyLXRyYWNlLW90bHAtcHJvdG9cIjtcbmltcG9ydCB7IFJlc291cmNlIH0gZnJvbSBcIkBvcGVudGVsZW1ldHJ5L3Jlc291cmNlc1wiO1xuaW1wb3J0IHsgTm9kZVRyYWNlclByb3ZpZGVyIH0gZnJvbSBcIkBvcGVudGVsZW1ldHJ5L3Nkay10cmFjZS1ub2RlXCI7XG5pbXBvcnQgeyBCYXRjaFNwYW5Qcm9jZXNzb3IgfSBmcm9tIFwiQG9wZW50ZWxlbWV0cnkvc2RrLXRyYWNlLWJhc2VcIjtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFlQRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBJbml0T3B0aW9ucyB7XG4gIC8qKiBUaGlua0hpdmUgQVBJIGtleSAoc3RhcnRzIHdpdGggdGhfKSAqL1xuICBhcGlLZXk/OiBzdHJpbmc7XG4gIC8qKiBBZ2VudCBJRCBmb3IgbGVnYWN5IGF1dGhlbnRpY2F0aW9uICovXG4gIGFnZW50SWQ/OiBzdHJpbmc7XG4gIC8qKiBUaGlua0hpdmUgQVBJIGVuZHBvaW50ICovXG4gIGVuZHBvaW50Pzogc3RyaW5nO1xuICAvKiogU2VydmljZSBuYW1lIGZvciB0cmFjZXMgKi9cbiAgc2VydmljZU5hbWU/OiBzdHJpbmc7XG4gIC8qKiBFbmFibGUgYXV0by1pbnN0cnVtZW50YXRpb24gKi9cbiAgYXV0b0luc3RydW1lbnQ/OiBib29sZWFuO1xuICAvKiogRnJhbWV3b3JrcyB0byBhdXRvLWluc3RydW1lbnQgKi9cbiAgZnJhbWV3b3Jrcz86IEFycmF5PCdsYW5nY2hhaW4nIHwgJ29wZW5haScgfCAnYW50aHJvcGljJyB8ICdsbGFtYWluZGV4Jz47XG4gIC8qKiBFbmFibGUgZGVidWcgbG9nZ2luZyAqL1xuICBkZWJ1Zz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhY2VPcHRpb25zIHtcbiAgLyoqIFVzZXIncyBtZXNzYWdlL3F1ZXJ5ICovXG4gIHVzZXJNZXNzYWdlOiBzdHJpbmc7XG4gIC8qKiBBZ2VudCdzIHJlc3BvbnNlICovXG4gIGFnZW50UmVzcG9uc2U6IHN0cmluZztcbiAgLyoqIFVzZXIncyBkZXRlY3RlZCBpbnRlbnQgKi9cbiAgdXNlckludGVudD86IHN0cmluZztcbiAgLyoqIE91dGNvbWU6IHN1Y2Nlc3MsIGZhaWx1cmUsIHBhcnRpYWxfc3VjY2VzcyAqL1xuICBvdXRjb21lPzogJ3N1Y2Nlc3MnIHwgJ2ZhaWx1cmUnIHwgJ3BhcnRpYWxfc3VjY2Vzcyc7XG4gIC8qKiBEdXJhdGlvbiBpbiBtaWxsaXNlY29uZHMgKi9cbiAgZHVyYXRpb24/OiBudW1iZXI7XG4gIC8qKiBTZXNzaW9uIElEIGZvciBjb252ZXJzYXRpb24gdHJhY2tpbmcgKi9cbiAgc2Vzc2lvbklkPzogc3RyaW5nO1xuICAvKiogQ29udmVyc2F0aW9uIGhpc3RvcnkgKi9cbiAgY29udmVyc2F0aW9uSGlzdG9yeT86IEFycmF5PHsgcm9sZTogc3RyaW5nOyBjb250ZW50OiBzdHJpbmcgfT47XG4gIC8qKiBTcGFuIGRhdGEgZm9yIGRldGFpbGVkIGFuYWx5c2lzICovXG4gIHNwYW5zPzogU3BhbkRhdGFbXTtcbiAgLyoqIEJ1c2luZXNzIGNvbnRleHQgZm9yIFJPSSBjYWxjdWxhdGlvbiAqL1xuICBidXNpbmVzc0NvbnRleHQ/OiBCdXNpbmVzc0NvbnRleHQ7XG4gIC8qKiBDdXN0b20gbWV0YWRhdGEgKi9cbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTcGFuRGF0YSB7XG4gIGlkPzogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIHR5cGU6ICdsbG0nIHwgJ3Rvb2wnIHwgJ3JldHJpZXZhbCcgfCAnZW1iZWRkaW5nJyB8ICdjaGFpbicgfCAnY3VzdG9tJztcbiAgc3RhcnRUaW1lPzogRGF0ZTtcbiAgZW5kVGltZT86IERhdGU7XG4gIGR1cmF0aW9uTXM/OiBudW1iZXI7XG4gIHN0YXR1cz86ICdvaycgfCAnZXJyb3InIHwgJ3RpbWVvdXQnO1xuICBlcnJvcj86IHN0cmluZztcbiAgaW5wdXQ/OiB1bmtub3duO1xuICBvdXRwdXQ/OiB1bmtub3duO1xuICAvLyBMTE0tc3BlY2lmaWNcbiAgbW9kZWw/OiBzdHJpbmc7XG4gIHByb3ZpZGVyPzogc3RyaW5nO1xuICBwcm9tcHRUb2tlbnM/OiBudW1iZXI7XG4gIGNvbXBsZXRpb25Ub2tlbnM/OiBudW1iZXI7XG4gIC8vIFRvb2wtc3BlY2lmaWNcbiAgdG9vbE5hbWU/OiBzdHJpbmc7XG4gIHRvb2xQYXJhbWV0ZXJzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIC8vIFJldHJpZXZhbC1zcGVjaWZpY1xuICBxdWVyeT86IHN0cmluZztcbiAgZG9jdW1lbnRDb3VudD86IG51bWJlcjtcbiAgdG9wU2NvcmU/OiBudW1iZXI7XG4gIHNvdXJjZXM/OiBzdHJpbmdbXTtcbiAgLy8gQ2hpbGRyZW5cbiAgY2hpbGRyZW4/OiBTcGFuRGF0YVtdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1c2luZXNzQ29udGV4dCB7XG4gIC8qKiBDdXN0b21lciBJRCAqL1xuICBjdXN0b21lcklkPzogc3RyaW5nO1xuICAvKiogVHJhbnNhY3Rpb24gdmFsdWUgaW4gZG9sbGFycyAqL1xuICB0cmFuc2FjdGlvblZhbHVlPzogbnVtYmVyO1xuICAvKiogUHJpb3JpdHkgbGV2ZWwgKi9cbiAgcHJpb3JpdHk/OiAnbG93JyB8ICdtZWRpdW0nIHwgJ2hpZ2gnIHwgJ2NyaXRpY2FsJztcbiAgLyoqIERlcGFydG1lbnQgKi9cbiAgZGVwYXJ0bWVudD86IHN0cmluZztcbiAgLyoqIEluZHVzdHJ5IHZlcnRpY2FsICovXG4gIGluZHVzdHJ5Pzogc3RyaW5nO1xuICAvKiogQ3VzdG9tIGZpZWxkcyAqL1xuICBjdXN0b20/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFeHBsYWluYWJpbGl0eVJlc3VsdCB7XG4gIHRyYWNlSWQ6IHN0cmluZztcbiAgZXhwbGFpbmFiaWxpdHlJZDogc3RyaW5nO1xuICBzdW1tYXJ5OiBzdHJpbmc7XG4gIG91dGNvbWU6IHtcbiAgICB2ZXJkaWN0OiAnc3VjY2VzcycgfCAncGFydGlhbF9zdWNjZXNzJyB8ICdmYWlsdXJlJztcbiAgICBjb25maWRlbmNlOiBudW1iZXI7XG4gICAgcmVhc29uaW5nOiBzdHJpbmc7XG4gIH07XG4gIGJ1c2luZXNzSW1wYWN0OiB7XG4gICAgaW1wYWN0U2NvcmU6IG51bWJlcjtcbiAgICBjdXN0b21lclNhdGlzZmFjdGlvbjogbnVtYmVyO1xuICAgIHJldmVudWVSaXNrOiBzdHJpbmc7XG4gIH07XG4gIHJlY29tbWVuZGF0aW9uczogQXJyYXk8e1xuICAgIHByaW9yaXR5OiBzdHJpbmc7XG4gICAgY2F0ZWdvcnk6IHN0cmluZztcbiAgICBhY3Rpb246IHN0cmluZztcbiAgICBleHBlY3RlZEltcGFjdDogc3RyaW5nO1xuICB9PjtcbiAgcmFnRXZhbHVhdGlvbj86IHtcbiAgICBncm91bmRlZG5lc3M6IG51bWJlcjtcbiAgICBmYWl0aGZ1bG5lc3M6IG51bWJlcjtcbiAgICBhbnN3ZXJSZWxldmFuY2U6IG51bWJlcjtcbiAgfTtcbiAgaGFsbHVjaW5hdGlvblJlcG9ydD86IHtcbiAgICBkZXRlY3RlZDogYm9vbGVhbjtcbiAgICB0eXBlczogc3RyaW5nW107XG4gICAgc2V2ZXJpdHk6IHN0cmluZztcbiAgfTtcbiAgcHJvY2Vzc2luZ1RpbWVNczogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFuYWx5emVPcHRpb25zIHtcbiAgLyoqIEZvcmNlIGEgc3BlY2lmaWMgYW5hbHlzaXMgdGllciAqL1xuICB0aWVyPzogJ3J1bGVfYmFzZWQnIHwgJ2Zhc3RfbGxtJyB8ICdmdWxsX2xsbScgfCAnZGVlcCc7XG4gIC8qKiBJbmNsdWRlIFJBRyBldmFsdWF0aW9uICovXG4gIGluY2x1ZGVSYWdFdmFsdWF0aW9uPzogYm9vbGVhbjtcbiAgLyoqIEluY2x1ZGUgaGFsbHVjaW5hdGlvbiBkZXRlY3Rpb24gKi9cbiAgaW5jbHVkZUhhbGx1Y2luYXRpb25DaGVjaz86IGJvb2xlYW47XG4gIC8qKiBXYWl0IGZvciBhbmFseXNpcyB0byBjb21wbGV0ZSAoc3luYyBtb2RlKSAqL1xuICB3YWl0Rm9yUmVzdWx0PzogYm9vbGVhbjtcbiAgLyoqIFdlYmhvb2sgVVJMIGZvciBhc3luYyBub3RpZmljYXRpb24gKi9cbiAgd2ViaG9va1VybD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGZWVkYmFja09wdGlvbnMge1xuICAvKiogVHJhY2UgSUQgdG8gcHJvdmlkZSBmZWVkYmFjayBmb3IgKi9cbiAgdHJhY2VJZDogc3RyaW5nO1xuICAvKiogVXNlciByYXRpbmcgKDEtNSkgKi9cbiAgcmF0aW5nPzogbnVtYmVyO1xuICAvKiogV2FzIHRoZSByZXNwb25zZSBoZWxwZnVsICovXG4gIHdhc0hlbHBmdWw/OiBib29sZWFuO1xuICAvKiogU3BlY2lmaWMgaXNzdWVzIGVuY291bnRlcmVkICovXG4gIGlzc3Vlcz86IEFycmF5PCdzbG93X3Jlc3BvbnNlJyB8ICdpbmNvcnJlY3QnIHwgJ3VuaGVscGZ1bCcgfCAnaGFsbHVjaW5hdGlvbicgfCAnb2ZmX3RvcGljJyB8ICdvdGhlcic+O1xuICAvKiogRnJlZS1mb3JtIGNvbW1lbnQgKi9cbiAgY29tbWVudD86IHN0cmluZztcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gR0xPQkFMIFNUQVRFXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmxldCB0cmFjZXI6IFJldHVyblR5cGU8dHlwZW9mIHRyYWNlLmdldFRyYWNlcj4gfCBudWxsID0gbnVsbDtcbmxldCBpbml0aWFsaXplZCA9IGZhbHNlO1xubGV0IGNvbmZpZzogUmVxdWlyZWQ8SW5pdE9wdGlvbnM+O1xuXG5jb25zdCBERUZBVUxUX0VORFBPSU5UID0gXCJodHRwczovL3RoaW5raGl2ZW1pbmQtaDI1ejdwdmQzcS11Yy5hLnJ1bi5hcHBcIjtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSFRUUCBDTElFTlRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuYXN5bmMgZnVuY3Rpb24gYXBpUmVxdWVzdDxUPihcbiAgcGF0aDogc3RyaW5nLFxuICBvcHRpb25zOiB7XG4gICAgbWV0aG9kPzogJ0dFVCcgfCAnUE9TVCcgfCAnUFVUJyB8ICdERUxFVEUnO1xuICAgIGJvZHk/OiB1bmtub3duO1xuICAgIGhlYWRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICB9ID0ge31cbik6IFByb21pc2U8VD4ge1xuICBjb25zdCB7IG1ldGhvZCA9ICdHRVQnLCBib2R5LCBoZWFkZXJzID0ge30gfSA9IG9wdGlvbnM7XG5cbiAgY29uc3QgdXJsID0gYCR7Y29uZmlnLmVuZHBvaW50fS9hcGkvdjEke3BhdGh9YDtcblxuICBjb25zdCByZXF1ZXN0SGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgIC4uLmhlYWRlcnMsXG4gIH07XG5cbiAgaWYgKGNvbmZpZy5hcGlLZXkpIHtcbiAgICByZXF1ZXN0SGVhZGVyc1snQXV0aG9yaXphdGlvbiddID0gYEJlYXJlciAke2NvbmZpZy5hcGlLZXl9YDtcbiAgfSBlbHNlIGlmIChjb25maWcuYWdlbnRJZCkge1xuICAgIHJlcXVlc3RIZWFkZXJzWydYLUFnZW50LUlEJ10gPSBjb25maWcuYWdlbnRJZDtcbiAgfVxuXG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgbWV0aG9kLFxuICAgIGhlYWRlcnM6IHJlcXVlc3RIZWFkZXJzLFxuICAgIGJvZHk6IGJvZHkgPyBKU09OLnN0cmluZ2lmeShib2R5KSA6IHVuZGVmaW5lZCxcbiAgfSk7XG5cbiAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgIGNvbnN0IGVycm9yID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhpbmtIaXZlIEFQSSBlcnJvcjogJHtyZXNwb25zZS5zdGF0dXN9IC0gJHtlcnJvcn1gKTtcbiAgfVxuXG4gIHJldHVybiByZXNwb25zZS5qc29uKCkgYXMgUHJvbWlzZTxUPjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSU5JVElBTElaQVRJT05cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBJbml0aWFsaXplIFRoaW5rSGl2ZSBTREtcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgaW5pdCB9IGZyb20gJ0B0aGlua2hpdmUvc2RrJztcbiAqXG4gKiBpbml0KHtcbiAqICAgYXBpS2V5OiAndGhfeW91cl9hcGlfa2V5JyxcbiAqICAgc2VydmljZU5hbWU6ICdteS1haS1hZ2VudCcsXG4gKiAgIGF1dG9JbnN0cnVtZW50OiB0cnVlLFxuICogICBmcmFtZXdvcmtzOiBbJ2xhbmdjaGFpbicsICdvcGVuYWknXSxcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbml0KG9wdGlvbnM6IEluaXRPcHRpb25zID0ge30pOiB2b2lkIHtcbiAgaWYgKGluaXRpYWxpemVkKSB7XG4gICAgaWYgKG9wdGlvbnMuZGVidWcpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdUaGlua0hpdmUgU0RLIGFscmVhZHkgaW5pdGlhbGl6ZWQnKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgYXBpS2V5ID0gb3B0aW9ucy5hcGlLZXkgfHwgcHJvY2Vzcy5lbnYuVEhJTktISVZFX0FQSV9LRVk7XG4gIGNvbnN0IGFnZW50SWQgPSBvcHRpb25zLmFnZW50SWQgfHwgcHJvY2Vzcy5lbnYuVEhJTktISVZFX0FHRU5UX0lEO1xuXG4gIGlmICghYXBpS2V5ICYmICFhZ2VudElkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiRWl0aGVyIGFwaUtleSBvciBhZ2VudElkIG11c3QgYmUgcHJvdmlkZWQgKG9yIHNldCBUSElOS0hJVkVfQVBJX0tFWSBlbnYgdmFyKVwiKTtcbiAgfVxuXG4gIGNvbmZpZyA9IHtcbiAgICBhcGlLZXk6IGFwaUtleSB8fCAnJyxcbiAgICBhZ2VudElkOiBhZ2VudElkIHx8ICcnLFxuICAgIGVuZHBvaW50OiBvcHRpb25zLmVuZHBvaW50IHx8IHByb2Nlc3MuZW52LlRISU5LSElWRV9FTkRQT0lOVCB8fCBERUZBVUxUX0VORFBPSU5ULFxuICAgIHNlcnZpY2VOYW1lOiBvcHRpb25zLnNlcnZpY2VOYW1lIHx8IHByb2Nlc3MuZW52LlRISU5LSElWRV9TRVJWSUNFX05BTUUgfHwgJ215LWFpLWFnZW50JyxcbiAgICBhdXRvSW5zdHJ1bWVudDogb3B0aW9ucy5hdXRvSW5zdHJ1bWVudCA/PyBmYWxzZSxcbiAgICBmcmFtZXdvcmtzOiBvcHRpb25zLmZyYW1ld29ya3MgfHwgWydsYW5nY2hhaW4nLCAnb3BlbmFpJ10sXG4gICAgZGVidWc6IG9wdGlvbnMuZGVidWcgPz8gZmFsc2UsXG4gIH07XG5cbiAgLy8gQ29uZmlndXJlIE9UTFAgZXhwb3J0ZXJcbiAgY29uc3QgZXhwb3J0ZXJIZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIGlmIChjb25maWcuYXBpS2V5KSB7XG4gICAgZXhwb3J0ZXJIZWFkZXJzW1wiQXV0aG9yaXphdGlvblwiXSA9IGBCZWFyZXIgJHtjb25maWcuYXBpS2V5fWA7XG4gIH0gZWxzZSBpZiAoY29uZmlnLmFnZW50SWQpIHtcbiAgICBleHBvcnRlckhlYWRlcnNbXCJYLUFnZW50LUlEXCJdID0gY29uZmlnLmFnZW50SWQ7XG4gIH1cblxuICBjb25zdCBleHBvcnRlciA9IG5ldyBPVExQVHJhY2VFeHBvcnRlcih7XG4gICAgdXJsOiBgJHtjb25maWcuZW5kcG9pbnR9L3YxL3RyYWNlc2AsXG4gICAgaGVhZGVyczogZXhwb3J0ZXJIZWFkZXJzLFxuICB9KTtcblxuICAvLyBDcmVhdGUgT3BlblRlbGVtZXRyeSByZXNvdXJjZVxuICBjb25zdCByZXNvdXJjZSA9IFJlc291cmNlLmRlZmF1bHQoKS5tZXJnZShcbiAgICBuZXcgUmVzb3VyY2Uoe1xuICAgICAgXCJzZXJ2aWNlLm5hbWVcIjogY29uZmlnLnNlcnZpY2VOYW1lLFxuICAgICAgXCJ0aGlua2hpdmUuc2RrLnZlcnNpb25cIjogXCIyLjAuMFwiLFxuICAgICAgXCJ0aGlua2hpdmUuc2RrLmxhbmd1YWdlXCI6IFwidHlwZXNjcmlwdFwiLFxuICAgIH0pXG4gICk7XG5cbiAgLy8gQ3JlYXRlIHByb3ZpZGVyIHdpdGggc3BhbiBwcm9jZXNzb3JcbiAgY29uc3QgcHJvdmlkZXIgPSBuZXcgTm9kZVRyYWNlclByb3ZpZGVyKHtcbiAgICByZXNvdXJjZSxcbiAgICBzcGFuUHJvY2Vzc29yczogW25ldyBCYXRjaFNwYW5Qcm9jZXNzb3IoZXhwb3J0ZXIpXSxcbiAgfSk7XG5cbiAgLy8gUmVnaXN0ZXIgcHJvdmlkZXJcbiAgcHJvdmlkZXIucmVnaXN0ZXIoKTtcblxuICAvLyBHZXQgdHJhY2VyXG4gIHRyYWNlciA9IHRyYWNlLmdldFRyYWNlcihcInRoaW5raGl2ZVwiLCBcIjIuMC4wXCIpO1xuICBpbml0aWFsaXplZCA9IHRydWU7XG5cbiAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKGDinIUgVGhpbmtIaXZlIFNESyBpbml0aWFsaXplZGApO1xuICAgIGNvbnNvbGUubG9nKGAgICBFbmRwb2ludDogJHtjb25maWcuZW5kcG9pbnR9YCk7XG4gICAgY29uc29sZS5sb2coYCAgIFNlcnZpY2U6ICR7Y29uZmlnLnNlcnZpY2VOYW1lfWApO1xuICAgIGNvbnNvbGUubG9nKGAgICBBdXRvLWluc3RydW1lbnQ6ICR7Y29uZmlnLmF1dG9JbnN0cnVtZW50fWApO1xuICB9XG5cbiAgLy8gU2V0dXAgYXV0by1pbnN0cnVtZW50YXRpb24gaWYgZW5hYmxlZFxuICBpZiAoY29uZmlnLmF1dG9JbnN0cnVtZW50KSB7XG4gICAgc2V0dXBBdXRvSW5zdHJ1bWVudGF0aW9uKGNvbmZpZy5mcmFtZXdvcmtzKTtcbiAgfVxufVxuXG4vKipcbiAqIEdldCB0aGUgZ2xvYmFsIHRyYWNlclxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VHJhY2VyKCkge1xuICBpZiAoIWluaXRpYWxpemVkIHx8ICF0cmFjZXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlua0hpdmUgU0RLIG5vdCBpbml0aWFsaXplZC4gQ2FsbCBpbml0KCkgZmlyc3QuXCIpO1xuICB9XG4gIHJldHVybiB0cmFjZXI7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgU0RLIGlzIGluaXRpYWxpemVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0luaXRpYWxpemVkKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gaW5pdGlhbGl6ZWQ7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFRSQUNJTkcgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogVHJhY2UgYW4gTExNIGNhbGxcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0cmFjZUxMTSh7XG4gKiAgIG5hbWU6ICdjaGF0X2NvbXBsZXRpb24nLFxuICogICBtb2RlbE5hbWU6ICdncHQtNCcsXG4gKiAgIHByb3ZpZGVyOiAnb3BlbmFpJyxcbiAqIH0sIGFzeW5jICgpID0+IHtcbiAqICAgcmV0dXJuIGF3YWl0IG9wZW5haS5jaGF0LmNvbXBsZXRpb25zLmNyZWF0ZSh7IC4uLiB9KTtcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFjZUxMTTxUPihcbiAgb3B0aW9uczoge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBtb2RlbE5hbWU/OiBzdHJpbmc7XG4gICAgcHJvdmlkZXI/OiBzdHJpbmc7XG4gICAgaW5wdXQ/OiB1bmtub3duO1xuICB9LFxuICBmbjogKCkgPT4gUHJvbWlzZTxUPlxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IHQgPSBnZXRUcmFjZXIoKTtcblxuICByZXR1cm4gdC5zdGFydEFjdGl2ZVNwYW4oXG4gICAgb3B0aW9ucy5uYW1lLFxuICAgIHtcbiAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgXCJvcGVuaW5mZXJlbmNlLnNwYW4ua2luZFwiOiBcIkxMTVwiLFxuICAgICAgICBcImxsbS5tb2RlbF9uYW1lXCI6IG9wdGlvbnMubW9kZWxOYW1lLFxuICAgICAgICBcImxsbS5wcm92aWRlclwiOiBvcHRpb25zLnByb3ZpZGVyLFxuICAgICAgICBcImlucHV0LnZhbHVlXCI6IG9wdGlvbnMuaW5wdXQgPyBKU09OLnN0cmluZ2lmeShvcHRpb25zLmlucHV0KS5zdWJzdHJpbmcoMCwgMTAwMDApIDogdW5kZWZpbmVkLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGFzeW5jIChzcGFuKSA9PiB7XG4gICAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZm4oKTtcbiAgICAgICAgc3Bhbi5zZXRBdHRyaWJ1dGUoXCJvdXRwdXQudmFsdWVcIiwgSlNPTi5zdHJpbmdpZnkocmVzdWx0KS5zdWJzdHJpbmcoMCwgMTAwMDApKTtcbiAgICAgICAgc3Bhbi5zZXRTdGF0dXMoeyBjb2RlOiBTcGFuU3RhdHVzQ29kZS5PSyB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XG4gICAgICAgIHNwYW4uc2V0U3RhdHVzKHsgY29kZTogU3BhblN0YXR1c0NvZGUuRVJST1IsIG1lc3NhZ2UgfSk7XG4gICAgICAgIHNwYW4ucmVjb3JkRXhjZXB0aW9uKGVycm9yIGFzIEVycm9yKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBzcGFuLnNldEF0dHJpYnV0ZShcImR1cmF0aW9uX21zXCIsIERhdGUubm93KCkgLSBzdGFydFRpbWUpO1xuICAgICAgICBzcGFuLmVuZCgpO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn1cblxuLyoqXG4gKiBUcmFjZSBhIHJldHJpZXZhbCBvcGVyYXRpb25cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgZG9jcyA9IGF3YWl0IHRyYWNlUmV0cmlldmFsKHtcbiAqICAgbmFtZTogJ3ZlY3Rvcl9zZWFyY2gnLFxuICogICBxdWVyeTogJ1doYXQgaXMgdGhlIHJldHVybiBwb2xpY3k/JyxcbiAqIH0sIGFzeW5jICgpID0+IHtcbiAqICAgcmV0dXJuIGF3YWl0IHZlY3RvclN0b3JlLnNpbWlsYXJpdHlTZWFyY2gocXVlcnksIDUpO1xuICogfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyYWNlUmV0cmlldmFsPFQ+KFxuICBvcHRpb25zOiB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHF1ZXJ5Pzogc3RyaW5nO1xuICAgIHRvcEs/OiBudW1iZXI7XG4gIH0sXG4gIGZuOiAoKSA9PiBQcm9taXNlPFQ+XG4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgdCA9IGdldFRyYWNlcigpO1xuXG4gIHJldHVybiB0LnN0YXJ0QWN0aXZlU3BhbihcbiAgICBvcHRpb25zLm5hbWUsXG4gICAge1xuICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICBcIm9wZW5pbmZlcmVuY2Uuc3Bhbi5raW5kXCI6IFwiUkVUUklFVkVSXCIsXG4gICAgICAgIFwicmV0cmlldmFsLnF1ZXJ5XCI6IG9wdGlvbnMucXVlcnksXG4gICAgICAgIFwicmV0cmlldmFsLnRvcF9rXCI6IG9wdGlvbnMudG9wSyxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBhc3luYyAoc3BhbikgPT4ge1xuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZuKCk7XG5cbiAgICAgICAgLy8gVHJ5IHRvIGV4dHJhY3QgZG9jdW1lbnQgY291bnQgZnJvbSByZXN1bHRcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgICAgICAgIHNwYW4uc2V0QXR0cmlidXRlKFwicmV0cmlldmFsLmRvY3VtZW50X2NvdW50XCIsIHJlc3VsdC5sZW5ndGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3Bhbi5zZXRTdGF0dXMoeyBjb2RlOiBTcGFuU3RhdHVzQ29kZS5PSyB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XG4gICAgICAgIHNwYW4uc2V0U3RhdHVzKHsgY29kZTogU3BhblN0YXR1c0NvZGUuRVJST1IsIG1lc3NhZ2UgfSk7XG4gICAgICAgIHNwYW4ucmVjb3JkRXhjZXB0aW9uKGVycm9yIGFzIEVycm9yKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBzcGFuLnNldEF0dHJpYnV0ZShcImR1cmF0aW9uX21zXCIsIERhdGUubm93KCkgLSBzdGFydFRpbWUpO1xuICAgICAgICBzcGFuLmVuZCgpO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn1cblxuLyoqXG4gKiBUcmFjZSBhIHRvb2wgY2FsbFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCB0cmFjZVRvb2woe1xuICogICBuYW1lOiAnc2VhcmNoX29yZGVycycsXG4gKiAgIHRvb2xOYW1lOiAnT3JkZXJMb29rdXAnLFxuICogICBwYXJhbWV0ZXJzOiB7IG9yZGVySWQ6ICcxMjM0NScgfSxcbiAqIH0sIGFzeW5jICgpID0+IHtcbiAqICAgcmV0dXJuIGF3YWl0IG9yZGVyU2VydmljZS5sb29rdXAoJzEyMzQ1Jyk7XG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJhY2VUb29sPFQ+KFxuICBvcHRpb25zOiB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHRvb2xOYW1lPzogc3RyaW5nO1xuICAgIHBhcmFtZXRlcnM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgfSxcbiAgZm46ICgpID0+IFByb21pc2U8VD5cbik6IFByb21pc2U8VD4ge1xuICBjb25zdCB0ID0gZ2V0VHJhY2VyKCk7XG5cbiAgcmV0dXJuIHQuc3RhcnRBY3RpdmVTcGFuKFxuICAgIG9wdGlvbnMudG9vbE5hbWUgfHwgb3B0aW9ucy5uYW1lLFxuICAgIHtcbiAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgXCJvcGVuaW5mZXJlbmNlLnNwYW4ua2luZFwiOiBcIlRPT0xcIixcbiAgICAgICAgXCJ0b29sLm5hbWVcIjogb3B0aW9ucy50b29sTmFtZSB8fCBvcHRpb25zLm5hbWUsXG4gICAgICAgIFwidG9vbC5wYXJhbWV0ZXJzXCI6IG9wdGlvbnMucGFyYW1ldGVycyA/IEpTT04uc3RyaW5naWZ5KG9wdGlvbnMucGFyYW1ldGVycykgOiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgIH0sXG4gICAgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBmbigpO1xuICAgICAgICBzcGFuLnNldEF0dHJpYnV0ZShcInRvb2wub3V0cHV0XCIsIEpTT04uc3RyaW5naWZ5KHJlc3VsdCkuc3Vic3RyaW5nKDAsIDEwMDAwKSk7XG4gICAgICAgIHNwYW4uc2V0U3RhdHVzKHsgY29kZTogU3BhblN0YXR1c0NvZGUuT0sgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuICAgICAgICBzcGFuLnNldFN0YXR1cyh7IGNvZGU6IFNwYW5TdGF0dXNDb2RlLkVSUk9SLCBtZXNzYWdlIH0pO1xuICAgICAgICBzcGFuLnJlY29yZEV4Y2VwdGlvbihlcnJvciBhcyBFcnJvcik7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgc3Bhbi5zZXRBdHRyaWJ1dGUoXCJkdXJhdGlvbl9tc1wiLCBEYXRlLm5vdygpIC0gc3RhcnRUaW1lKTtcbiAgICAgICAgc3Bhbi5lbmQoKTtcbiAgICAgIH1cbiAgICB9XG4gICk7XG59XG5cbi8qKlxuICogVHJhY2UgYSBjaGFpbi93b3JrZmxvd1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCByZXN1bHQgPSBhd2FpdCB0cmFjZUNoYWluKHtcbiAqICAgbmFtZTogJ2N1c3RvbWVyX3N1cHBvcnRfY2hhaW4nLFxuICogfSwgYXN5bmMgKCkgPT4ge1xuICogICAvLyBNdWx0aXBsZSBMTE0gY2FsbHMsIHRvb2xzLCBldGMuXG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJhY2VDaGFpbjxUPihcbiAgb3B0aW9uczoge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBpbnB1dD86IHVua25vd247XG4gIH0sXG4gIGZuOiAoKSA9PiBQcm9taXNlPFQ+XG4pOiBQcm9taXNlPFQ+IHtcbiAgY29uc3QgdCA9IGdldFRyYWNlcigpO1xuXG4gIHJldHVybiB0LnN0YXJ0QWN0aXZlU3BhbihcbiAgICBvcHRpb25zLm5hbWUsXG4gICAge1xuICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICBcIm9wZW5pbmZlcmVuY2Uuc3Bhbi5raW5kXCI6IFwiQ0hBSU5cIixcbiAgICAgICAgXCJpbnB1dC52YWx1ZVwiOiBvcHRpb25zLmlucHV0ID8gSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5pbnB1dCkuc3Vic3RyaW5nKDAsIDEwMDAwKSA6IHVuZGVmaW5lZCxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBhc3luYyAoc3BhbikgPT4ge1xuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZuKCk7XG4gICAgICAgIHNwYW4uc2V0QXR0cmlidXRlKFwib3V0cHV0LnZhbHVlXCIsIEpTT04uc3RyaW5naWZ5KHJlc3VsdCkuc3Vic3RyaW5nKDAsIDEwMDAwKSk7XG4gICAgICAgIHNwYW4uc2V0U3RhdHVzKHsgY29kZTogU3BhblN0YXR1c0NvZGUuT0sgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuICAgICAgICBzcGFuLnNldFN0YXR1cyh7IGNvZGU6IFNwYW5TdGF0dXNDb2RlLkVSUk9SLCBtZXNzYWdlIH0pO1xuICAgICAgICBzcGFuLnJlY29yZEV4Y2VwdGlvbihlcnJvciBhcyBFcnJvcik7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgc3Bhbi5zZXRBdHRyaWJ1dGUoXCJkdXJhdGlvbl9tc1wiLCBEYXRlLm5vdygpIC0gc3RhcnRUaW1lKTtcbiAgICAgICAgc3Bhbi5lbmQoKTtcbiAgICAgIH1cbiAgICB9XG4gICk7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEVYUExBSU5FUiBDTElFTlRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBFeHBsYWluZXIgQVBJIGNsaWVudCBmb3IgdHJhY2UgYW5hbHlzaXNcbiAqL1xuZXhwb3J0IGNvbnN0IGV4cGxhaW5lciA9IHtcbiAgLyoqXG4gICAqIEFuYWx5emUgYSB0cmFjZSBhbmQgZ2V0IGV4cGxhaW5hYmlsaXR5IGluc2lnaHRzXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhwbGFpbmVyLmFuYWx5emUoe1xuICAgKiAgIHVzZXJNZXNzYWdlOiAnSGVscCBtZSB3aXRoIG15IG9yZGVyICMxMjM0NScsXG4gICAqICAgYWdlbnRSZXNwb25zZTogJ0kgZm91bmQgeW91ciBvcmRlci4uLicsXG4gICAqICAgb3V0Y29tZTogJ3N1Y2Nlc3MnLFxuICAgKiAgIHNwYW5zOiBbXG4gICAqICAgICB7IG5hbWU6ICdvcmRlcl9sb29rdXAnLCB0eXBlOiAndG9vbCcsIGR1cmF0aW9uTXM6IDE1MCB9LFxuICAgKiAgICAgeyBuYW1lOiAnZ3B0LTQnLCB0eXBlOiAnbGxtJywgZHVyYXRpb25NczogMjUwMCwgbW9kZWw6ICdncHQtNCcgfSxcbiAgICogICBdLFxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBhbmFseXplKFxuICAgIHRyYWNlOiBUcmFjZU9wdGlvbnMsXG4gICAgb3B0aW9uczogQW5hbHl6ZU9wdGlvbnMgPSB7fVxuICApOiBQcm9taXNlPEV4cGxhaW5hYmlsaXR5UmVzdWx0PiB7XG4gICAgaWYgKCFpbml0aWFsaXplZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpbmtIaXZlIFNESyBub3QgaW5pdGlhbGl6ZWQuIENhbGwgaW5pdCgpIGZpcnN0LlwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgdHJhY2U6IHtcbiAgICAgICAgdXNlck1lc3NhZ2U6IHRyYWNlLnVzZXJNZXNzYWdlLFxuICAgICAgICBhZ2VudFJlc3BvbnNlOiB0cmFjZS5hZ2VudFJlc3BvbnNlLFxuICAgICAgICB1c2VySW50ZW50OiB0cmFjZS51c2VySW50ZW50LFxuICAgICAgICBvdXRjb21lOiB0cmFjZS5vdXRjb21lIHx8ICdzdWNjZXNzJyxcbiAgICAgICAgZHVyYXRpb246IHRyYWNlLmR1cmF0aW9uLFxuICAgICAgICBzZXNzaW9uSWQ6IHRyYWNlLnNlc3Npb25JZCxcbiAgICAgICAgY29udmVyc2F0aW9uSGlzdG9yeTogdHJhY2UuY29udmVyc2F0aW9uSGlzdG9yeSxcbiAgICAgICAgbWV0YWRhdGE6IHRyYWNlLm1ldGFkYXRhLFxuICAgICAgfSxcbiAgICAgIHNwYW5zOiB0cmFjZS5zcGFucyxcbiAgICAgIGJ1c2luZXNzQ29udGV4dDogdHJhY2UuYnVzaW5lc3NDb250ZXh0LFxuICAgICAgb3B0aW9uczoge1xuICAgICAgICB0aWVyOiBvcHRpb25zLnRpZXIsXG4gICAgICAgIGluY2x1ZGVSYWdFdmFsdWF0aW9uOiBvcHRpb25zLmluY2x1ZGVSYWdFdmFsdWF0aW9uID8/IHRydWUsXG4gICAgICAgIGluY2x1ZGVIYWxsdWNpbmF0aW9uQ2hlY2s6IG9wdGlvbnMuaW5jbHVkZUhhbGx1Y2luYXRpb25DaGVjayA/PyB0cnVlLFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgaWYgKG9wdGlvbnMud2FpdEZvclJlc3VsdCA9PT0gZmFsc2UgJiYgb3B0aW9ucy53ZWJob29rVXJsKSB7XG4gICAgICAvLyBBc3luYyBhbmFseXNpcyB3aXRoIHdlYmhvb2tcbiAgICAgIHJldHVybiBhcGlSZXF1ZXN0PEV4cGxhaW5hYmlsaXR5UmVzdWx0PignL2V4cGxhaW5lci9hbmFseXplLWFzeW5jJywge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgYm9keTogeyAuLi5wYXlsb2FkLCB3ZWJob29rVXJsOiBvcHRpb25zLndlYmhvb2tVcmwgfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBhcGlSZXF1ZXN0PEV4cGxhaW5hYmlsaXR5UmVzdWx0PignL2V4cGxhaW5lci9hbmFseXplJywge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5OiBwYXlsb2FkLFxuICAgIH0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiBCYXRjaCBhbmFseXplIG11bHRpcGxlIHRyYWNlc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBleHBsYWluZXIuYW5hbHl6ZUJhdGNoKFtcbiAgICogICB7IHVzZXJNZXNzYWdlOiAnUTEnLCBhZ2VudFJlc3BvbnNlOiAnQTEnIH0sXG4gICAqICAgeyB1c2VyTWVzc2FnZTogJ1EyJywgYWdlbnRSZXNwb25zZTogJ0EyJyB9LFxuICAgKiBdKTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBhbmFseXplQmF0Y2goXG4gICAgdHJhY2VzOiBUcmFjZU9wdGlvbnNbXSxcbiAgICBvcHRpb25zOiBBbmFseXplT3B0aW9ucyA9IHt9XG4gICk6IFByb21pc2U8e1xuICAgIHJlc3VsdHM6IEV4cGxhaW5hYmlsaXR5UmVzdWx0W107XG4gICAgc3VtbWFyeToge1xuICAgICAgdG90YWw6IG51bWJlcjtcbiAgICAgIHN1Y2Nlc3NDb3VudDogbnVtYmVyO1xuICAgICAgZmFpbHVyZUNvdW50OiBudW1iZXI7XG4gICAgICBhdmVyYWdlUHJvY2Vzc2luZ1RpbWU6IG51bWJlcjtcbiAgICB9O1xuICB9PiB7XG4gICAgaWYgKCFpbml0aWFsaXplZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpbmtIaXZlIFNESyBub3QgaW5pdGlhbGl6ZWQuIENhbGwgaW5pdCgpIGZpcnN0LlwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXBpUmVxdWVzdCgnL2V4cGxhaW5lci9hbmFseXplLWJhdGNoJywge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5OiB7XG4gICAgICAgIHRyYWNlczogdHJhY2VzLm1hcCh0ID0+ICh7XG4gICAgICAgICAgdXNlck1lc3NhZ2U6IHQudXNlck1lc3NhZ2UsXG4gICAgICAgICAgYWdlbnRSZXNwb25zZTogdC5hZ2VudFJlc3BvbnNlLFxuICAgICAgICAgIHVzZXJJbnRlbnQ6IHQudXNlckludGVudCxcbiAgICAgICAgICBvdXRjb21lOiB0Lm91dGNvbWUgfHwgJ3N1Y2Nlc3MnLFxuICAgICAgICAgIHNwYW5zOiB0LnNwYW5zLFxuICAgICAgICAgIGJ1c2luZXNzQ29udGV4dDogdC5idXNpbmVzc0NvbnRleHQsXG4gICAgICAgICAgbWV0YWRhdGE6IHQubWV0YWRhdGEsXG4gICAgICAgIH0pKSxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBhIHByZXZpb3VzbHkgYW5hbHl6ZWQgdHJhY2VcbiAgICovXG4gIGFzeW5jIGdldCh0cmFjZUlkOiBzdHJpbmcpOiBQcm9taXNlPEV4cGxhaW5hYmlsaXR5UmVzdWx0PiB7XG4gICAgaWYgKCFpbml0aWFsaXplZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpbmtIaXZlIFNESyBub3QgaW5pdGlhbGl6ZWQuIENhbGwgaW5pdCgpIGZpcnN0LlwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXBpUmVxdWVzdDxFeHBsYWluYWJpbGl0eVJlc3VsdD4oYC9leHBsYWluZXIvJHt0cmFjZUlkfWApO1xuICB9LFxuXG4gIC8qKlxuICAgKiBTZWFyY2ggdHJhY2VzIHNlbWFudGljYWxseVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBleHBsYWluZXIuc2VhcmNoKHtcbiAgICogICBxdWVyeTogJ29yZGVyIHJlZnVuZCBpc3N1ZXMnLFxuICAgKiAgIGZpbHRlcnM6IHsgb3V0Y29tZTogJ2ZhaWx1cmUnIH0sXG4gICAqICAgbGltaXQ6IDEwLFxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBzZWFyY2gocGFyYW1zOiB7XG4gICAgcXVlcnk6IHN0cmluZztcbiAgICBmaWx0ZXJzPzoge1xuICAgICAgb3V0Y29tZT86ICdzdWNjZXNzJyB8ICdmYWlsdXJlJyB8ICdwYXJ0aWFsX3N1Y2Nlc3MnO1xuICAgICAgbWluSW1wYWN0U2NvcmU/OiBudW1iZXI7XG4gICAgICBkYXRlUmFuZ2U/OiB7IGZyb206IERhdGU7IHRvOiBEYXRlIH07XG4gICAgfTtcbiAgICBsaW1pdD86IG51bWJlcjtcbiAgfSk6IFByb21pc2U8e1xuICAgIHJlc3VsdHM6IEFycmF5PEV4cGxhaW5hYmlsaXR5UmVzdWx0ICYgeyBzaW1pbGFyaXR5OiBudW1iZXIgfT47XG4gICAgdG90YWw6IG51bWJlcjtcbiAgfT4ge1xuICAgIGlmICghaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaW5rSGl2ZSBTREsgbm90IGluaXRpYWxpemVkLiBDYWxsIGluaXQoKSBmaXJzdC5cIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFwaVJlcXVlc3QoJy9leHBsYWluZXIvc2VhcmNoJywge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5OiBwYXJhbXMsXG4gICAgfSk7XG4gIH0sXG59O1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBGRUVEQkFDSyBDTElFTlRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBGZWVkYmFjayBBUEkgZm9yIGltcHJvdmluZyBhbmFseXNpcyBxdWFsaXR5XG4gKi9cbmV4cG9ydCBjb25zdCBmZWVkYmFjayA9IHtcbiAgLyoqXG4gICAqIFN1Ym1pdCBmZWVkYmFjayBmb3IgYSB0cmFjZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGF3YWl0IGZlZWRiYWNrLnN1Ym1pdCh7XG4gICAqICAgdHJhY2VJZDogJ3RyYWNlXzEyMycsXG4gICAqICAgcmF0aW5nOiA1LFxuICAgKiAgIHdhc0hlbHBmdWw6IHRydWUsXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIHN1Ym1pdChvcHRpb25zOiBGZWVkYmFja09wdGlvbnMpOiBQcm9taXNlPHsgc3VjY2VzczogYm9vbGVhbiB9PiB7XG4gICAgaWYgKCFpbml0aWFsaXplZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpbmtIaXZlIFNESyBub3QgaW5pdGlhbGl6ZWQuIENhbGwgaW5pdCgpIGZpcnN0LlwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXBpUmVxdWVzdCgnL2ZlZWRiYWNrJywge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5OiBvcHRpb25zLFxuICAgIH0pO1xuICB9LFxufTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUVVBTElUWSBNRVRSSUNTIENMSUVOVFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFF1YWxpdHkgbWV0cmljcyBBUEkgZm9yIFJBRyBldmFsdWF0aW9uIGFuZCBoYWxsdWNpbmF0aW9uIGRldGVjdGlvblxuICovXG5leHBvcnQgY29uc3QgcXVhbGl0eSA9IHtcbiAgLyoqXG4gICAqIEdldCBSQUcgZXZhbHVhdGlvbiBzY29yZXMgZm9yIGEgdHJhY2VcbiAgICovXG4gIGFzeW5jIGdldFJhZ1Njb3Jlcyh0cmFjZUlkOiBzdHJpbmcpOiBQcm9taXNlPHtcbiAgICBjb250ZXh0UmVsZXZhbmNlOiBudW1iZXI7XG4gICAgY29udGV4dFByZWNpc2lvbjogbnVtYmVyO1xuICAgIGNvbnRleHRSZWNhbGw6IG51bWJlcjtcbiAgICBncm91bmRlZG5lc3M6IG51bWJlcjtcbiAgICBmYWl0aGZ1bG5lc3M6IG51bWJlcjtcbiAgICBhbnN3ZXJSZWxldmFuY2U6IG51bWJlcjtcbiAgICBjaXRhdGlvbkFjY3VyYWN5OiBudW1iZXI7XG4gICAgY2l0YXRpb25Db21wbGV0ZW5lc3M6IG51bWJlcjtcbiAgICBvdmVyYWxsR3JhZGU6IHN0cmluZztcbiAgfT4ge1xuICAgIGlmICghaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaW5rSGl2ZSBTREsgbm90IGluaXRpYWxpemVkLiBDYWxsIGluaXQoKSBmaXJzdC5cIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFwaVJlcXVlc3QoYC9xdWFsaXR5L3JhZy1zY29yZXMvJHt0cmFjZUlkfWApO1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZXQgaGFsbHVjaW5hdGlvbiByZXBvcnQgZm9yIGEgdHJhY2VcbiAgICovXG4gIGFzeW5jIGdldEhhbGx1Y2luYXRpb25SZXBvcnQodHJhY2VJZDogc3RyaW5nKTogUHJvbWlzZTx7XG4gICAgaGFzSGFsbHVjaW5hdGlvbnM6IGJvb2xlYW47XG4gICAgc2V2ZXJpdHk6ICdub25lJyB8ICdsb3cnIHwgJ21lZGl1bScgfCAnaGlnaCc7XG4gICAgY29uZmlkZW5jZTogbnVtYmVyO1xuICAgIGRldGVjdGVkVHlwZXM6IEFycmF5PHtcbiAgICAgIHR5cGU6IHN0cmluZztcbiAgICAgIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gICAgICBldmlkZW5jZTogc3RyaW5nO1xuICAgICAgc2V2ZXJpdHk6IHN0cmluZztcbiAgICB9PjtcbiAgfT4ge1xuICAgIGlmICghaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaW5rSGl2ZSBTREsgbm90IGluaXRpYWxpemVkLiBDYWxsIGluaXQoKSBmaXJzdC5cIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFwaVJlcXVlc3QoYC9xdWFsaXR5L2hhbGx1Y2luYXRpb24tcmVwb3J0LyR7dHJhY2VJZH1gKTtcbiAgfSxcblxuICAvKipcbiAgICogRXZhbHVhdGUgUkFHIHF1YWxpdHkgZm9yIGN1c3RvbSBpbnB1dFxuICAgKi9cbiAgYXN5bmMgZXZhbHVhdGVSYWcoaW5wdXQ6IHtcbiAgICBxdWVyeTogc3RyaW5nO1xuICAgIHJlc3BvbnNlOiBzdHJpbmc7XG4gICAgY29udGV4dHM6IEFycmF5PHsgY29udGVudDogc3RyaW5nOyBzb3VyY2U/OiBzdHJpbmc7IHNjb3JlPzogbnVtYmVyIH0+O1xuICB9KTogUHJvbWlzZTx7XG4gICAgc2NvcmVzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+O1xuICAgIGdyYWRlOiBzdHJpbmc7XG4gICAgZ3JvdW5kZWRTcGFuczogc3RyaW5nW107XG4gICAgdW5ncm91bmRlZFNwYW5zOiBzdHJpbmdbXTtcbiAgfT4ge1xuICAgIGlmICghaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaW5rSGl2ZSBTREsgbm90IGluaXRpYWxpemVkLiBDYWxsIGluaXQoKSBmaXJzdC5cIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFwaVJlcXVlc3QoJy9xdWFsaXR5L2V2YWx1YXRlLXJhZycsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgYm9keTogaW5wdXQsXG4gICAgfSk7XG4gIH0sXG59O1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBST0kgQU5BTFlUSUNTIENMSUVOVFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFJPSSBhbmFseXRpY3MgQVBJIGZvciBidXNpbmVzcyBpbXBhY3QgdHJhY2tpbmdcbiAqL1xuZXhwb3J0IGNvbnN0IGFuYWx5dGljcyA9IHtcbiAgLyoqXG4gICAqIEdldCBST0kgc3VtbWFyeSBmb3IgdGhlIGFjY291bnRcbiAgICovXG4gIGFzeW5jIGdldFJvaVN1bW1hcnkoKTogUHJvbWlzZTx7XG4gICAgdG90YWxSZXZlbnVlU2F2ZWQ6IG51bWJlcjtcbiAgICBzdXBwb3J0Q29zdFJlZHVjdGlvbjogbnVtYmVyO1xuICAgIGF2ZXJhZ2VSZXNvbHV0aW9uVGltZTogbnVtYmVyO1xuICAgIGN1c3RvbWVyU2F0aXNmYWN0aW9uOiBudW1iZXI7XG4gICAgdHJlbmRzOiBBcnJheTx7XG4gICAgICBkYXRlOiBzdHJpbmc7XG4gICAgICByZXZlbnVlU2F2ZWQ6IG51bWJlcjtcbiAgICAgIHRyYWNlc0FuYWx5emVkOiBudW1iZXI7XG4gICAgfT47XG4gIH0+IHtcbiAgICBpZiAoIWluaXRpYWxpemVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlua0hpdmUgU0RLIG5vdCBpbml0aWFsaXplZC4gQ2FsbCBpbml0KCkgZmlyc3QuXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBhcGlSZXF1ZXN0KCcvYW5hbHl0aWNzL3JvaS9zdW1tYXJ5Jyk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBST0kgYnkgYWdlbnRcbiAgICovXG4gIGFzeW5jIGdldFJvaUJ5QWdlbnQoYWdlbnRJZDogc3RyaW5nKTogUHJvbWlzZTx7XG4gICAgYWdlbnRJZDogc3RyaW5nO1xuICAgIHJldmVudWVTYXZlZDogbnVtYmVyO1xuICAgIHRyYWNlc0FuYWx5emVkOiBudW1iZXI7XG4gICAgc3VjY2Vzc1JhdGU6IG51bWJlcjtcbiAgICB0b3BJc3N1ZXM6IEFycmF5PHsgaXNzdWU6IHN0cmluZzsgY291bnQ6IG51bWJlcjsgaW1wYWN0OiBudW1iZXIgfT47XG4gIH0+IHtcbiAgICBpZiAoIWluaXRpYWxpemVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlua0hpdmUgU0RLIG5vdCBpbml0aWFsaXplZC4gQ2FsbCBpbml0KCkgZmlyc3QuXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBhcGlSZXF1ZXN0KGAvYW5hbHl0aWNzL3JvaS9ieS1hZ2VudC8ke2FnZW50SWR9YCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBjb3JyZWxhdGlvbiBhbmFseXNpc1xuICAgKi9cbiAgYXN5bmMgZ2V0Q29ycmVsYXRpb25zKCk6IFByb21pc2U8e1xuICAgIGNvcnJlbGF0aW9uczogQXJyYXk8e1xuICAgICAgdHlwZTogc3RyaW5nO1xuICAgICAgY29lZmZpY2llbnQ6IG51bWJlcjtcbiAgICAgIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gICAgICBhY3Rpb25hYmxlSW5zaWdodDogc3RyaW5nO1xuICAgIH0+O1xuICB9PiB7XG4gICAgaWYgKCFpbml0aWFsaXplZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpbmtIaXZlIFNESyBub3QgaW5pdGlhbGl6ZWQuIENhbGwgaW5pdCgpIGZpcnN0LlwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXBpUmVxdWVzdCgnL2FuYWx5dGljcy9jb3JyZWxhdGlvbnMnKTtcbiAgfSxcbn07XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEFVVE8tSU5TVFJVTUVOVEFUSU9OXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogU2V0dXAgYXV0by1pbnN0cnVtZW50YXRpb24gZm9yIEFJIGZyYW1ld29ya3NcbiAqL1xuZnVuY3Rpb24gc2V0dXBBdXRvSW5zdHJ1bWVudGF0aW9uKFxuICBmcmFtZXdvcmtzOiBBcnJheTwnbGFuZ2NoYWluJyB8ICdvcGVuYWknIHwgJ2FudGhyb3BpYycgfCAnbGxhbWFpbmRleCc+XG4pOiB2b2lkIHtcbiAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKGBTZXR0aW5nIHVwIGF1dG8taW5zdHJ1bWVudGF0aW9uIGZvcjogJHtmcmFtZXdvcmtzLmpvaW4oJywgJyl9YCk7XG4gIH1cblxuICAvLyBOb3RlOiBGdWxsIGF1dG8taW5zdHJ1bWVudGF0aW9uIHJlcXVpcmVzIGZyYW1ld29yay1zcGVjaWZpYyBwYXRjaGVzXG4gIC8vIFRoaXMgaXMgYSBwbGFjZWhvbGRlciBmb3IgdGhlIGluc3RydW1lbnRhdGlvbiBzZXR1cFxuICAvLyBJbiBwcm9kdWN0aW9uLCB1c2UgQG9wZW50ZWxlbWV0cnkvaW5zdHJ1bWVudGF0aW9uLSogcGFja2FnZXNcblxuICBmb3IgKGNvbnN0IGZyYW1ld29yayBvZiBmcmFtZXdvcmtzKSB7XG4gICAgdHJ5IHtcbiAgICAgIHN3aXRjaCAoZnJhbWV3b3JrKSB7XG4gICAgICAgIGNhc2UgJ29wZW5haSc6XG4gICAgICAgICAgaW5zdHJ1bWVudE9wZW5BSSgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdsYW5nY2hhaW4nOlxuICAgICAgICAgIGluc3RydW1lbnRMYW5nQ2hhaW4oKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnYW50aHJvcGljJzpcbiAgICAgICAgICBpbnN0cnVtZW50QW50aHJvcGljKCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2xsYW1haW5kZXgnOlxuICAgICAgICAgIGluc3RydW1lbnRMbGFtYUluZGV4KCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBGYWlsZWQgdG8gaW5zdHJ1bWVudCAke2ZyYW1ld29ya306YCwgZXJyb3IpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBpbnN0cnVtZW50T3BlbkFJKCk6IHZvaWQge1xuICAvLyBQbGFjZWhvbGRlciAtIHdvdWxkIHBhdGNoIE9wZW5BSSBjbGllbnRcbiAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKCdPcGVuQUkgaW5zdHJ1bWVudGF0aW9uIHJlYWR5Jyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5zdHJ1bWVudExhbmdDaGFpbigpOiB2b2lkIHtcbiAgLy8gUGxhY2Vob2xkZXIgLSB3b3VsZCB1c2UgTGFuZ0NoYWluIGNhbGxiYWNrc1xuICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgY29uc29sZS5sb2coJ0xhbmdDaGFpbiBpbnN0cnVtZW50YXRpb24gcmVhZHknKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpbnN0cnVtZW50QW50aHJvcGljKCk6IHZvaWQge1xuICAvLyBQbGFjZWhvbGRlciAtIHdvdWxkIHBhdGNoIEFudGhyb3BpYyBjbGllbnRcbiAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKCdBbnRocm9waWMgaW5zdHJ1bWVudGF0aW9uIHJlYWR5Jyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5zdHJ1bWVudExsYW1hSW5kZXgoKTogdm9pZCB7XG4gIC8vIFBsYWNlaG9sZGVyIC0gd291bGQgdXNlIExsYW1hSW5kZXggY2FsbGJhY2tzXG4gIGlmIChjb25maWcuZGVidWcpIHtcbiAgICBjb25zb2xlLmxvZygnTGxhbWFJbmRleCBpbnN0cnVtZW50YXRpb24gcmVhZHknKTtcbiAgfVxufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDT05WRU5JRU5DRSBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDcmVhdGUgYSB0cmFjZSBhbmQgYW5hbHl6ZSBpdCBpbiBvbmUgY2FsbFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCB7IHRyYWNlLCBhbmFseXNpcyB9ID0gYXdhaXQgY3JlYXRlQW5kQW5hbHl6ZSh7XG4gKiAgIHVzZXJNZXNzYWdlOiAnSGVscCBtZSB0cmFjayBteSBvcmRlcicsXG4gKiAgIGFnZW50UmVzcG9uc2U6ICdZb3VyIG9yZGVyIGlzIG9uIHRoZSB3YXkuLi4nLFxuICogfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUFuZEFuYWx5emUoXG4gIHRyYWNlRGF0YTogVHJhY2VPcHRpb25zLFxuICBvcHRpb25zOiBBbmFseXplT3B0aW9ucyA9IHt9XG4pOiBQcm9taXNlPHtcbiAgdHJhY2U6IFRyYWNlT3B0aW9ucztcbiAgYW5hbHlzaXM6IEV4cGxhaW5hYmlsaXR5UmVzdWx0O1xufT4ge1xuICBjb25zdCBhbmFseXNpcyA9IGF3YWl0IGV4cGxhaW5lci5hbmFseXplKHRyYWNlRGF0YSwgb3B0aW9ucyk7XG4gIHJldHVybiB7IHRyYWNlOiB0cmFjZURhdGEsIGFuYWx5c2lzIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEVYUE9SVFNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGRlZmF1bHQge1xuICBpbml0LFxuICBnZXRUcmFjZXIsXG4gIGlzSW5pdGlhbGl6ZWQsXG4gIHRyYWNlTExNLFxuICB0cmFjZVJldHJpZXZhbCxcbiAgdHJhY2VUb29sLFxuICB0cmFjZUNoYWluLFxuICBleHBsYWluZXIsXG4gIGZlZWRiYWNrLFxuICBxdWFsaXR5LFxuICBhbmFseXRpY3MsXG4gIGNyZWF0ZUFuZEFuYWx5emUsXG59O1xuIl19