@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/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/index.d.ts +629 -0
- package/dist/index.js +639 -0
- package/package.json +54 -0
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
|