@thinkhive/sdk 3.3.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/MIGRATION.md CHANGED
@@ -1,6 +1,86 @@
1
- # Migration Guide: v2.x to v3.0
1
+ # Migration Guide
2
2
 
3
- This guide helps you migrate from ThinkHive SDK v2.x to v3.0.
3
+ This guide covers migration between major versions of the ThinkHive SDK.
4
+
5
+ ---
6
+
7
+ ## v3.x to v4.0
8
+
9
+ ### Breaking Changes
10
+
11
+ #### `apiVersion` Removed from `InitOptions`
12
+
13
+ The `apiVersion` configuration option has been removed. The SDK now handles API routing internally -- modules automatically route to the correct API version.
14
+
15
+ ```diff
16
+ init({
17
+ apiKey: 'th_xxx',
18
+ serviceName: 'my-agent',
19
+ - apiVersion: 'v3',
20
+ });
21
+ ```
22
+
23
+ #### Default Endpoint Changed
24
+
25
+ The default endpoint is now `https://app.thinkhive.ai` (previously pointed to the staging Cloud Run URL).
26
+
27
+ ```diff
28
+ // If you were relying on the old default, no action needed —
29
+ // the new default points to production.
30
+ // If you explicitly set the old staging URL, remove it:
31
+ init({
32
+ apiKey: 'th_xxx',
33
+ serviceName: 'my-agent',
34
+ - endpoint: 'https://thinkhivemind-h25z7pvd3q-uc.a.run.app',
35
+ });
36
+ ```
37
+
38
+ #### Calibration API Changes
39
+
40
+ `calibration.recordOutcome()` and `calibration.reliabilityDiagram()` have been removed. Use `calibration.status()` to check calibration state.
41
+
42
+ ```diff
43
+ - await calibration.recordOutcome({
44
+ - runId: run.id,
45
+ - predictionType: 'churn_risk',
46
+ - predictedValue: 0.7,
47
+ - actualOutcome: 1,
48
+ - });
49
+ -
50
+ - const diagram = await calibration.reliabilityDiagram(agentId);
51
+
52
+ // Still available:
53
+ const status = await calibration.status(agentId, 'churn_risk');
54
+ ```
55
+
56
+ #### OTLP Init Requires API Key
57
+
58
+ Initializing the SDK with only an `agentId` is no longer sufficient for OTLP-based tracing. You must provide an `apiKey`.
59
+
60
+ ```diff
61
+ init({
62
+ + apiKey: 'th_xxx',
63
+ agentId: 'agent-123',
64
+ serviceName: 'my-agent',
65
+ });
66
+ ```
67
+
68
+ #### Version Bump
69
+
70
+ The SDK version is now `4.0.0`. Update your `package.json`:
71
+
72
+ ```diff
73
+ "dependencies": {
74
+ - "@thinkhive/sdk": "^3.3.0"
75
+ + "@thinkhive/sdk": "^4.0.0"
76
+ }
77
+ ```
78
+
79
+ ---
80
+
81
+ ## v2.x to v3.0
82
+
83
+ This section covers migration from ThinkHive SDK v2.x to v3.0.
4
84
 
5
85
  ## Breaking Changes
6
86
 
@@ -48,13 +128,12 @@ init({
48
128
  serviceName: 'my-agent',
49
129
  });
50
130
 
51
- // v3
131
+ // v3+
52
132
  import { init } from '@thinkhive/sdk';
53
133
 
54
134
  init({
55
135
  apiKey: 'th_xxx',
56
136
  serviceName: 'my-agent',
57
- apiVersion: 'v3', // Default is v3
58
137
  });
59
138
  ```
60
139
 
@@ -196,14 +275,6 @@ import { calibration } from '@thinkhive/sdk';
196
275
  const status = await calibration.status('agent_123', 'churn_risk');
197
276
  console.log(`Brier score: ${status.brierScore}`);
198
277
  console.log(`Is calibrated: ${status.isCalibrated}`);
199
-
200
- // Record prediction outcomes
201
- await calibration.recordOutcome({
202
- runId: run.id,
203
- predictionType: 'churn_risk',
204
- predictedValue: 0.7, // We predicted 70% churn risk
205
- actualOutcome: 1, // Customer did churn
206
- });
207
278
  ```
208
279
 
209
280
  ## Deprecated APIs
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ThinkHive SDK v3.3.0
1
+ # ThinkHive SDK v4.0.0
2
2
 
3
3
  The official JavaScript/TypeScript SDK for [ThinkHive](https://thinkhive.ai) - AI Agent Observability Platform.
4
4
 
@@ -27,7 +27,7 @@ import { init, runs, traceLLM, shutdown } from '@thinkhive/sdk';
27
27
 
28
28
  // Initialize the SDK
29
29
  init({
30
- apiKey: 'th_your_api_key',
30
+ apiKey: 'thk_your_api_key',
31
31
  serviceName: 'my-ai-agent',
32
32
  autoInstrument: true,
33
33
  frameworks: ['langchain', 'openai'],
@@ -36,7 +36,7 @@ init({
36
36
  // Create a run (atomic unit of work)
37
37
  const run = await runs.create({
38
38
  agentId: 'weather-agent',
39
- conversation: [
39
+ conversationMessages: [
40
40
  { role: 'user', content: 'What is the weather in San Francisco?' },
41
41
  { role: 'assistant', content: 'The weather in San Francisco is currently 65°F and sunny.' }
42
42
  ],
@@ -54,7 +54,7 @@ await shutdown();
54
54
  ```typescript
55
55
  import { init, traceLLM, traceRetrieval, traceTool, traceChain } from '@thinkhive/sdk';
56
56
 
57
- init({ apiKey: 'th_your_api_key', serviceName: 'my-agent' });
57
+ init({ apiKey: 'thk_your_api_key', serviceName: 'my-agent' });
58
58
 
59
59
  // Trace an LLM call
60
60
  const response = await traceLLM({
@@ -194,14 +194,17 @@ const confident = getHighConfidenceClaims(claimList, 0.9);
194
194
  ```typescript
195
195
  import { calibration, calculateBrierScore, isWellCalibrated } from '@thinkhive/sdk';
196
196
 
197
- // Get calibration status
198
- const status = await calibration.getStatus(agentId);
197
+ // Get calibration status for a prediction type
198
+ const status = await calibration.status(agentId, 'churn_risk');
199
+
200
+ // Get all calibration metrics
201
+ const metrics = await calibration.allMetrics(agentId);
199
202
 
200
203
  // Calculate Brier score for predictions
201
- const brierScore = calculateBrierScore(predictions, outcomes);
204
+ const brierScore = calculateBrierScore(predictions);
202
205
 
203
206
  // Check if well calibrated
204
- if (isWellCalibrated(status)) {
207
+ if (isWellCalibrated(brierScore)) {
205
208
  console.log('Agent predictions are well calibrated');
206
209
  }
207
210
  ```
@@ -284,7 +287,7 @@ import { init } from '@thinkhive/sdk';
284
287
 
285
288
  // Initialize with auto-instrumentation
286
289
  init({
287
- apiKey: 'th_your_api_key',
290
+ apiKey: 'thk_your_api_key',
288
291
  serviceName: 'my-ai-agent',
289
292
  autoInstrument: true,
290
293
  frameworks: ['langchain', 'openai', 'anthropic']
@@ -306,10 +309,10 @@ init({
306
309
  | Variable | Description |
307
310
  |----------|-------------|
308
311
  | `THINKHIVE_API_KEY` | Your ThinkHive API key |
309
- | `THINKHIVE_ENDPOINT` | Custom API endpoint (default: https://demo.thinkhive.ai) |
312
+ | `THINKHIVE_ENDPOINT` | Custom API endpoint (default: https://app.thinkhive.ai) |
310
313
  | `THINKHIVE_SERVICE_NAME` | Service name for traces (optional) |
311
314
 
312
- ## V3 Architecture
315
+ ## Architecture
313
316
 
314
317
  ### Key Concepts
315
318
 
@@ -344,7 +347,7 @@ init({
344
347
  | `roiAnalytics` | Business ROI and financial impact analysis |
345
348
  | `qualityMetrics` | RAG evaluation and hallucination detection |
346
349
 
347
- ### New Evaluation APIs (v3.0)
350
+ ### Evaluation APIs
348
351
 
349
352
  | API | Description |
350
353
  |-----|-------------|
@@ -355,6 +358,15 @@ init({
355
358
  | `conversationEval` | Multi-turn conversation evaluation |
356
359
  | `transcriptPatterns` | Pattern detection in transcripts |
357
360
 
361
+ ## Upgrading from v3
362
+
363
+ See [MIGRATION.md](MIGRATION.md) for the full v3 → v4 migration guide. Key changes:
364
+
365
+ - **`apiVersion` removed** from `init()` options — routing is handled automatically per module
366
+ - **`calibration.recordOutcome()`** and **`calibration.reliabilityDiagram()`** removed — use `calibration.status()` and `calibration.allMetrics()` instead
367
+ - **Default endpoint** changed from staging to `https://app.thinkhive.ai`
368
+ - **OTLP init** now requires `apiKey` (agent ID alone is not sufficient)
369
+
358
370
  ## API Reference
359
371
 
360
372
  See [API Documentation](https://docs.thinkhive.ai/sdk/javascript/reference) for complete type definitions.
@@ -0,0 +1,169 @@
1
+ /**
2
+ * ThinkHive SDK - Agents Management
3
+ *
4
+ * CRUD operations for managing AI agents:
5
+ * - List, get, create, update, delete agents
6
+ * - Agent configuration management
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { agents } from 'thinkhive-js';
11
+ *
12
+ * // List all agents
13
+ * const allAgents = await agents.list();
14
+ *
15
+ * // Create a new agent
16
+ * const agent = await agents.create({
17
+ * name: 'Support Agent',
18
+ * description: 'Handles customer support',
19
+ * agentType: 'customer_support',
20
+ * primarySuccessMetric: 'Deflection Rate',
21
+ * });
22
+ *
23
+ * // Update an agent
24
+ * await agents.update(agent.id, { name: 'Updated Agent' });
25
+ *
26
+ * // Get agent configuration
27
+ * const config = await agents.getConfig(agent.id);
28
+ *
29
+ * // Delete an agent (with dry-run preview)
30
+ * const impact = await agents.delete(agent.id, { dryRun: true });
31
+ * console.log(`Will delete ${impact.cascadeImpact.traces} traces`);
32
+ *
33
+ * // Actually delete
34
+ * await agents.delete(agent.id);
35
+ * ```
36
+ */
37
+ export interface Agent {
38
+ id: string;
39
+ companyId: string;
40
+ departmentId?: string | null;
41
+ createdBy?: string | null;
42
+ name: string;
43
+ description: string;
44
+ industry: string;
45
+ successMetrics: string[];
46
+ agentType?: string | null;
47
+ agentOwner?: string | null;
48
+ builtInHouse?: boolean | null;
49
+ primarySuccessMetric?: string | null;
50
+ secondaryMetrics?: string[] | null;
51
+ connectedSystem?: string | null;
52
+ telemetryMethod?: string | null;
53
+ autoEvaluate?: boolean | null;
54
+ evaluationSampleRate?: string | null;
55
+ defaultCriteriaIds?: string[] | null;
56
+ defaultGuardrailIds?: string[] | null;
57
+ createdAt?: string | null;
58
+ }
59
+ export interface CreateAgentOptions {
60
+ name: string;
61
+ description?: string;
62
+ industry?: string;
63
+ agentType?: string;
64
+ agentOwner?: string;
65
+ builtInHouse?: boolean;
66
+ departmentId?: string;
67
+ successMetrics?: string[];
68
+ primarySuccessMetric?: string;
69
+ secondaryMetrics?: string[];
70
+ connectedSystem?: string;
71
+ autoEvaluate?: boolean;
72
+ evaluationSampleRate?: number;
73
+ }
74
+ export interface UpdateAgentOptions {
75
+ name?: string;
76
+ description?: string;
77
+ agentType?: string;
78
+ agentOwner?: string;
79
+ builtInHouse?: boolean;
80
+ departmentId?: string | null;
81
+ industry?: string;
82
+ primarySuccessMetric?: string;
83
+ secondaryMetrics?: string[];
84
+ connectedSystem?: string;
85
+ autoEvaluate?: boolean;
86
+ evaluationSampleRate?: number;
87
+ isActive?: boolean;
88
+ }
89
+ export interface AgentConfig {
90
+ id: string;
91
+ agentId: string;
92
+ version: number;
93
+ name: string;
94
+ description?: string | null;
95
+ provider: string;
96
+ model: string;
97
+ temperature?: string | null;
98
+ maxTokens?: number | null;
99
+ systemPrompt?: string | null;
100
+ promptTemplate?: string | null;
101
+ ragEnabled?: boolean | null;
102
+ ragConfig?: unknown;
103
+ toolsEnabled?: boolean | null;
104
+ tools?: unknown;
105
+ isBaseline?: boolean | null;
106
+ isActive?: boolean | null;
107
+ createdAt?: string | null;
108
+ updatedAt?: string | null;
109
+ }
110
+ export interface UpdateAgentConfigOptions {
111
+ name?: string;
112
+ provider?: string;
113
+ model?: string;
114
+ temperature?: number;
115
+ maxTokens?: number;
116
+ systemPrompt?: string;
117
+ promptTemplate?: string;
118
+ ragEnabled?: boolean;
119
+ ragConfig?: Record<string, unknown>;
120
+ toolsEnabled?: boolean;
121
+ tools?: unknown[];
122
+ }
123
+ export interface DeleteAgentOptions {
124
+ /** If true, returns cascade impact without actually deleting */
125
+ dryRun?: boolean;
126
+ }
127
+ export interface CascadeImpact {
128
+ dryRun: boolean;
129
+ agentId: string;
130
+ agentName: string;
131
+ cascadeImpact: {
132
+ traces: number;
133
+ apiKeys: number;
134
+ runningEvaluations?: number;
135
+ };
136
+ }
137
+ export declare const agents: {
138
+ /**
139
+ * List agents for the authenticated company
140
+ */
141
+ list(options?: {
142
+ companyId?: string;
143
+ departmentId?: string;
144
+ }): Promise<Agent[]>;
145
+ /**
146
+ * Get a single agent by ID
147
+ */
148
+ get(id: string): Promise<Agent>;
149
+ /**
150
+ * Create a new agent
151
+ */
152
+ create(options: CreateAgentOptions): Promise<Agent>;
153
+ /**
154
+ * Update an existing agent
155
+ */
156
+ update(id: string, options: UpdateAgentOptions): Promise<Agent>;
157
+ /**
158
+ * Delete an agent. Use dryRun option to preview cascade impact.
159
+ */
160
+ delete(id: string, options?: DeleteAgentOptions): Promise<void | CascadeImpact>;
161
+ /**
162
+ * Get agent configuration (baseline)
163
+ */
164
+ getConfig(agentId: string): Promise<AgentConfig | null>;
165
+ /**
166
+ * Create or update agent configuration
167
+ */
168
+ updateConfig(agentId: string, config: UpdateAgentConfigOptions): Promise<AgentConfig>;
169
+ };
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ /**
3
+ * ThinkHive SDK - Agents Management
4
+ *
5
+ * CRUD operations for managing AI agents:
6
+ * - List, get, create, update, delete agents
7
+ * - Agent configuration management
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { agents } from 'thinkhive-js';
12
+ *
13
+ * // List all agents
14
+ * const allAgents = await agents.list();
15
+ *
16
+ * // Create a new agent
17
+ * const agent = await agents.create({
18
+ * name: 'Support Agent',
19
+ * description: 'Handles customer support',
20
+ * agentType: 'customer_support',
21
+ * primarySuccessMetric: 'Deflection Rate',
22
+ * });
23
+ *
24
+ * // Update an agent
25
+ * await agents.update(agent.id, { name: 'Updated Agent' });
26
+ *
27
+ * // Get agent configuration
28
+ * const config = await agents.getConfig(agent.id);
29
+ *
30
+ * // Delete an agent (with dry-run preview)
31
+ * const impact = await agents.delete(agent.id, { dryRun: true });
32
+ * console.log(`Will delete ${impact.cascadeImpact.traces} traces`);
33
+ *
34
+ * // Actually delete
35
+ * await agents.delete(agent.id);
36
+ * ```
37
+ */
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.agents = void 0;
40
+ const client_1 = require("../core/client");
41
+ // ============================================================================
42
+ // API Client
43
+ // ============================================================================
44
+ exports.agents = {
45
+ /**
46
+ * List agents for the authenticated company
47
+ */
48
+ async list(options) {
49
+ const params = new URLSearchParams();
50
+ if (options?.companyId)
51
+ params.set('companyId', options.companyId);
52
+ if (options?.departmentId)
53
+ params.set('departmentId', options.departmentId);
54
+ const qs = params.toString();
55
+ const response = await (0, client_1.apiRequest)(`/agents${qs ? `?${qs}` : ''}`, { apiVersion: 'none' });
56
+ return response.data ?? response;
57
+ },
58
+ /**
59
+ * Get a single agent by ID
60
+ */
61
+ async get(id) {
62
+ if (!id)
63
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'id');
64
+ const response = await (0, client_1.apiRequest)(`/agents/${id}`, { apiVersion: 'none' });
65
+ return response.data ?? response;
66
+ },
67
+ /**
68
+ * Create a new agent
69
+ */
70
+ async create(options) {
71
+ if (!options.name) {
72
+ throw new client_1.ThinkHiveValidationError('Agent name is required', 'name');
73
+ }
74
+ const body = {
75
+ name: options.name,
76
+ description: options.description || '',
77
+ industry: options.industry || 'other',
78
+ successMetrics: options.successMetrics ?? [options.primarySuccessMetric || 'Task Success Rate'],
79
+ };
80
+ if (options.agentType)
81
+ body.agentType = options.agentType;
82
+ if (options.agentOwner)
83
+ body.agentOwner = options.agentOwner;
84
+ if (options.builtInHouse !== undefined)
85
+ body.builtInHouse = options.builtInHouse;
86
+ if (options.departmentId)
87
+ body.departmentId = options.departmentId;
88
+ if (options.primarySuccessMetric)
89
+ body.primarySuccessMetric = options.primarySuccessMetric;
90
+ if (options.secondaryMetrics)
91
+ body.secondaryMetrics = options.secondaryMetrics;
92
+ if (options.connectedSystem)
93
+ body.connectedSystem = options.connectedSystem;
94
+ if (options.autoEvaluate !== undefined)
95
+ body.autoEvaluate = options.autoEvaluate;
96
+ if (options.evaluationSampleRate !== undefined) {
97
+ body.evaluationSampleRate = options.evaluationSampleRate.toFixed(4);
98
+ }
99
+ const response = await (0, client_1.apiRequest)('/agents', {
100
+ method: 'POST',
101
+ body,
102
+ apiVersion: 'none',
103
+ });
104
+ return response.data ?? response;
105
+ },
106
+ /**
107
+ * Update an existing agent
108
+ */
109
+ async update(id, options) {
110
+ if (!id)
111
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'id');
112
+ const body = {};
113
+ if (options.name !== undefined)
114
+ body.name = options.name;
115
+ if (options.description !== undefined)
116
+ body.description = options.description;
117
+ if (options.agentType !== undefined)
118
+ body.agentType = options.agentType;
119
+ if (options.agentOwner !== undefined)
120
+ body.agentOwner = options.agentOwner;
121
+ if (options.builtInHouse !== undefined)
122
+ body.builtInHouse = options.builtInHouse;
123
+ if (options.departmentId !== undefined)
124
+ body.departmentId = options.departmentId;
125
+ if (options.industry !== undefined)
126
+ body.industry = options.industry;
127
+ if (options.primarySuccessMetric !== undefined)
128
+ body.primarySuccessMetric = options.primarySuccessMetric;
129
+ if (options.secondaryMetrics !== undefined)
130
+ body.secondaryMetrics = options.secondaryMetrics;
131
+ if (options.connectedSystem !== undefined)
132
+ body.connectedSystem = options.connectedSystem;
133
+ if (options.autoEvaluate !== undefined)
134
+ body.autoEvaluate = options.autoEvaluate;
135
+ if (options.isActive !== undefined)
136
+ body.isActive = options.isActive;
137
+ if (options.evaluationSampleRate !== undefined) {
138
+ body.evaluationSampleRate = options.evaluationSampleRate.toFixed(4);
139
+ }
140
+ const response = await (0, client_1.apiRequest)(`/agents/${id}`, {
141
+ method: 'PATCH',
142
+ body,
143
+ apiVersion: 'none',
144
+ });
145
+ return response.data ?? response;
146
+ },
147
+ /**
148
+ * Delete an agent. Use dryRun option to preview cascade impact.
149
+ */
150
+ async delete(id, options) {
151
+ if (!id)
152
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'id');
153
+ const qs = options?.dryRun ? '?dryRun=true' : '';
154
+ const response = await (0, client_1.apiRequest)(`/agents/${id}${qs}`, {
155
+ method: 'DELETE',
156
+ apiVersion: 'none',
157
+ });
158
+ if (options?.dryRun) {
159
+ return response.data ?? response;
160
+ }
161
+ },
162
+ /**
163
+ * Get agent configuration (baseline)
164
+ */
165
+ async getConfig(agentId) {
166
+ if (!agentId)
167
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'agentId');
168
+ const response = await (0, client_1.apiRequest)(`/agents/${agentId}/config`, { apiVersion: 'none' });
169
+ return response?.data ?? response ?? null;
170
+ },
171
+ /**
172
+ * Create or update agent configuration
173
+ */
174
+ async updateConfig(agentId, config) {
175
+ if (!agentId)
176
+ throw new client_1.ThinkHiveValidationError('Agent ID is required', 'agentId');
177
+ const response = await (0, client_1.apiRequest)(`/agents/${agentId}/config`, {
178
+ method: 'PUT',
179
+ body: config,
180
+ apiVersion: 'none',
181
+ });
182
+ return response.data ?? response;
183
+ },
184
+ };
185
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FwaS9hZ2VudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1DRzs7O0FBRUgsMkNBQXNFO0FBaUh0RSwrRUFBK0U7QUFDL0UsYUFBYTtBQUNiLCtFQUErRTtBQUVsRSxRQUFBLE1BQU0sR0FBRztJQUNwQjs7T0FFRztJQUNILEtBQUssQ0FBQyxJQUFJLENBQUMsT0FHVjtRQUNDLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7UUFDckMsSUFBSSxPQUFPLEVBQUUsU0FBUztZQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNuRSxJQUFJLE9BQU8sRUFBRSxZQUFZO1lBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRTVFLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM3QixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUEsbUJBQVUsRUFBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUMxRixPQUFRLFFBQWdCLENBQUMsSUFBSSxJQUFJLFFBQVEsQ0FBQztJQUM1QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQVU7UUFDbEIsSUFBSSxDQUFDLEVBQUU7WUFBRSxNQUFNLElBQUksaUNBQXdCLENBQUMsc0JBQXNCLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDMUUsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFBLG1CQUFVLEVBQUMsV0FBVyxFQUFFLEVBQUUs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QyxPQUFPO1lBQUUsTUFBTSxJQUFJLGlDQUF3QixDQUFDLHNCQUFzQixFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBRXBGLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBQSxtQkFBVSxFQUFDLFdBQVcsT0FBTyxTQUFTLEVBQUU7WUFDN0QsTUFBTSxFQUFFLEtBQUs7WUFDYixJQUFJLEVBQUUsTUFBTTtZQUNaLFVBQVUsRUFBRSxNQUFNO1NBQ25CLENBQUMsQ0FBQztRQUNILE9BQVEsUUFBZ0IsQ0FBQyxJQUFJLElBQUksUUFBUSxDQUFDO0lBQzVDLENBQUM7Q0FDRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGlua0hpdmUgU0RLIC0gQWdlbnRzIE1hbmFnZW1lbnRcbiAqXG4gKiBDUlVEIG9wZXJhdGlvbnMgZm9yIG1hbmFnaW5nIEFJIGFnZW50czpcbiAqIC0gTGlzdCwgZ2V0LCBjcmVhdGUsIHVwZGF0ZSwgZGVsZXRlIGFnZW50c1xuICogLSBBZ2VudCBjb25maWd1cmF0aW9uIG1hbmFnZW1lbnRcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgYWdlbnRzIH0gZnJvbSAndGhpbmtoaXZlLWpzJztcbiAqXG4gKiAvLyBMaXN0IGFsbCBhZ2VudHNcbiAqIGNvbnN0IGFsbEFnZW50cyA9IGF3YWl0IGFnZW50cy5saXN0KCk7XG4gKlxuICogLy8gQ3JlYXRlIGEgbmV3IGFnZW50XG4gKiBjb25zdCBhZ2VudCA9IGF3YWl0IGFnZW50cy5jcmVhdGUoe1xuICogICBuYW1lOiAnU3VwcG9ydCBBZ2VudCcsXG4gKiAgIGRlc2NyaXB0aW9uOiAnSGFuZGxlcyBjdXN0b21lciBzdXBwb3J0JyxcbiAqICAgYWdlbnRUeXBlOiAnY3VzdG9tZXJfc3VwcG9ydCcsXG4gKiAgIHByaW1hcnlTdWNjZXNzTWV0cmljOiAnRGVmbGVjdGlvbiBSYXRlJyxcbiAqIH0pO1xuICpcbiAqIC8vIFVwZGF0ZSBhbiBhZ2VudFxuICogYXdhaXQgYWdlbnRzLnVwZGF0ZShhZ2VudC5pZCwgeyBuYW1lOiAnVXBkYXRlZCBBZ2VudCcgfSk7XG4gKlxuICogLy8gR2V0IGFnZW50IGNvbmZpZ3VyYXRpb25cbiAqIGNvbnN0IGNvbmZpZyA9IGF3YWl0IGFnZW50cy5nZXRDb25maWcoYWdlbnQuaWQpO1xuICpcbiAqIC8vIERlbGV0ZSBhbiBhZ2VudCAod2l0aCBkcnktcnVuIHByZXZpZXcpXG4gKiBjb25zdCBpbXBhY3QgPSBhd2FpdCBhZ2VudHMuZGVsZXRlKGFnZW50LmlkLCB7IGRyeVJ1bjogdHJ1ZSB9KTtcbiAqIGNvbnNvbGUubG9nKGBXaWxsIGRlbGV0ZSAke2ltcGFjdC5jYXNjYWRlSW1wYWN0LnRyYWNlc30gdHJhY2VzYCk7XG4gKlxuICogLy8gQWN0dWFsbHkgZGVsZXRlXG4gKiBhd2FpdCBhZ2VudHMuZGVsZXRlKGFnZW50LmlkKTtcbiAqIGBgYFxuICovXG5cbmltcG9ydCB7IGFwaVJlcXVlc3QsIFRoaW5rSGl2ZVZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4uL2NvcmUvY2xpZW50JztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVHlwZXNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBBZ2VudCB7XG4gIGlkOiBzdHJpbmc7XG4gIGNvbXBhbnlJZDogc3RyaW5nO1xuICBkZXBhcnRtZW50SWQ/OiBzdHJpbmcgfCBudWxsO1xuICBjcmVhdGVkQnk/OiBzdHJpbmcgfCBudWxsO1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIGluZHVzdHJ5OiBzdHJpbmc7XG4gIHN1Y2Nlc3NNZXRyaWNzOiBzdHJpbmdbXTtcbiAgYWdlbnRUeXBlPzogc3RyaW5nIHwgbnVsbDtcbiAgYWdlbnRPd25lcj86IHN0cmluZyB8IG51bGw7XG4gIGJ1aWx0SW5Ib3VzZT86IGJvb2xlYW4gfCBudWxsO1xuICBwcmltYXJ5U3VjY2Vzc01ldHJpYz86IHN0cmluZyB8IG51bGw7XG4gIHNlY29uZGFyeU1ldHJpY3M/OiBzdHJpbmdbXSB8IG51bGw7XG4gIGNvbm5lY3RlZFN5c3RlbT86IHN0cmluZyB8IG51bGw7XG4gIHRlbGVtZXRyeU1ldGhvZD86IHN0cmluZyB8IG51bGw7XG4gIGF1dG9FdmFsdWF0ZT86IGJvb2xlYW4gfCBudWxsO1xuICBldmFsdWF0aW9uU2FtcGxlUmF0ZT86IHN0cmluZyB8IG51bGw7XG4gIGRlZmF1bHRDcml0ZXJpYUlkcz86IHN0cmluZ1tdIHwgbnVsbDtcbiAgZGVmYXVsdEd1YXJkcmFpbElkcz86IHN0cmluZ1tdIHwgbnVsbDtcbiAgY3JlYXRlZEF0Pzogc3RyaW5nIHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVBZ2VudE9wdGlvbnMge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICBpbmR1c3RyeT86IHN0cmluZztcbiAgYWdlbnRUeXBlPzogc3RyaW5nO1xuICBhZ2VudE93bmVyPzogc3RyaW5nO1xuICBidWlsdEluSG91c2U/OiBib29sZWFuO1xuICBkZXBhcnRtZW50SWQ/OiBzdHJpbmc7XG4gIHN1Y2Nlc3NNZXRyaWNzPzogc3RyaW5nW107XG4gIHByaW1hcnlTdWNjZXNzTWV0cmljPzogc3RyaW5nO1xuICBzZWNvbmRhcnlNZXRyaWNzPzogc3RyaW5nW107XG4gIGNvbm5lY3RlZFN5c3RlbT86IHN0cmluZztcbiAgYXV0b0V2YWx1YXRlPzogYm9vbGVhbjtcbiAgZXZhbHVhdGlvblNhbXBsZVJhdGU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXBkYXRlQWdlbnRPcHRpb25zIHtcbiAgbmFtZT86IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIGFnZW50VHlwZT86IHN0cmluZztcbiAgYWdlbnRPd25lcj86IHN0cmluZztcbiAgYnVpbHRJbkhvdXNlPzogYm9vbGVhbjtcbiAgZGVwYXJ0bWVudElkPzogc3RyaW5nIHwgbnVsbDtcbiAgaW5kdXN0cnk/OiBzdHJpbmc7XG4gIHByaW1hcnlTdWNjZXNzTWV0cmljPzogc3RyaW5nO1xuICBzZWNvbmRhcnlNZXRyaWNzPzogc3RyaW5nW107XG4gIGNvbm5lY3RlZFN5c3RlbT86IHN0cmluZztcbiAgYXV0b0V2YWx1YXRlPzogYm9vbGVhbjtcbiAgZXZhbHVhdGlvblNhbXBsZVJhdGU/OiBudW1iZXI7XG4gIGlzQWN0aXZlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBZ2VudENvbmZpZyB7XG4gIGlkOiBzdHJpbmc7XG4gIGFnZW50SWQ6IHN0cmluZztcbiAgdmVyc2lvbjogbnVtYmVyO1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nIHwgbnVsbDtcbiAgcHJvdmlkZXI6IHN0cmluZztcbiAgbW9kZWw6IHN0cmluZztcbiAgdGVtcGVyYXR1cmU/OiBzdHJpbmcgfCBudWxsO1xuICBtYXhUb2tlbnM/OiBudW1iZXIgfCBudWxsO1xuICBzeXN0ZW1Qcm9tcHQ/OiBzdHJpbmcgfCBudWxsO1xuICBwcm9tcHRUZW1wbGF0ZT86IHN0cmluZyB8IG51bGw7XG4gIHJhZ0VuYWJsZWQ/OiBib29sZWFuIHwgbnVsbDtcbiAgcmFnQ29uZmlnPzogdW5rbm93bjtcbiAgdG9vbHNFbmFibGVkPzogYm9vbGVhbiB8IG51bGw7XG4gIHRvb2xzPzogdW5rbm93bjtcbiAgaXNCYXNlbGluZT86IGJvb2xlYW4gfCBudWxsO1xuICBpc0FjdGl2ZT86IGJvb2xlYW4gfCBudWxsO1xuICBjcmVhdGVkQXQ/OiBzdHJpbmcgfCBudWxsO1xuICB1cGRhdGVkQXQ/OiBzdHJpbmcgfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVwZGF0ZUFnZW50Q29uZmlnT3B0aW9ucyB7XG4gIG5hbWU/OiBzdHJpbmc7XG4gIHByb3ZpZGVyPzogc3RyaW5nO1xuICBtb2RlbD86IHN0cmluZztcbiAgdGVtcGVyYXR1cmU/OiBudW1iZXI7XG4gIG1heFRva2Vucz86IG51bWJlcjtcbiAgc3lzdGVtUHJvbXB0Pzogc3RyaW5nO1xuICBwcm9tcHRUZW1wbGF0ZT86IHN0cmluZztcbiAgcmFnRW5hYmxlZD86IGJvb2xlYW47XG4gIHJhZ0NvbmZpZz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB0b29sc0VuYWJsZWQ/OiBib29sZWFuO1xuICB0b29scz86IHVua25vd25bXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZWxldGVBZ2VudE9wdGlvbnMge1xuICAvKiogSWYgdHJ1ZSwgcmV0dXJucyBjYXNjYWRlIGltcGFjdCB3aXRob3V0IGFjdHVhbGx5IGRlbGV0aW5nICovXG4gIGRyeVJ1bj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FzY2FkZUltcGFjdCB7XG4gIGRyeVJ1bjogYm9vbGVhbjtcbiAgYWdlbnRJZDogc3RyaW5nO1xuICBhZ2VudE5hbWU6IHN0cmluZztcbiAgY2FzY2FkZUltcGFjdDoge1xuICAgIHRyYWNlczogbnVtYmVyO1xuICAgIGFwaUtleXM6IG51bWJlcjtcbiAgICBydW5uaW5nRXZhbHVhdGlvbnM/OiBudW1iZXI7XG4gIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEFQSSBDbGllbnRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGNvbnN0IGFnZW50cyA9IHtcbiAgLyoqXG4gICAqIExpc3QgYWdlbnRzIGZvciB0aGUgYXV0aGVudGljYXRlZCBjb21wYW55XG4gICAqL1xuICBhc3luYyBsaXN0KG9wdGlvbnM/OiB7XG4gICAgY29tcGFueUlkPzogc3RyaW5nO1xuICAgIGRlcGFydG1lbnRJZD86IHN0cmluZztcbiAgfSk6IFByb21pc2U8QWdlbnRbXT4ge1xuICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTtcbiAgICBpZiAob3B0aW9ucz8uY29tcGFueUlkKSBwYXJhbXMuc2V0KCdjb21wYW55SWQnLCBvcHRpb25zLmNvbXBhbnlJZCk7XG4gICAgaWYgKG9wdGlvbnM/LmRlcGFydG1lbnRJZCkgcGFyYW1zLnNldCgnZGVwYXJ0bWVudElkJywgb3B0aW9ucy5kZXBhcnRtZW50SWQpO1xuXG4gICAgY29uc3QgcXMgPSBwYXJhbXMudG9TdHJpbmcoKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3QoYC9hZ2VudHMke3FzID8gYD8ke3FzfWAgOiAnJ31gLCB7IGFwaVZlcnNpb246ICdub25lJyB9KTtcbiAgICByZXR1cm4gKHJlc3BvbnNlIGFzIGFueSkuZGF0YSA/PyByZXNwb25zZTtcbiAgfSxcblxuICAvKipcbiAgICogR2V0IGEgc2luZ2xlIGFnZW50IGJ5IElEXG4gICAqL1xuICBhc3luYyBnZXQoaWQ6IHN0cmluZyk6IFByb21pc2U8QWdlbnQ+IHtcbiAgICBpZiAoIWlkKSB0aHJvdyBuZXcgVGhpbmtIaXZlVmFsaWRhdGlvbkVycm9yKCdBZ2VudCBJRCBpcyByZXF1aXJlZCcsICdpZCcpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXBpUmVxdWVzdChgL2FnZW50cy8ke2lkfWAsIHsgYXBpVmVyc2lvbjogJ25vbmUnIH0pO1xuICAgIHJldHVybiAocmVzcG9uc2UgYXMgYW55KS5kYXRhID8/IHJlc3BvbnNlO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgYWdlbnRcbiAgICovXG4gIGFzeW5jIGNyZWF0ZShvcHRpb25zOiBDcmVhdGVBZ2VudE9wdGlvbnMpOiBQcm9taXNlPEFnZW50PiB7XG4gICAgaWYgKCFvcHRpb25zLm5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBUaGlua0hpdmVWYWxpZGF0aW9uRXJyb3IoJ0FnZW50IG5hbWUgaXMgcmVxdWlyZWQnLCAnbmFtZScpO1xuICAgIH1cblxuICAgIGNvbnN0IGJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgICAgbmFtZTogb3B0aW9ucy5uYW1lLFxuICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnMuZGVzY3JpcHRpb24gfHwgJycsXG4gICAgICBpbmR1c3RyeTogb3B0aW9ucy5pbmR1c3RyeSB8fCAnb3RoZXInLFxuICAgICAgc3VjY2Vzc01ldHJpY3M6IG9wdGlvbnMuc3VjY2Vzc01ldHJpY3MgPz8gW29wdGlvbnMucHJpbWFyeVN1Y2Nlc3NNZXRyaWMgfHwgJ1Rhc2sgU3VjY2VzcyBSYXRlJ10sXG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zLmFnZW50VHlwZSkgYm9keS5hZ2VudFR5cGUgPSBvcHRpb25zLmFnZW50VHlwZTtcbiAgICBpZiAob3B0aW9ucy5hZ2VudE93bmVyKSBib2R5LmFnZW50T3duZXIgPSBvcHRpb25zLmFnZW50T3duZXI7XG4gICAgaWYgKG9wdGlvbnMuYnVpbHRJbkhvdXNlICE9PSB1bmRlZmluZWQpIGJvZHkuYnVpbHRJbkhvdXNlID0gb3B0aW9ucy5idWlsdEluSG91c2U7XG4gICAgaWYgKG9wdGlvbnMuZGVwYXJ0bWVudElkKSBib2R5LmRlcGFydG1lbnRJZCA9IG9wdGlvbnMuZGVwYXJ0bWVudElkO1xuICAgIGlmIChvcHRpb25zLnByaW1hcnlTdWNjZXNzTWV0cmljKSBib2R5LnByaW1hcnlTdWNjZXNzTWV0cmljID0gb3B0aW9ucy5wcmltYXJ5U3VjY2Vzc01ldHJpYztcbiAgICBpZiAob3B0aW9ucy5zZWNvbmRhcnlNZXRyaWNzKSBib2R5LnNlY29uZGFyeU1ldHJpY3MgPSBvcHRpb25zLnNlY29uZGFyeU1ldHJpY3M7XG4gICAgaWYgKG9wdGlvbnMuY29ubmVjdGVkU3lzdGVtKSBib2R5LmNvbm5lY3RlZFN5c3RlbSA9IG9wdGlvbnMuY29ubmVjdGVkU3lzdGVtO1xuICAgIGlmIChvcHRpb25zLmF1dG9FdmFsdWF0ZSAhPT0gdW5kZWZpbmVkKSBib2R5LmF1dG9FdmFsdWF0ZSA9IG9wdGlvbnMuYXV0b0V2YWx1YXRlO1xuICAgIGlmIChvcHRpb25zLmV2YWx1YXRpb25TYW1wbGVSYXRlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGJvZHkuZXZhbHVhdGlvblNhbXBsZVJhdGUgPSBvcHRpb25zLmV2YWx1YXRpb25TYW1wbGVSYXRlLnRvRml4ZWQoNCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBhcGlSZXF1ZXN0KCcvYWdlbnRzJywge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5LFxuICAgICAgYXBpVmVyc2lvbjogJ25vbmUnLFxuICAgIH0pO1xuICAgIHJldHVybiAocmVzcG9uc2UgYXMgYW55KS5kYXRhID8/IHJlc3BvbnNlO1xuICB9LFxuXG4gIC8qKlxuICAgKiBVcGRhdGUgYW4gZXhpc3RpbmcgYWdlbnRcbiAgICovXG4gIGFzeW5jIHVwZGF0ZShpZDogc3RyaW5nLCBvcHRpb25zOiBVcGRhdGVBZ2VudE9wdGlvbnMpOiBQcm9taXNlPEFnZW50PiB7XG4gICAgaWYgKCFpZCkgdGhyb3cgbmV3IFRoaW5rSGl2ZVZhbGlkYXRpb25FcnJvcignQWdlbnQgSUQgaXMgcmVxdWlyZWQnLCAnaWQnKTtcblxuICAgIGNvbnN0IGJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgaWYgKG9wdGlvbnMubmFtZSAhPT0gdW5kZWZpbmVkKSBib2R5Lm5hbWUgPSBvcHRpb25zLm5hbWU7XG4gICAgaWYgKG9wdGlvbnMuZGVzY3JpcHRpb24gIT09IHVuZGVmaW5lZCkgYm9keS5kZXNjcmlwdGlvbiA9IG9wdGlvbnMuZGVzY3JpcHRpb247XG4gICAgaWYgKG9wdGlvbnMuYWdlbnRUeXBlICE9PSB1bmRlZmluZWQpIGJvZHkuYWdlbnRUeXBlID0gb3B0aW9ucy5hZ2VudFR5cGU7XG4gICAgaWYgKG9wdGlvbnMuYWdlbnRPd25lciAhPT0gdW5kZWZpbmVkKSBib2R5LmFnZW50T3duZXIgPSBvcHRpb25zLmFnZW50T3duZXI7XG4gICAgaWYgKG9wdGlvbnMuYnVpbHRJbkhvdXNlICE9PSB1bmRlZmluZWQpIGJvZHkuYnVpbHRJbkhvdXNlID0gb3B0aW9ucy5idWlsdEluSG91c2U7XG4gICAgaWYgKG9wdGlvbnMuZGVwYXJ0bWVudElkICE9PSB1bmRlZmluZWQpIGJvZHkuZGVwYXJ0bWVudElkID0gb3B0aW9ucy5kZXBhcnRtZW50SWQ7XG4gICAgaWYgKG9wdGlvbnMuaW5kdXN0cnkgIT09IHVuZGVmaW5lZCkgYm9keS5pbmR1c3RyeSA9IG9wdGlvbnMuaW5kdXN0cnk7XG4gICAgaWYgKG9wdGlvbnMucHJpbWFyeVN1Y2Nlc3NNZXRyaWMgIT09IHVuZGVmaW5lZCkgYm9keS5wcmltYXJ5U3VjY2Vzc01ldHJpYyA9IG9wdGlvbnMucHJpbWFyeVN1Y2Nlc3NNZXRyaWM7XG4gICAgaWYgKG9wdGlvbnMuc2Vjb25kYXJ5TWV0cmljcyAhPT0gdW5kZWZpbmVkKSBib2R5LnNlY29uZGFyeU1ldHJpY3MgPSBvcHRpb25zLnNlY29uZGFyeU1ldHJpY3M7XG4gICAgaWYgKG9wdGlvbnMuY29ubmVjdGVkU3lzdGVtICE9PSB1bmRlZmluZWQpIGJvZHkuY29ubmVjdGVkU3lzdGVtID0gb3B0aW9ucy5jb25uZWN0ZWRTeXN0ZW07XG4gICAgaWYgKG9wdGlvbnMuYXV0b0V2YWx1YXRlICE9PSB1bmRlZmluZWQpIGJvZHkuYXV0b0V2YWx1YXRlID0gb3B0aW9ucy5hdXRvRXZhbHVhdGU7XG4gICAgaWYgKG9wdGlvbnMuaXNBY3RpdmUgIT09IHVuZGVmaW5lZCkgYm9keS5pc0FjdGl2ZSA9IG9wdGlvbnMuaXNBY3RpdmU7XG4gICAgaWYgKG9wdGlvbnMuZXZhbHVhdGlvblNhbXBsZVJhdGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgYm9keS5ldmFsdWF0aW9uU2FtcGxlUmF0ZSA9IG9wdGlvbnMuZXZhbHVhdGlvblNhbXBsZVJhdGUudG9GaXhlZCg0KTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3QoYC9hZ2VudHMvJHtpZH1gLCB7XG4gICAgICBtZXRob2Q6ICdQQVRDSCcsXG4gICAgICBib2R5LFxuICAgICAgYXBpVmVyc2lvbjogJ25vbmUnLFxuICAgIH0pO1xuICAgIHJldHVybiAocmVzcG9uc2UgYXMgYW55KS5kYXRhID8/IHJlc3BvbnNlO1xuICB9LFxuXG4gIC8qKlxuICAgKiBEZWxldGUgYW4gYWdlbnQuIFVzZSBkcnlSdW4gb3B0aW9uIHRvIHByZXZpZXcgY2FzY2FkZSBpbXBhY3QuXG4gICAqL1xuICBhc3luYyBkZWxldGUoaWQ6IHN0cmluZywgb3B0aW9ucz86IERlbGV0ZUFnZW50T3B0aW9ucyk6IFByb21pc2U8dm9pZCB8IENhc2NhZGVJbXBhY3Q+IHtcbiAgICBpZiAoIWlkKSB0aHJvdyBuZXcgVGhpbmtIaXZlVmFsaWRhdGlvbkVycm9yKCdBZ2VudCBJRCBpcyByZXF1aXJlZCcsICdpZCcpO1xuXG4gICAgY29uc3QgcXMgPSBvcHRpb25zPy5kcnlSdW4gPyAnP2RyeVJ1bj10cnVlJyA6ICcnO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXBpUmVxdWVzdChgL2FnZW50cy8ke2lkfSR7cXN9YCwge1xuICAgICAgbWV0aG9kOiAnREVMRVRFJyxcbiAgICAgIGFwaVZlcnNpb246ICdub25lJyxcbiAgICB9KTtcblxuICAgIGlmIChvcHRpb25zPy5kcnlSdW4pIHtcbiAgICAgIHJldHVybiAocmVzcG9uc2UgYXMgYW55KS5kYXRhID8/IHJlc3BvbnNlO1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogR2V0IGFnZW50IGNvbmZpZ3VyYXRpb24gKGJhc2VsaW5lKVxuICAgKi9cbiAgYXN5bmMgZ2V0Q29uZmlnKGFnZW50SWQ6IHN0cmluZyk6IFByb21pc2U8QWdlbnRDb25maWcgfCBudWxsPiB7XG4gICAgaWYgKCFhZ2VudElkKSB0aHJvdyBuZXcgVGhpbmtIaXZlVmFsaWRhdGlvbkVycm9yKCdBZ2VudCBJRCBpcyByZXF1aXJlZCcsICdhZ2VudElkJyk7XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGFwaVJlcXVlc3QoYC9hZ2VudHMvJHthZ2VudElkfS9jb25maWdgLCB7IGFwaVZlcnNpb246ICdub25lJyB9KTtcbiAgICByZXR1cm4gKHJlc3BvbnNlIGFzIGFueSk/LmRhdGEgPz8gcmVzcG9uc2UgPz8gbnVsbDtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYXRlIG9yIHVwZGF0ZSBhZ2VudCBjb25maWd1cmF0aW9uXG4gICAqL1xuICBhc3luYyB1cGRhdGVDb25maWcoYWdlbnRJZDogc3RyaW5nLCBjb25maWc6IFVwZGF0ZUFnZW50Q29uZmlnT3B0aW9ucyk6IFByb21pc2U8QWdlbnRDb25maWc+IHtcbiAgICBpZiAoIWFnZW50SWQpIHRocm93IG5ldyBUaGlua0hpdmVWYWxpZGF0aW9uRXJyb3IoJ0FnZW50IElEIGlzIHJlcXVpcmVkJywgJ2FnZW50SWQnKTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXBpUmVxdWVzdChgL2FnZW50cy8ke2FnZW50SWR9L2NvbmZpZ2AsIHtcbiAgICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgICBib2R5OiBjb25maWcsXG4gICAgICBhcGlWZXJzaW9uOiAnbm9uZScsXG4gICAgfSk7XG4gICAgcmV0dXJuIChyZXNwb25zZSBhcyBhbnkpLmRhdGEgPz8gcmVzcG9uc2U7XG4gIH0sXG59O1xuIl19