@cdklabs/cdk-appmod-catalog-blueprints 1.4.1 → 1.6.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/.jsii +2579 -194
- package/lib/document-processing/adapter/adapter.d.ts +4 -2
- package/lib/document-processing/adapter/adapter.js +1 -1
- package/lib/document-processing/adapter/queued-s3-adapter.d.ts +9 -2
- package/lib/document-processing/adapter/queued-s3-adapter.js +29 -15
- package/lib/document-processing/agentic-document-processing.d.ts +4 -0
- package/lib/document-processing/agentic-document-processing.js +20 -10
- package/lib/document-processing/base-document-processing.d.ts +54 -2
- package/lib/document-processing/base-document-processing.js +136 -82
- package/lib/document-processing/bedrock-document-processing.d.ts +202 -2
- package/lib/document-processing/bedrock-document-processing.js +717 -77
- package/lib/document-processing/chunking-config.d.ts +614 -0
- package/lib/document-processing/chunking-config.js +5 -0
- package/lib/document-processing/default-document-processing-config.js +1 -1
- package/lib/document-processing/index.d.ts +1 -0
- package/lib/document-processing/index.js +2 -1
- package/lib/document-processing/resources/aggregation/handler.py +567 -0
- package/lib/document-processing/resources/aggregation/requirements.txt +7 -0
- package/lib/document-processing/resources/aggregation/test_handler.py +362 -0
- package/lib/document-processing/resources/cleanup/handler.py +276 -0
- package/lib/document-processing/resources/cleanup/requirements.txt +5 -0
- package/lib/document-processing/resources/cleanup/test_handler.py +436 -0
- package/lib/document-processing/resources/default-bedrock-invoke/index.py +85 -3
- package/lib/document-processing/resources/default-bedrock-invoke/test_index.py +622 -0
- package/lib/document-processing/resources/pdf-chunking/README.md +313 -0
- package/lib/document-processing/resources/pdf-chunking/chunking_strategies.py +460 -0
- package/lib/document-processing/resources/pdf-chunking/error_handling.py +491 -0
- package/lib/document-processing/resources/pdf-chunking/handler.py +958 -0
- package/lib/document-processing/resources/pdf-chunking/metrics.py +435 -0
- package/lib/document-processing/resources/pdf-chunking/requirements.txt +3 -0
- package/lib/document-processing/resources/pdf-chunking/strategy_selection.py +420 -0
- package/lib/document-processing/resources/pdf-chunking/structured_logging.py +457 -0
- package/lib/document-processing/resources/pdf-chunking/test_chunking_strategies.py +353 -0
- package/lib/document-processing/resources/pdf-chunking/test_error_handling.py +487 -0
- package/lib/document-processing/resources/pdf-chunking/test_handler.py +609 -0
- package/lib/document-processing/resources/pdf-chunking/test_integration.py +694 -0
- package/lib/document-processing/resources/pdf-chunking/test_metrics.py +532 -0
- package/lib/document-processing/resources/pdf-chunking/test_strategy_selection.py +471 -0
- package/lib/document-processing/resources/pdf-chunking/test_structured_logging.py +449 -0
- package/lib/document-processing/resources/pdf-chunking/test_token_estimation.py +374 -0
- package/lib/document-processing/resources/pdf-chunking/token_estimation.py +189 -0
- package/lib/document-processing/tests/agentic-document-processing-nag.test.js +4 -3
- package/lib/document-processing/tests/agentic-document-processing.test.js +488 -4
- package/lib/document-processing/tests/base-document-processing-nag.test.js +9 -2
- package/lib/document-processing/tests/base-document-processing-schema.test.d.ts +1 -0
- package/lib/document-processing/tests/base-document-processing-schema.test.js +337 -0
- package/lib/document-processing/tests/base-document-processing.test.js +114 -8
- package/lib/document-processing/tests/bedrock-document-processing-chunking-nag.test.d.ts +1 -0
- package/lib/document-processing/tests/bedrock-document-processing-chunking-nag.test.js +382 -0
- package/lib/document-processing/tests/bedrock-document-processing-nag.test.js +4 -3
- package/lib/document-processing/tests/bedrock-document-processing-security.test.d.ts +1 -0
- package/lib/document-processing/tests/bedrock-document-processing-security.test.js +389 -0
- package/lib/document-processing/tests/bedrock-document-processing.test.js +808 -8
- package/lib/document-processing/tests/chunking-config.test.d.ts +1 -0
- package/lib/document-processing/tests/chunking-config.test.js +238 -0
- package/lib/document-processing/tests/queued-s3-adapter-nag.test.js +9 -2
- package/lib/document-processing/tests/queued-s3-adapter.test.js +17 -6
- package/lib/framework/agents/base-agent.js +1 -1
- package/lib/framework/agents/batch-agent.js +1 -1
- package/lib/framework/agents/default-agent-config.js +1 -1
- package/lib/framework/bedrock/bedrock.js +1 -1
- package/lib/framework/custom-resource/default-runtimes.js +1 -1
- package/lib/framework/foundation/access-log.js +1 -1
- package/lib/framework/foundation/eventbridge-broker.js +1 -1
- package/lib/framework/foundation/network.d.ts +4 -2
- package/lib/framework/foundation/network.js +52 -41
- package/lib/framework/tests/access-log.test.js +5 -2
- package/lib/framework/tests/batch-agent.test.js +5 -2
- package/lib/framework/tests/bedrock.test.js +5 -2
- package/lib/framework/tests/eventbridge-broker.test.js +5 -2
- package/lib/framework/tests/framework-nag.test.js +26 -7
- package/lib/framework/tests/network.test.js +30 -2
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utilities/data-loader.js +1 -1
- package/lib/utilities/lambda-iam-utils.js +1 -1
- package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.js +1 -1
- package/lib/utilities/observability/default-observability-config.js +1 -1
- package/lib/utilities/observability/lambda-observability-property-injector.js +1 -1
- package/lib/utilities/observability/log-group-data-protection-utils.js +1 -1
- package/lib/utilities/observability/powertools-config.d.ts +10 -1
- package/lib/utilities/observability/powertools-config.js +19 -3
- package/lib/utilities/observability/state-machine-observability-property-injector.js +1 -1
- package/lib/utilities/test-utils.d.ts +43 -0
- package/lib/utilities/test-utils.js +56 -0
- package/lib/utilities/tests/data-loader-nag.test.js +3 -2
- package/lib/utilities/tests/data-loader.test.js +3 -2
- package/lib/webapp/frontend-construct.js +1 -1
- package/lib/webapp/tests/frontend-construct-nag.test.js +3 -2
- package/lib/webapp/tests/frontend-construct.test.js +3 -2
- package/package.json +6 -5
- package/lib/document-processing/resources/default-error-handler/index.js +0 -46
- package/lib/document-processing/resources/default-pdf-processor/index.js +0 -46
- package/lib/document-processing/resources/default-pdf-validator/index.js +0 -36
|
@@ -11,6 +11,7 @@ const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
|
11
11
|
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
|
|
12
12
|
const aws_iam_1 = require("aws-cdk-lib/aws-iam");
|
|
13
13
|
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
|
14
|
+
const aws_stepfunctions_1 = require("aws-cdk-lib/aws-stepfunctions");
|
|
14
15
|
const aws_stepfunctions_tasks_1 = require("aws-cdk-lib/aws-stepfunctions-tasks");
|
|
15
16
|
const base_document_processing_1 = require("./base-document-processing");
|
|
16
17
|
const framework_1 = require("../framework");
|
|
@@ -58,9 +59,24 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
|
|
|
58
59
|
* @param scope - The scope in which to define this construct
|
|
59
60
|
* @param id - The scoped construct ID. Must be unique within the scope.
|
|
60
61
|
* @param props - Configuration properties for the Bedrock document processing pipeline
|
|
62
|
+
* @throws Error if chunking configuration is invalid
|
|
61
63
|
*/
|
|
62
64
|
constructor(scope, id, props) {
|
|
63
65
|
super(scope, id, props);
|
|
66
|
+
/** Counter for generating unique classification step IDs */
|
|
67
|
+
this._classificationStepCounter = 0;
|
|
68
|
+
/** Counter for generating unique processing step IDs */
|
|
69
|
+
this._processingStepCounter = 0;
|
|
70
|
+
/** Counter for generating unique aggregation step IDs */
|
|
71
|
+
this._aggregationStepCounter = 0;
|
|
72
|
+
/** Counter for generating unique enrichment step IDs */
|
|
73
|
+
this._enrichmentStepCounter = 0;
|
|
74
|
+
/** Counter for generating unique post-processing step IDs */
|
|
75
|
+
this._postProcessingStepCounter = 0;
|
|
76
|
+
// Validate chunking configuration if provided
|
|
77
|
+
if (props.enableChunking && props.chunkingConfig) {
|
|
78
|
+
this.validateChunkingConfig(props.chunkingConfig);
|
|
79
|
+
}
|
|
64
80
|
if (props.network) {
|
|
65
81
|
props.network.createServiceEndpoint('vpce-bedrock', aws_ec2_1.InterfaceVpcEndpointAwsService.BEDROCK);
|
|
66
82
|
props.network.createServiceEndpoint('vpce-bedrock-runtime', aws_ec2_1.InterfaceVpcEndpointAwsService.BEDROCK_RUNTIME);
|
|
@@ -68,6 +84,77 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
|
|
|
68
84
|
this.bedrockDocumentProcessingProps = props;
|
|
69
85
|
this.stateMachine = this.handleStateMachineCreation('bedrock-document-processing-workflow');
|
|
70
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Validates the chunking configuration parameters.
|
|
89
|
+
*
|
|
90
|
+
* Ensures that:
|
|
91
|
+
* - Chunk size is greater than 0
|
|
92
|
+
* - Overlap is non-negative and less than chunk size
|
|
93
|
+
* - Thresholds are greater than 0
|
|
94
|
+
* - Max concurrency is greater than 0
|
|
95
|
+
* - Min success threshold is between 0 and 1
|
|
96
|
+
*
|
|
97
|
+
* @param config - The chunking configuration to validate
|
|
98
|
+
* @throws Error if any configuration parameter is invalid
|
|
99
|
+
*/
|
|
100
|
+
validateChunkingConfig(config) {
|
|
101
|
+
// Validate chunk size (for fixed-pages strategy)
|
|
102
|
+
if (config.chunkSize !== undefined) {
|
|
103
|
+
if (config.chunkSize <= 0) {
|
|
104
|
+
throw new Error('ChunkingConfig validation error: chunkSize must be greater than 0');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Validate overlap pages (for fixed-pages strategy)
|
|
108
|
+
if (config.overlapPages !== undefined) {
|
|
109
|
+
if (config.overlapPages < 0) {
|
|
110
|
+
throw new Error('ChunkingConfig validation error: overlapPages must be non-negative');
|
|
111
|
+
}
|
|
112
|
+
const effectiveChunkSize = config.chunkSize || 50; // default chunk size
|
|
113
|
+
if (config.overlapPages >= effectiveChunkSize) {
|
|
114
|
+
throw new Error('ChunkingConfig validation error: overlapPages must be less than chunkSize');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Validate page threshold
|
|
118
|
+
if (config.pageThreshold !== undefined && config.pageThreshold <= 0) {
|
|
119
|
+
throw new Error('ChunkingConfig validation error: pageThreshold must be greater than 0');
|
|
120
|
+
}
|
|
121
|
+
// Validate token threshold
|
|
122
|
+
if (config.tokenThreshold !== undefined && config.tokenThreshold <= 0) {
|
|
123
|
+
throw new Error('ChunkingConfig validation error: tokenThreshold must be greater than 0');
|
|
124
|
+
}
|
|
125
|
+
// Validate max tokens per chunk (for token-based strategy)
|
|
126
|
+
if (config.maxTokensPerChunk !== undefined && config.maxTokensPerChunk <= 0) {
|
|
127
|
+
throw new Error('ChunkingConfig validation error: maxTokensPerChunk must be greater than 0');
|
|
128
|
+
}
|
|
129
|
+
// Validate overlap tokens (for token-based and hybrid strategies)
|
|
130
|
+
if (config.overlapTokens !== undefined) {
|
|
131
|
+
if (config.overlapTokens < 0) {
|
|
132
|
+
throw new Error('ChunkingConfig validation error: overlapTokens must be non-negative');
|
|
133
|
+
}
|
|
134
|
+
const effectiveMaxTokens = config.maxTokensPerChunk || 100000; // default max tokens
|
|
135
|
+
if (config.overlapTokens >= effectiveMaxTokens) {
|
|
136
|
+
throw new Error('ChunkingConfig validation error: overlapTokens must be less than maxTokensPerChunk');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Validate max pages per chunk (for hybrid strategy)
|
|
140
|
+
if (config.maxPagesPerChunk !== undefined && config.maxPagesPerChunk <= 0) {
|
|
141
|
+
throw new Error('ChunkingConfig validation error: maxPagesPerChunk must be greater than 0');
|
|
142
|
+
}
|
|
143
|
+
// Validate target tokens per chunk (for hybrid strategy)
|
|
144
|
+
if (config.targetTokensPerChunk !== undefined && config.targetTokensPerChunk <= 0) {
|
|
145
|
+
throw new Error('ChunkingConfig validation error: targetTokensPerChunk must be greater than 0');
|
|
146
|
+
}
|
|
147
|
+
// Validate max concurrency
|
|
148
|
+
if (config.maxConcurrency !== undefined && config.maxConcurrency <= 0) {
|
|
149
|
+
throw new Error('ChunkingConfig validation error: maxConcurrency must be greater than 0');
|
|
150
|
+
}
|
|
151
|
+
// Validate min success threshold
|
|
152
|
+
if (config.minSuccessThreshold !== undefined) {
|
|
153
|
+
if (config.minSuccessThreshold < 0 || config.minSuccessThreshold > 1) {
|
|
154
|
+
throw new Error('ChunkingConfig validation error: minSuccessThreshold must be between 0 and 1');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
71
158
|
/**
|
|
72
159
|
* Implements the document classification step using Amazon Bedrock.
|
|
73
160
|
*
|
|
@@ -75,47 +162,60 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
|
|
|
75
162
|
* the document type. The function reads the document from S3 and sends it to
|
|
76
163
|
* Bedrock with the classification prompt.
|
|
77
164
|
*
|
|
165
|
+
* This method caches the Lambda function to avoid creating duplicate resources,
|
|
166
|
+
* but creates a new LambdaInvoke task each time to allow proper state chaining.
|
|
167
|
+
*
|
|
78
168
|
* @returns LambdaInvoke task configured for document classification
|
|
79
169
|
*/
|
|
80
170
|
classificationStep() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
account
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
171
|
+
// Create Lambda function only once
|
|
172
|
+
if (!this._classificationFunction) {
|
|
173
|
+
const prompt = this.bedrockDocumentProcessingProps.classificationPrompt || BedrockDocumentProcessing.DEFAULT_CLASSIFICATION_PROMPT;
|
|
174
|
+
const adjustedModelId = bedrock_1.BedrockModelUtils.deriveActualModelId(this.bedrockDocumentProcessingProps.classificationBedrockModel);
|
|
175
|
+
const role = this.generateLambdaRoleForBedrock('ClassificationLambdaRole', this.bedrockDocumentProcessingProps.classificationBedrockModel);
|
|
176
|
+
const { region, account } = aws_cdk_lib_1.Stack.of(this);
|
|
177
|
+
const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
|
|
178
|
+
account,
|
|
179
|
+
functionName: 'bedrock-idp-classification',
|
|
180
|
+
region,
|
|
181
|
+
scope: this,
|
|
182
|
+
enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
|
|
183
|
+
});
|
|
184
|
+
this.encryptionKey.grantEncryptDecrypt(role);
|
|
185
|
+
this._classificationFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'BedrockClassificationFunction', {
|
|
186
|
+
functionName: generatedLogPermissions.uniqueFunctionName,
|
|
187
|
+
architecture: aws_lambda_1.Architecture.X86_64,
|
|
188
|
+
runtime: framework_1.DefaultRuntimes.PYTHON,
|
|
189
|
+
entry: path.join(__dirname, 'resources/default-bedrock-invoke'),
|
|
190
|
+
role,
|
|
191
|
+
memorySize: 512,
|
|
192
|
+
timeout: this.bedrockDocumentProcessingProps.stepTimeouts || aws_cdk_lib_1.Duration.minutes(5),
|
|
193
|
+
environment: {
|
|
194
|
+
MODEL_ID: adjustedModelId,
|
|
195
|
+
PROMPT: prompt,
|
|
196
|
+
INVOKE_TYPE: 'classification',
|
|
197
|
+
...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
|
|
198
|
+
},
|
|
199
|
+
environmentEncryption: this.encryptionKey,
|
|
200
|
+
vpc: this.bedrockDocumentProcessingProps.network
|
|
201
|
+
? this.bedrockDocumentProcessingProps.network.vpc
|
|
202
|
+
: undefined,
|
|
203
|
+
vpcSubnets: this.bedrockDocumentProcessingProps.network
|
|
204
|
+
? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
|
|
205
|
+
: undefined,
|
|
206
|
+
});
|
|
207
|
+
for (const statement of generatedLogPermissions.policyStatements) {
|
|
208
|
+
this._classificationFunction.role?.addToPrincipalPolicy(statement);
|
|
209
|
+
}
|
|
210
|
+
if (this.bedrockDocumentProcessingProps.network) {
|
|
211
|
+
this._classificationFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
|
|
212
|
+
}
|
|
116
213
|
}
|
|
117
|
-
|
|
118
|
-
|
|
214
|
+
// Always create a new LambdaInvoke task to allow proper state chaining
|
|
215
|
+
const stepId = `ClassificationStep-${this._classificationStepCounter}`;
|
|
216
|
+
this._classificationStepCounter++;
|
|
217
|
+
return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
|
|
218
|
+
lambdaFunction: this._classificationFunction,
|
|
119
219
|
resultPath: '$.classificationResult',
|
|
120
220
|
resultSelector: {
|
|
121
221
|
'documentClassification.$': '$.Payload.documentClassification',
|
|
@@ -129,46 +229,59 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
|
|
|
129
229
|
* structured data from the document. Uses the classification result from the
|
|
130
230
|
* previous step to provide context for more accurate extraction.
|
|
131
231
|
*
|
|
232
|
+
* This method caches the Lambda function to avoid creating duplicate resources,
|
|
233
|
+
* but creates a new LambdaInvoke task each time to allow proper state chaining.
|
|
234
|
+
*
|
|
132
235
|
* @returns LambdaInvoke task configured for document extraction
|
|
133
236
|
*/
|
|
134
237
|
processingStep() {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
account
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
238
|
+
// Create Lambda function only once
|
|
239
|
+
if (!this._processingFunction) {
|
|
240
|
+
const prompt = this.bedrockDocumentProcessingProps.processingPrompt || BedrockDocumentProcessing.DEFAULT_PROCESSING_PROMPT;
|
|
241
|
+
const adjustedModelId = bedrock_1.BedrockModelUtils.deriveActualModelId(this.bedrockDocumentProcessingProps.processingBedrockModel);
|
|
242
|
+
const role = this.generateLambdaRoleForBedrock('ProcessingLambdaRole', this.bedrockDocumentProcessingProps.processingBedrockModel);
|
|
243
|
+
const { region, account } = aws_cdk_lib_1.Stack.of(this);
|
|
244
|
+
const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
|
|
245
|
+
account,
|
|
246
|
+
functionName: 'bedrock-idp-processing',
|
|
247
|
+
region,
|
|
248
|
+
scope: this,
|
|
249
|
+
});
|
|
250
|
+
this.encryptionKey.grantEncryptDecrypt(role);
|
|
251
|
+
this._processingFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'BedrockExtractionFunction', {
|
|
252
|
+
functionName: generatedLogPermissions.uniqueFunctionName,
|
|
253
|
+
runtime: framework_1.DefaultRuntimes.PYTHON,
|
|
254
|
+
architecture: aws_lambda_1.Architecture.X86_64,
|
|
255
|
+
entry: path.join(__dirname, 'resources/default-bedrock-invoke'),
|
|
256
|
+
role,
|
|
257
|
+
memorySize: 512,
|
|
258
|
+
timeout: this.bedrockDocumentProcessingProps.stepTimeouts || aws_cdk_lib_1.Duration.minutes(5),
|
|
259
|
+
environment: {
|
|
260
|
+
MODEL_ID: adjustedModelId,
|
|
261
|
+
PROMPT: prompt,
|
|
262
|
+
INVOKE_TYPE: 'processing',
|
|
263
|
+
...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
|
|
264
|
+
},
|
|
265
|
+
environmentEncryption: this.encryptionKey,
|
|
266
|
+
vpc: this.bedrockDocumentProcessingProps.network
|
|
267
|
+
? this.bedrockDocumentProcessingProps.network.vpc
|
|
268
|
+
: undefined,
|
|
269
|
+
vpcSubnets: this.bedrockDocumentProcessingProps.network
|
|
270
|
+
? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
|
|
271
|
+
: undefined,
|
|
272
|
+
});
|
|
273
|
+
for (const statement of generatedLogPermissions.policyStatements) {
|
|
274
|
+
this._processingFunction.role?.addToPrincipalPolicy(statement);
|
|
275
|
+
}
|
|
276
|
+
if (this.bedrockDocumentProcessingProps.network) {
|
|
277
|
+
this._processingFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
|
|
278
|
+
}
|
|
169
279
|
}
|
|
170
|
-
|
|
171
|
-
|
|
280
|
+
// Always create a new LambdaInvoke task to allow proper state chaining
|
|
281
|
+
const stepId = `ProcessingStep-${this._processingStepCounter}`;
|
|
282
|
+
this._processingStepCounter++;
|
|
283
|
+
return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
|
|
284
|
+
lambdaFunction: this._processingFunction,
|
|
172
285
|
resultPath: '$.processingResult',
|
|
173
286
|
resultSelector: {
|
|
174
287
|
'documentClassification.$': '$.Payload.documentClassification',
|
|
@@ -182,6 +295,7 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
|
|
|
182
295
|
inlinePolicies: {
|
|
183
296
|
BedrockInvokePolicy: new aws_iam_1.PolicyDocument({
|
|
184
297
|
statements: [
|
|
298
|
+
// S3 read-only access for document retrieval - least privilege
|
|
185
299
|
...this.ingressAdapter.generateAdapterIAMPolicies(),
|
|
186
300
|
bedrock_1.BedrockModelUtils.generateModelIAMPermissions(this, model),
|
|
187
301
|
],
|
|
@@ -202,9 +316,13 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
|
|
|
202
316
|
if (!this.bedrockDocumentProcessingProps.enrichmentLambdaFunction) {
|
|
203
317
|
return undefined;
|
|
204
318
|
}
|
|
205
|
-
|
|
319
|
+
const stepId = `EnrichmentStep-${this._enrichmentStepCounter}`;
|
|
320
|
+
this._enrichmentStepCounter++;
|
|
321
|
+
return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
|
|
206
322
|
lambdaFunction: this.bedrockDocumentProcessingProps.enrichmentLambdaFunction,
|
|
207
323
|
resultPath: '$.enrichedResult',
|
|
324
|
+
outputPath: '$',
|
|
325
|
+
payloadResponseOnly: true,
|
|
208
326
|
});
|
|
209
327
|
}
|
|
210
328
|
/**
|
|
@@ -220,15 +338,515 @@ class BedrockDocumentProcessing extends base_document_processing_1.BaseDocumentP
|
|
|
220
338
|
if (!this.bedrockDocumentProcessingProps.postProcessingLambdaFunction) {
|
|
221
339
|
return undefined;
|
|
222
340
|
}
|
|
223
|
-
|
|
341
|
+
const stepId = `PostProcessingStep-${this._postProcessingStepCounter}`;
|
|
342
|
+
this._postProcessingStepCounter++;
|
|
343
|
+
return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
|
|
224
344
|
lambdaFunction: this.bedrockDocumentProcessingProps.postProcessingLambdaFunction,
|
|
225
345
|
resultPath: '$.postProcessedResult',
|
|
346
|
+
outputPath: '$',
|
|
347
|
+
payloadResponseOnly: true,
|
|
226
348
|
});
|
|
227
349
|
}
|
|
350
|
+
/**
|
|
351
|
+
* Implements the optional preprocessing step for PDF chunking.
|
|
352
|
+
*
|
|
353
|
+
* When chunking is enabled, creates a Lambda function that analyzes PDFs and
|
|
354
|
+
* splits large documents into manageable chunks. The function:
|
|
355
|
+
* 1. Analyzes the PDF to determine page count and token estimates
|
|
356
|
+
* 2. Decides if chunking is needed based on configured thresholds
|
|
357
|
+
* 3. If chunking is needed, splits the PDF and uploads chunks to S3
|
|
358
|
+
*
|
|
359
|
+
* @returns LambdaInvoke task for PDF analysis and chunking, or undefined if chunking is disabled
|
|
360
|
+
*/
|
|
361
|
+
preprocessingStep() {
|
|
362
|
+
// Only enable chunking if explicitly configured
|
|
363
|
+
if (!this.bedrockDocumentProcessingProps.enableChunking) {
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
const { region, account } = aws_cdk_lib_1.Stack.of(this);
|
|
367
|
+
const chunkingConfig = this.bedrockDocumentProcessingProps.chunkingConfig || {};
|
|
368
|
+
// Create IAM role for chunking Lambda with least privilege permissions
|
|
369
|
+
// Chunking Lambda needs: GetObject (read raw PDFs), PutObject (write chunks)
|
|
370
|
+
const role = new aws_iam_1.Role(this, 'ChunkingLambdaRole', {
|
|
371
|
+
assumedBy: new aws_iam_1.ServicePrincipal('lambda.amazonaws.com'),
|
|
372
|
+
inlinePolicies: {
|
|
373
|
+
ChunkingPolicy: new aws_iam_1.PolicyDocument({
|
|
374
|
+
statements: [
|
|
375
|
+
...this.ingressAdapter.generateAdapterIAMPolicies(),
|
|
376
|
+
],
|
|
377
|
+
}),
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
|
|
381
|
+
account,
|
|
382
|
+
functionName: 'bedrock-idp-chunking',
|
|
383
|
+
region,
|
|
384
|
+
scope: this,
|
|
385
|
+
enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
|
|
386
|
+
});
|
|
387
|
+
this.encryptionKey.grantEncryptDecrypt(role);
|
|
388
|
+
// Create PDF Analysis & Chunking Lambda
|
|
389
|
+
const chunkingLambda = new aws_lambda_python_alpha_1.PythonFunction(this, 'PDFChunkingFunction', {
|
|
390
|
+
functionName: generatedLogPermissions.uniqueFunctionName,
|
|
391
|
+
entry: path.join(__dirname, 'resources/pdf-chunking'),
|
|
392
|
+
index: 'handler.py',
|
|
393
|
+
handler: 'handler',
|
|
394
|
+
runtime: framework_1.DefaultRuntimes.PYTHON,
|
|
395
|
+
architecture: aws_lambda_1.Architecture.X86_64,
|
|
396
|
+
role,
|
|
397
|
+
memorySize: 2048,
|
|
398
|
+
timeout: aws_cdk_lib_1.Duration.minutes(10),
|
|
399
|
+
environment: {
|
|
400
|
+
CHUNKING_STRATEGY: chunkingConfig.strategy || 'hybrid',
|
|
401
|
+
PAGE_THRESHOLD: String(chunkingConfig.pageThreshold || 100),
|
|
402
|
+
TOKEN_THRESHOLD: String(chunkingConfig.tokenThreshold || 150000),
|
|
403
|
+
CHUNK_SIZE: String(chunkingConfig.chunkSize || 50),
|
|
404
|
+
OVERLAP_PAGES: String(chunkingConfig.overlapPages || 5),
|
|
405
|
+
MAX_TOKENS_PER_CHUNK: String(chunkingConfig.maxTokensPerChunk || 100000),
|
|
406
|
+
OVERLAP_TOKENS: String(chunkingConfig.overlapTokens || 5000),
|
|
407
|
+
TARGET_TOKENS_PER_CHUNK: String(chunkingConfig.targetTokensPerChunk || 80000),
|
|
408
|
+
MAX_PAGES_PER_CHUNK: String(chunkingConfig.maxPagesPerChunk || 99),
|
|
409
|
+
...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
|
|
410
|
+
},
|
|
411
|
+
environmentEncryption: this.encryptionKey,
|
|
412
|
+
vpc: this.bedrockDocumentProcessingProps.network
|
|
413
|
+
? this.bedrockDocumentProcessingProps.network.vpc
|
|
414
|
+
: undefined,
|
|
415
|
+
vpcSubnets: this.bedrockDocumentProcessingProps.network
|
|
416
|
+
? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
|
|
417
|
+
: undefined,
|
|
418
|
+
});
|
|
419
|
+
for (const statement of generatedLogPermissions.policyStatements) {
|
|
420
|
+
chunkingLambda.role?.addToPrincipalPolicy(statement);
|
|
421
|
+
}
|
|
422
|
+
if (this.bedrockDocumentProcessingProps.network) {
|
|
423
|
+
chunkingLambda.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
|
|
424
|
+
}
|
|
425
|
+
return new aws_stepfunctions_tasks_1.LambdaInvoke(this, 'PDFAnalysisAndChunking', {
|
|
426
|
+
lambdaFunction: chunkingLambda,
|
|
427
|
+
resultPath: '$.chunkingResult',
|
|
428
|
+
resultSelector: {
|
|
429
|
+
'requiresChunking.$': '$.Payload.requiresChunking',
|
|
430
|
+
'tokenAnalysis.$': '$.Payload.tokenAnalysis',
|
|
431
|
+
'strategy.$': '$.Payload.strategy',
|
|
432
|
+
'chunks.$': '$.Payload.chunks',
|
|
433
|
+
},
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Provides additional metadata fields for chunking to be stored in DynamoDB.
|
|
438
|
+
*
|
|
439
|
+
* When chunking is enabled, adds fields for:
|
|
440
|
+
* - ChunkingEnabled: string representation of boolean flag
|
|
441
|
+
* - ChunkingStrategy: strategy used (fixed-pages, token-based, hybrid)
|
|
442
|
+
* - TokenAnalysis: JSON string with token analysis results
|
|
443
|
+
* - ChunkMetadata: JSON string array with chunk information
|
|
444
|
+
*
|
|
445
|
+
* @returns Record of DynamoDB attribute values for chunking metadata
|
|
446
|
+
*/
|
|
447
|
+
preprocessingMetadata() {
|
|
448
|
+
if (!this.bedrockDocumentProcessingProps.enableChunking) {
|
|
449
|
+
return {};
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
ChunkingEnabled: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('States.Format(\'{}\', $.chunkingResult.requiresChunking)')),
|
|
453
|
+
ChunkingStrategy: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.chunkingResult.strategy')),
|
|
454
|
+
TokenAnalysis: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.chunkingResult.tokenAnalysis'))),
|
|
455
|
+
ChunkMetadata: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.chunkingResult.chunks'))),
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Creates the processing workflow with conditional branching for chunked documents.
|
|
460
|
+
*
|
|
461
|
+
* When chunking is enabled, creates a Choice State that:
|
|
462
|
+
* - Routes to chunked processing flow if document was chunked
|
|
463
|
+
* - Routes to standard processing flow if document was not chunked
|
|
464
|
+
*
|
|
465
|
+
* When chunking is disabled, returns the standard processing workflow.
|
|
466
|
+
*
|
|
467
|
+
* @returns Step Functions chain for processing the document
|
|
468
|
+
*/
|
|
469
|
+
createProcessingWorkflow() {
|
|
470
|
+
// If chunking is not enabled, use standard workflow
|
|
471
|
+
if (!this.bedrockDocumentProcessingProps.enableChunking) {
|
|
472
|
+
return this.createStandardProcessingWorkflow();
|
|
473
|
+
}
|
|
474
|
+
// Create Choice State to check if chunking was applied
|
|
475
|
+
const choiceState = new aws_stepfunctions_1.Choice(this, 'CheckIfChunked');
|
|
476
|
+
choiceState
|
|
477
|
+
.when(aws_stepfunctions_1.Condition.booleanEquals('$.chunkingResult.requiresChunking', true), this.createChunkedProcessingFlow())
|
|
478
|
+
.otherwise(
|
|
479
|
+
// Pass 'Standard' prefix to avoid construct ID collisions with chunked flow
|
|
480
|
+
this.createStandardProcessingWorkflow('Standard'));
|
|
481
|
+
return choiceState;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Creates the chunked processing flow for large documents.
|
|
485
|
+
*
|
|
486
|
+
* This flow:
|
|
487
|
+
* 1. Uses a Map State to process each chunk in parallel (or sequentially)
|
|
488
|
+
* 2. Each chunk goes through classification and processing
|
|
489
|
+
* 3. Results are aggregated using the aggregation Lambda
|
|
490
|
+
* 4. DynamoDB is updated with the aggregated result
|
|
491
|
+
* 5. Temporary chunks are cleaned up from S3
|
|
492
|
+
*
|
|
493
|
+
* @returns Step Functions chain for chunked document processing
|
|
494
|
+
*/
|
|
495
|
+
createChunkedProcessingFlow() {
|
|
496
|
+
const chunkingConfig = this.bedrockDocumentProcessingProps.chunkingConfig || {};
|
|
497
|
+
const maxConcurrency = chunkingConfig.processingMode === 'sequential'
|
|
498
|
+
? 1
|
|
499
|
+
: (chunkingConfig.maxConcurrency || 10);
|
|
500
|
+
// Create Map State for processing chunks
|
|
501
|
+
const mapState = new aws_stepfunctions_1.Map(this, 'ProcessChunks', {
|
|
502
|
+
itemsPath: '$.chunkingResult.chunks',
|
|
503
|
+
maxConcurrency,
|
|
504
|
+
parameters: {
|
|
505
|
+
'documentId.$': '$.documentId',
|
|
506
|
+
'chunk.$': '$$.Map.Item.Value',
|
|
507
|
+
'chunkIndex.$': '$$.Map.Item.Index',
|
|
508
|
+
'totalChunks.$': 'States.ArrayLength($.chunkingResult.chunks)',
|
|
509
|
+
// Override content to point to the chunk PDF, not the original document
|
|
510
|
+
'content': {
|
|
511
|
+
'location': 's3',
|
|
512
|
+
'bucket.$': '$$.Map.Item.Value.bucket',
|
|
513
|
+
'key.$': '$$.Map.Item.Value.key',
|
|
514
|
+
'filename.$': '$.content.filename',
|
|
515
|
+
},
|
|
516
|
+
'contentType.$': '$.contentType',
|
|
517
|
+
},
|
|
518
|
+
resultPath: '$.chunkResults',
|
|
519
|
+
});
|
|
520
|
+
// Define per-chunk processing: classification → processing
|
|
521
|
+
const chunkClassification = this.classificationStep();
|
|
522
|
+
const chunkProcessing = this.processingStep();
|
|
523
|
+
mapState.itemProcessor(chunkClassification.next(chunkProcessing));
|
|
524
|
+
// Create aggregation step (Lambda invoke only, normalization added separately)
|
|
525
|
+
const aggregationLambdaStep = this.createAggregationStep();
|
|
526
|
+
// Add a Pass state to normalize the aggregated result for downstream compatibility
|
|
527
|
+
// This copies aggregatedResult to processingResult so enrichment/post-processing
|
|
528
|
+
// see a consistent structure regardless of whether chunking was used
|
|
529
|
+
const normalizeState = new aws_stepfunctions_1.Pass(this, 'NormalizeAggregatedResult', {
|
|
530
|
+
parameters: {
|
|
531
|
+
'documentId.$': '$.documentId',
|
|
532
|
+
'contentType.$': '$.contentType',
|
|
533
|
+
'content.$': '$.content',
|
|
534
|
+
'chunkingResult.$': '$.chunkingResult',
|
|
535
|
+
'chunkResults.$': '$.chunkResults',
|
|
536
|
+
'aggregatedResult.$': '$.aggregatedResult',
|
|
537
|
+
// Copy aggregated result to processingResult for downstream compatibility
|
|
538
|
+
'processingResult': {
|
|
539
|
+
'result.$': '$.aggregatedResult.result',
|
|
540
|
+
},
|
|
541
|
+
// Also set classificationResult from the first successful chunk for consistency
|
|
542
|
+
'classificationResult.$': '$.chunkResults[0].classificationResult',
|
|
543
|
+
},
|
|
544
|
+
});
|
|
545
|
+
// Create DynamoDB update step for aggregated result
|
|
546
|
+
const updateAggregatedResultStep = this.createUpdateAggregatedResultStep();
|
|
547
|
+
// Create cleanup step
|
|
548
|
+
const cleanupStep = this.createCleanupStep();
|
|
549
|
+
// Create move to processed chain with 'Chunked' prefix to avoid ID collisions
|
|
550
|
+
const moveToProcessed = this.ingressAdapter.createSuccessChain(this, 'Chunked');
|
|
551
|
+
// Create error handler for aggregation failures
|
|
552
|
+
const aggregationErrorHandler = this.createAggregationErrorHandler();
|
|
553
|
+
// Get optional enrichment and post-processing steps
|
|
554
|
+
const enrichmentStep = this.enrichmentStep();
|
|
555
|
+
const postProcessingStep = this.postProcessingStep();
|
|
556
|
+
// Build the final chain after aggregation
|
|
557
|
+
// Chain: Map State → Aggregation → DynamoDB Update → [Enrichment] → [PostProcessing] → Cleanup → Move to Processed
|
|
558
|
+
let finalChain = cleanupStep
|
|
559
|
+
.addRetry({
|
|
560
|
+
errors: ['Lambda.ServiceException', 'Lambda.TooManyRequestsException'],
|
|
561
|
+
interval: aws_cdk_lib_1.Duration.seconds(2),
|
|
562
|
+
maxAttempts: 3,
|
|
563
|
+
backoffRate: 2,
|
|
564
|
+
})
|
|
565
|
+
.next(moveToProcessed);
|
|
566
|
+
// Add post-processing if provided (insert before cleanup)
|
|
567
|
+
if (postProcessingStep) {
|
|
568
|
+
const postProcessingErrorHandler = new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ChunkedPostProcessingFailDDBUpdate', {
|
|
569
|
+
table: this.documentProcessingTable,
|
|
570
|
+
key: {
|
|
571
|
+
DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
|
|
572
|
+
},
|
|
573
|
+
updateExpression: 'SET WorkflowStatus = :newStatus',
|
|
574
|
+
expressionAttributeValues: {
|
|
575
|
+
':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('post-processing-failure'),
|
|
576
|
+
},
|
|
577
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
578
|
+
}).next(this.ingressAdapter.createFailedChain(this, 'ChunkedPostProc'));
|
|
579
|
+
finalChain = postProcessingStep
|
|
580
|
+
.addCatch(postProcessingErrorHandler, {
|
|
581
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
582
|
+
})
|
|
583
|
+
.next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ChunkedPostProcessingSuccessUpdate', {
|
|
584
|
+
table: this.documentProcessingTable,
|
|
585
|
+
key: {
|
|
586
|
+
DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
|
|
587
|
+
},
|
|
588
|
+
updateExpression: 'SET WorkflowStatus = :newStatus, PostProcessingResult = :postProcessingResult',
|
|
589
|
+
expressionAttributeValues: {
|
|
590
|
+
':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('post-processing-complete'),
|
|
591
|
+
':postProcessingResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.postProcessedResult'))),
|
|
592
|
+
},
|
|
593
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
594
|
+
}).next(finalChain));
|
|
595
|
+
}
|
|
596
|
+
// Add enrichment if provided (insert before post-processing or cleanup)
|
|
597
|
+
if (enrichmentStep) {
|
|
598
|
+
const enrichmentErrorHandler = new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ChunkedEnrichmentFailDDBUpdate', {
|
|
599
|
+
table: this.documentProcessingTable,
|
|
600
|
+
key: {
|
|
601
|
+
DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
|
|
602
|
+
},
|
|
603
|
+
updateExpression: 'SET WorkflowStatus = :newStatus',
|
|
604
|
+
expressionAttributeValues: {
|
|
605
|
+
':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('enrichment-failure'),
|
|
606
|
+
},
|
|
607
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
608
|
+
}).next(this.ingressAdapter.createFailedChain(this, 'ChunkedEnrich'));
|
|
609
|
+
finalChain = enrichmentStep
|
|
610
|
+
.addCatch(enrichmentErrorHandler, {
|
|
611
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
612
|
+
})
|
|
613
|
+
.next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ChunkedEnrichmentSuccessUpdate', {
|
|
614
|
+
table: this.documentProcessingTable,
|
|
615
|
+
key: {
|
|
616
|
+
DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
|
|
617
|
+
},
|
|
618
|
+
updateExpression: 'SET WorkflowStatus = :newStatus, EnrichmentResult = :enrichmentResult',
|
|
619
|
+
expressionAttributeValues: {
|
|
620
|
+
':newStatus': postProcessingStep
|
|
621
|
+
? aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('enrichment-complete')
|
|
622
|
+
: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('complete'),
|
|
623
|
+
':enrichmentResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.enrichedResult'))),
|
|
624
|
+
},
|
|
625
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
626
|
+
}).next(finalChain));
|
|
627
|
+
}
|
|
628
|
+
// Chain: Map State → Aggregation → Normalize → DynamoDB Update → [Enrichment] → [PostProcessing] → Cleanup → Move to Processed
|
|
629
|
+
return mapState
|
|
630
|
+
.addCatch(aggregationErrorHandler, {
|
|
631
|
+
resultPath: '$.error',
|
|
632
|
+
})
|
|
633
|
+
.next(aggregationLambdaStep
|
|
634
|
+
.addCatch(aggregationErrorHandler, {
|
|
635
|
+
resultPath: '$.error',
|
|
636
|
+
})
|
|
637
|
+
.addRetry({
|
|
638
|
+
errors: ['Lambda.ServiceException', 'Lambda.TooManyRequestsException'],
|
|
639
|
+
interval: aws_cdk_lib_1.Duration.seconds(2),
|
|
640
|
+
maxAttempts: 3,
|
|
641
|
+
backoffRate: 2,
|
|
642
|
+
})
|
|
643
|
+
.next(normalizeState.next(updateAggregatedResultStep
|
|
644
|
+
.addRetry({
|
|
645
|
+
errors: ['DynamoDB.ProvisionedThroughputExceededException'],
|
|
646
|
+
interval: aws_cdk_lib_1.Duration.seconds(1),
|
|
647
|
+
maxAttempts: 3,
|
|
648
|
+
backoffRate: 2,
|
|
649
|
+
})
|
|
650
|
+
.next(finalChain))));
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Creates the aggregation step for combining chunk results using Bedrock.
|
|
654
|
+
*
|
|
655
|
+
* Uses the same Bedrock invoke Lambda pattern as the processing step but with
|
|
656
|
+
* a different prompt designed for aggregating multiple chunk results.
|
|
657
|
+
* The chunk processing results are passed as text data to the model.
|
|
658
|
+
*
|
|
659
|
+
* @returns LambdaInvoke task for result aggregation
|
|
660
|
+
*/
|
|
661
|
+
createAggregationStep() {
|
|
662
|
+
// Create Lambda function only once (reuses bedrock-invoke pattern)
|
|
663
|
+
if (!this._aggregationFunction) {
|
|
664
|
+
const prompt = this.bedrockDocumentProcessingProps.aggregationPrompt || BedrockDocumentProcessing.DEFAULT_AGGREGATION_PROMPT;
|
|
665
|
+
const adjustedModelId = bedrock_1.BedrockModelUtils.deriveActualModelId(this.bedrockDocumentProcessingProps.processingBedrockModel);
|
|
666
|
+
const role = this.generateLambdaRoleForBedrock('AggregationLambdaRole', this.bedrockDocumentProcessingProps.processingBedrockModel);
|
|
667
|
+
const { region, account } = aws_cdk_lib_1.Stack.of(this);
|
|
668
|
+
const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
|
|
669
|
+
account,
|
|
670
|
+
functionName: 'bedrock-idp-aggregation',
|
|
671
|
+
region,
|
|
672
|
+
scope: this,
|
|
673
|
+
enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
|
|
674
|
+
});
|
|
675
|
+
this.encryptionKey.grantEncryptDecrypt(role);
|
|
676
|
+
this._aggregationFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'BedrockAggregationFunction', {
|
|
677
|
+
functionName: generatedLogPermissions.uniqueFunctionName,
|
|
678
|
+
architecture: aws_lambda_1.Architecture.X86_64,
|
|
679
|
+
runtime: framework_1.DefaultRuntimes.PYTHON,
|
|
680
|
+
entry: path.join(__dirname, 'resources/default-bedrock-invoke'),
|
|
681
|
+
role,
|
|
682
|
+
memorySize: 1024,
|
|
683
|
+
timeout: this.bedrockDocumentProcessingProps.stepTimeouts || aws_cdk_lib_1.Duration.minutes(5),
|
|
684
|
+
environment: {
|
|
685
|
+
MODEL_ID: adjustedModelId,
|
|
686
|
+
PROMPT: prompt,
|
|
687
|
+
INVOKE_TYPE: 'aggregation',
|
|
688
|
+
INVOKE_MAX_TOKENS: '64000', // Aggregation may need more tokens for merged output
|
|
689
|
+
...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
|
|
690
|
+
},
|
|
691
|
+
environmentEncryption: this.encryptionKey,
|
|
692
|
+
vpc: this.bedrockDocumentProcessingProps.network
|
|
693
|
+
? this.bedrockDocumentProcessingProps.network.vpc
|
|
694
|
+
: undefined,
|
|
695
|
+
vpcSubnets: this.bedrockDocumentProcessingProps.network
|
|
696
|
+
? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
|
|
697
|
+
: undefined,
|
|
698
|
+
});
|
|
699
|
+
for (const statement of generatedLogPermissions.policyStatements) {
|
|
700
|
+
this._aggregationFunction.role?.addToPrincipalPolicy(statement);
|
|
701
|
+
}
|
|
702
|
+
if (this.bedrockDocumentProcessingProps.network) {
|
|
703
|
+
this._aggregationFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
// Always create a new LambdaInvoke task to allow proper state chaining
|
|
707
|
+
const stepId = `AggregationStep-${this._aggregationStepCounter}`;
|
|
708
|
+
this._aggregationStepCounter++;
|
|
709
|
+
// Pass chunk results as data content - the Lambda will format them for Bedrock
|
|
710
|
+
return new aws_stepfunctions_tasks_1.LambdaInvoke(this, stepId, {
|
|
711
|
+
lambdaFunction: this._aggregationFunction,
|
|
712
|
+
payload: aws_stepfunctions_1.TaskInput.fromObject({
|
|
713
|
+
'documentId.$': '$.documentId',
|
|
714
|
+
'contentType': 'data',
|
|
715
|
+
'content': {
|
|
716
|
+
// Pass the chunk results as JSON string for the Lambda to process
|
|
717
|
+
'data.$': 'States.JsonToString($.chunkResults)',
|
|
718
|
+
},
|
|
719
|
+
}),
|
|
720
|
+
// Store in both aggregatedResult AND processingResult for consistency with non-chunked flow
|
|
721
|
+
// This allows enrichment/post-processing steps to use $.processingResult regardless of chunking
|
|
722
|
+
resultPath: '$.aggregatedResult',
|
|
723
|
+
resultSelector: {
|
|
724
|
+
'result.$': '$.Payload.result',
|
|
725
|
+
},
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Creates the DynamoDB update step for storing aggregated results.
|
|
730
|
+
*
|
|
731
|
+
* Updates the document record with:
|
|
732
|
+
* - AggregatedResult: JSON string with classification, entities, and summary
|
|
733
|
+
* - WorkflowStatus: 'complete'
|
|
734
|
+
*
|
|
735
|
+
* @returns DynamoUpdateItem task for storing aggregated results
|
|
736
|
+
*/
|
|
737
|
+
createUpdateAggregatedResultStep() {
|
|
738
|
+
return new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'StoreAggregatedResult', {
|
|
739
|
+
table: this.documentProcessingTable,
|
|
740
|
+
key: {
|
|
741
|
+
DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
|
|
742
|
+
},
|
|
743
|
+
updateExpression: 'SET AggregatedResult = :result, WorkflowStatus = :status',
|
|
744
|
+
expressionAttributeValues: {
|
|
745
|
+
':result': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.aggregatedResult'))),
|
|
746
|
+
':status': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('complete'),
|
|
747
|
+
},
|
|
748
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Creates the cleanup Lambda step for removing temporary chunk files.
|
|
753
|
+
*
|
|
754
|
+
* The cleanup Lambda:
|
|
755
|
+
* - Deletes all chunk files from S3 chunks/ prefix
|
|
756
|
+
* - Uses batch delete for efficiency (up to 1000 objects per request)
|
|
757
|
+
* - Logs errors but doesn't fail the workflow
|
|
758
|
+
*
|
|
759
|
+
* @returns LambdaInvoke task for chunk cleanup
|
|
760
|
+
*/
|
|
761
|
+
createCleanupStep() {
|
|
762
|
+
// Create Lambda function only once
|
|
763
|
+
if (!this._cleanupFunction) {
|
|
764
|
+
const { region, account } = aws_cdk_lib_1.Stack.of(this);
|
|
765
|
+
const role = new aws_iam_1.Role(this, 'CleanupLambdaRole', {
|
|
766
|
+
assumedBy: new aws_iam_1.ServicePrincipal('lambda.amazonaws.com'),
|
|
767
|
+
inlinePolicies: {
|
|
768
|
+
CleanupPolicy: new aws_iam_1.PolicyDocument({
|
|
769
|
+
statements: [
|
|
770
|
+
// S3 access for deleting chunks only - least privilege
|
|
771
|
+
...this.ingressAdapter.generateAdapterIAMPolicies(['s3:DeleteObject'], true),
|
|
772
|
+
],
|
|
773
|
+
}),
|
|
774
|
+
},
|
|
775
|
+
});
|
|
776
|
+
const generatedLogPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
|
|
777
|
+
account,
|
|
778
|
+
functionName: 'bedrock-idp-cleanup',
|
|
779
|
+
region,
|
|
780
|
+
scope: this,
|
|
781
|
+
enableObservability: this.bedrockDocumentProcessingProps.enableObservability,
|
|
782
|
+
});
|
|
783
|
+
this.encryptionKey.grantEncryptDecrypt(role);
|
|
784
|
+
this._cleanupFunction = new aws_lambda_python_alpha_1.PythonFunction(this, 'CleanupFunction', {
|
|
785
|
+
functionName: generatedLogPermissions.uniqueFunctionName,
|
|
786
|
+
entry: path.join(__dirname, 'resources/cleanup'),
|
|
787
|
+
index: 'handler.py',
|
|
788
|
+
handler: 'handler',
|
|
789
|
+
runtime: framework_1.DefaultRuntimes.PYTHON,
|
|
790
|
+
architecture: aws_lambda_1.Architecture.X86_64,
|
|
791
|
+
role,
|
|
792
|
+
memorySize: 512,
|
|
793
|
+
timeout: aws_cdk_lib_1.Duration.minutes(5),
|
|
794
|
+
environment: {
|
|
795
|
+
...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.bedrockDocumentProcessingProps.enableObservability, this.metricNamespace, this.metricServiceName),
|
|
796
|
+
},
|
|
797
|
+
environmentEncryption: this.encryptionKey,
|
|
798
|
+
vpc: this.bedrockDocumentProcessingProps.network
|
|
799
|
+
? this.bedrockDocumentProcessingProps.network.vpc
|
|
800
|
+
: undefined,
|
|
801
|
+
vpcSubnets: this.bedrockDocumentProcessingProps.network
|
|
802
|
+
? this.bedrockDocumentProcessingProps.network.applicationSubnetSelection()
|
|
803
|
+
: undefined,
|
|
804
|
+
});
|
|
805
|
+
for (const statement of generatedLogPermissions.policyStatements) {
|
|
806
|
+
this._cleanupFunction.role?.addToPrincipalPolicy(statement);
|
|
807
|
+
}
|
|
808
|
+
if (this.bedrockDocumentProcessingProps.network) {
|
|
809
|
+
this._cleanupFunction.role?.addToPrincipalPolicy(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return new aws_stepfunctions_tasks_1.LambdaInvoke(this, 'CleanupChunks', {
|
|
813
|
+
lambdaFunction: this._cleanupFunction,
|
|
814
|
+
payload: aws_stepfunctions_1.TaskInput.fromObject({
|
|
815
|
+
'documentId.$': '$.documentId',
|
|
816
|
+
'chunks.$': '$.chunkingResult.chunks',
|
|
817
|
+
}),
|
|
818
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Creates the error handler for aggregation failures.
|
|
823
|
+
*
|
|
824
|
+
* When aggregation fails:
|
|
825
|
+
* - Updates DynamoDB with 'aggregation-failure' status
|
|
826
|
+
* - Moves document to failed/ prefix
|
|
827
|
+
*
|
|
828
|
+
* @returns Step Functions chain for handling aggregation errors
|
|
829
|
+
*/
|
|
830
|
+
createAggregationErrorHandler() {
|
|
831
|
+
const updateFailureStatus = new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'AggregationFailDDBUpdate', {
|
|
832
|
+
table: this.documentProcessingTable,
|
|
833
|
+
key: {
|
|
834
|
+
DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
|
|
835
|
+
},
|
|
836
|
+
updateExpression: 'SET WorkflowStatus = :newStatus',
|
|
837
|
+
expressionAttributeValues: {
|
|
838
|
+
':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('aggregation-failure'),
|
|
839
|
+
},
|
|
840
|
+
resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
|
|
841
|
+
});
|
|
842
|
+
// Use 'Chunked' prefix to avoid ID collisions with standard workflow
|
|
843
|
+
const moveToFailed = this.ingressAdapter.createFailedChain(this, 'Chunked');
|
|
844
|
+
return updateFailureStatus.next(moveToFailed);
|
|
845
|
+
}
|
|
228
846
|
}
|
|
229
847
|
exports.BedrockDocumentProcessing = BedrockDocumentProcessing;
|
|
230
848
|
_a = JSII_RTTI_SYMBOL_1;
|
|
231
|
-
BedrockDocumentProcessing[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BedrockDocumentProcessing", version: "1.
|
|
849
|
+
BedrockDocumentProcessing[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BedrockDocumentProcessing", version: "1.6.0" };
|
|
232
850
|
BedrockDocumentProcessing.DEFAULT_CLASSIFICATION_PROMPT = `
|
|
233
851
|
Analyze the document below, and classify the type of document it is (eg. INVOICE, IDENTITY_DOCUMENT, RECEIPT, etc). The result should be in JSON and should follow the following structure (only respond in JSON with the following structure and do not use markdown to indicate the json, just output plain old json with nothing else):
|
|
234
852
|
|
|
@@ -258,4 +876,26 @@ BedrockDocumentProcessing.DEFAULT_PROCESSING_PROMPT = `
|
|
|
258
876
|
Attached document is as follows:
|
|
259
877
|
|
|
260
878
|
`;
|
|
261
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdXNlLWNhc2VzL2RvY3VtZW50LXByb2Nlc3NpbmcvYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUV0Qyw2QkFBNkI7QUFDN0IsOEVBQWtFO0FBQ2xFLDZDQUE4QztBQUM5QyxpREFBcUU7QUFDckUsaURBQTZFO0FBQzdFLHVEQUFnRTtBQUVoRSxpRkFBbUU7QUFFbkUseUVBQTZIO0FBQzdILDRDQUErQztBQUMvQyxrREFBNEU7QUFDNUUsNENBQThDO0FBQzlDLG9GQUFnRjtBQTZDaEY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0FBQ0gsTUFBYSx5QkFBMEIsU0FBUSxpREFBc0I7SUFxQ25FOzs7Ozs7Ozs7O09BVUc7SUFDSCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXFDO1FBQzdFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hCLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsY0FBYyxFQUFFLHdDQUE4QixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzVGLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsc0JBQXNCLEVBQUUsd0NBQThCLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDOUcsQ0FBQztRQUVELElBQUksQ0FBQyw4QkFBOEIsR0FBRyxLQUFLLENBQUM7UUFDNUMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsMEJBQTBCLENBQUMsc0NBQXNDLENBQUMsQ0FBQztJQUM5RixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDTyxrQkFBa0I7UUFDMUIsTUFBTSxNQUFNLEdBQUcs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ZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IFB5dGhvbkZ1bmN0aW9uIH0gZnJvbSAnQGF3cy1jZGsvYXdzLWxhbWJkYS1weXRob24tYWxwaGEnO1xuaW1wb3J0IHsgRHVyYXRpb24sIFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgeyBSb2xlLCBTZXJ2aWNlUHJpbmNpcGFsLCBQb2xpY3lEb2N1bWVudCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgRnVuY3Rpb24sIEFyY2hpdGVjdHVyZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgU3RhdGVNYWNoaW5lIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMnO1xuaW1wb3J0IHsgTGFtYmRhSW52b2tlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMtdGFza3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nLCBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMsIERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIH0gZnJvbSAnLi9iYXNlLWRvY3VtZW50LXByb2Nlc3NpbmcnO1xuaW1wb3J0IHsgRGVmYXVsdFJ1bnRpbWVzIH0gZnJvbSAnLi4vZnJhbWV3b3JrJztcbmltcG9ydCB7IEJlZHJvY2tNb2RlbFByb3BzLCBCZWRyb2NrTW9kZWxVdGlscyB9IGZyb20gJy4uL2ZyYW1ld29yay9iZWRyb2NrJztcbmltcG9ydCB7IExhbWJkYUlhbVV0aWxzIH0gZnJvbSAnLi4vdXRpbGl0aWVzJztcbmltcG9ydCB7IFBvd2VydG9vbHNDb25maWcgfSBmcm9tICcuLi91dGlsaXRpZXMvb2JzZXJ2YWJpbGl0eS9wb3dlcnRvb2xzLWNvbmZpZyc7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIGZvciBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nIGNvbnN0cnVjdC5cbiAqIEV4dGVuZHMgQmFzZURvY3VtZW50UHJvY2Vzc2luZ1Byb3BzIHdpdGggQmVkcm9jay1zcGVjaWZpYyBvcHRpb25zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcyBleHRlbmRzIEJhc2VEb2N1bWVudFByb2Nlc3NpbmdQcm9wcyB7XG4gIC8qKlxuICAgKiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWwgZm9yIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uIHN0ZXAuXG4gICAqL1xuICByZWFkb25seSBjbGFzc2lmaWNhdGlvbkJlZHJvY2tNb2RlbD86IEJlZHJvY2tNb2RlbFByb3BzO1xuXG4gIC8qKlxuICAgKiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWwgZm9yIGRvY3VtZW50IGV4dHJhY3Rpb24gc3RlcC5cbiAgICovXG4gIHJlYWRvbmx5IHByb2Nlc3NpbmdCZWRyb2NrTW9kZWw/OiBCZWRyb2NrTW9kZWxQcm9wcztcbiAgLyoqXG4gICAqIEN1c3RvbSBwcm9tcHQgdGVtcGxhdGUgZm9yIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uLlxuICAgKiBNdXN0IGluY2x1ZGUgcGxhY2Vob2xkZXIgZm9yIGRvY3VtZW50IGNvbnRlbnQuXG4gICAqIEBkZWZhdWx0IERFRkFVTFRfQ0xBU1NJRklDQVRJT05fUFJPTVBUXG4gICAqL1xuICByZWFkb25seSBjbGFzc2lmaWNhdGlvblByb21wdD86IHN0cmluZztcbiAgLyoqXG4gICAqIEN1c3RvbSBwcm9tcHQgdGVtcGxhdGUgZm9yIGRvY3VtZW50IGV4dHJhY3Rpb24uXG4gICAqIE11c3QgaW5jbHVkZSBwbGFjZWhvbGRlciBmb3IgZG9jdW1lbnQgY29udGVudCBhbmQgY2xhc3NpZmljYXRpb24gcmVzdWx0LlxuICAgKiBAZGVmYXVsdCBERUZBVUxUX0VYVFJBQ1RJT05fUFJPTVBUXG4gICAqL1xuICByZWFkb25seSBwcm9jZXNzaW5nUHJvbXB0Pzogc3RyaW5nO1xuICAvKipcbiAgICogT3B0aW9uYWwgTGFtYmRhIGZ1bmN0aW9uIGZvciBkb2N1bWVudCBlbnJpY2htZW50IHN0ZXAuXG4gICAqIElmIHByb3ZpZGVkLCB3aWxsIGJlIGludm9rZWQgYWZ0ZXIgZXh0cmFjdGlvbiB3aXRoIHdvcmtmbG93IHN0YXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgZW5yaWNobWVudExhbWJkYUZ1bmN0aW9uPzogRnVuY3Rpb247XG4gIC8qKlxuICAgKiBPcHRpb25hbCBMYW1iZGEgZnVuY3Rpb24gZm9yIHBvc3QtcHJvY2Vzc2luZyBzdGVwLlxuICAgKiBJZiBwcm92aWRlZCwgd2lsbCBiZSBpbnZva2VkIGFmdGVyIGVucmljaG1lbnQgd2l0aCB3b3JrZmxvdyBzdGF0ZS5cbiAgICovXG4gIHJlYWRvbmx5IHBvc3RQcm9jZXNzaW5nTGFtYmRhRnVuY3Rpb24/OiBGdW5jdGlvbjtcbiAgLyoqXG4gICAqIFRpbWVvdXQgZm9yIGluZGl2aWR1YWwgU3RlcCBGdW5jdGlvbnMgdGFza3MgKGNsYXNzaWZpY2F0aW9uLCBleHRyYWN0aW9uLCBldGMuKS5cbiAgICogQGRlZmF1bHQgRHVyYXRpb24ubWludXRlcyg1KVxuICAgKi9cbiAgcmVhZG9ubHkgc3RlcFRpbWVvdXRzPzogRHVyYXRpb247XG59XG5cbi8qKlxuICogRG9jdW1lbnQgcHJvY2Vzc2luZyB3b3JrZmxvdyBwb3dlcmVkIGJ5IEFtYXpvbiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWxzLlxuICpcbiAqIEV4dGVuZHMgQmFzZURvY3VtZW50UHJvY2Vzc2luZyB0byBwcm92aWRlIEFJLXBvd2VyZWQgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24gYW5kIGV4dHJhY3Rpb25cbiAqIHVzaW5nIEFtYXpvbiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWxzLiBUaGlzIGltcGxlbWVudGF0aW9uIG9mZmVyczpcbiAqXG4gKiAjIyBLZXkgRmVhdHVyZXNcbiAqIC0gKipBSS1Qb3dlcmVkIENsYXNzaWZpY2F0aW9uKio6IFVzZXMgQ2xhdWRlIDMuNyBTb25uZXQgKGNvbmZpZ3VyYWJsZSkgdG8gY2xhc3NpZnkgZG9jdW1lbnQgdHlwZXNcbiAqIC0gKipJbnRlbGxpZ2VudCBFeHRyYWN0aW9uKio6IEV4dHJhY3RzIHN0cnVjdHVyZWQgZGF0YSBmcm9tIGRvY3VtZW50cyB1c2luZyBmb3VuZGF0aW9uIG1vZGVsc1xuICogLSAqKkNyb3NzLVJlZ2lvbiBJbmZlcmVuY2UqKjogT3B0aW9uYWwgc3VwcG9ydCBmb3IgaW1wcm92ZWQgYXZhaWxhYmlsaXR5IHZpYSBpbmZlcmVuY2UgcHJvZmlsZXNcbiAqIC0gKipGbGV4aWJsZSBQcm9jZXNzaW5nKio6IE9wdGlvbmFsIGVucmljaG1lbnQgYW5kIHBvc3QtcHJvY2Vzc2luZyBMYW1iZGEgZnVuY3Rpb25zXG4gKiAtICoqQ29zdCBPcHRpbWl6ZWQqKjogQ29uZmlndXJhYmxlIHRpbWVvdXRzIGFuZCBtb2RlbCBzZWxlY3Rpb24gZm9yIGNvc3QgY29udHJvbFxuICpcbiAqICMjIFByb2Nlc3NpbmcgV29ya2Zsb3dcbiAqIFMzIFVwbG9hZCDihpIgQ2xhc3NpZmljYXRpb24gKEJlZHJvY2spIOKGkiBFeHRyYWN0aW9uIChCZWRyb2NrKSDihpIgW0VucmljaG1lbnRdIOKGkiBbUG9zdC1Qcm9jZXNzaW5nXSDihpIgUmVzdWx0c1xuICpcbiAqICMjIERlZmF1bHQgTW9kZWxzXG4gKiAtIENsYXNzaWZpY2F0aW9uOiBDbGF1ZGUgMy43IFNvbm5ldCAoYW50aHJvcGljLmNsYXVkZS0zLTctc29ubmV0LTIwMjUwMjE5LXYxOjApXG4gKiAtIEV4dHJhY3Rpb246IENsYXVkZSAzLjcgU29ubmV0IChhbnRocm9waWMuY2xhdWRlLTMtNy1zb25uZXQtMjAyNTAyMTktdjE6MClcbiAqXG4gKiAjIyBQcm9tcHQgVGVtcGxhdGVzXG4gKiBUaGUgY29uc3RydWN0IHVzZXMgZGVmYXVsdCBwcm9tcHRzIHRoYXQgY2FuIGJlIGN1c3RvbWl6ZWQ6XG4gKiAtICoqQ2xhc3NpZmljYXRpb24qKjogQW5hbHl6ZXMgZG9jdW1lbnQgYW5kIHJldHVybnMgSlNPTiB3aXRoIGRvY3VtZW50Q2xhc3NpZmljYXRpb24gZmllbGRcbiAqIC0gKipFeHRyYWN0aW9uKio6IFVzZXMgY2xhc3NpZmljYXRpb24gcmVzdWx0IHRvIGV4dHJhY3QgZW50aXRpZXMgaW4gc3RydWN0dXJlZCBKU09OIGZvcm1hdFxuICpcbiAqICMjIENyb3NzLVJlZ2lvbiBJbmZlcmVuY2VcbiAqIFdoZW4gZW5hYmxlZCwgdXNlcyBCZWRyb2NrIGluZmVyZW5jZSBwcm9maWxlcyBmb3IgaW1wcm92ZWQgYXZhaWxhYmlsaXR5OlxuICogLSBVUyBwcmVmaXg6IFJvdXRlcyB0byBVUy1iYXNlZCByZWdpb25zIGZvciBsb3dlciBsYXRlbmN5XG4gKiAtIEVVIHByZWZpeDogUm91dGVzIHRvIEVVLWJhc2VkIHJlZ2lvbnMgZm9yIGRhdGEgcmVzaWRlbmN5IGNvbXBsaWFuY2VcbiAqL1xuZXhwb3J0IGNsYXNzIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcgZXh0ZW5kcyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nIHtcbiAgcHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0NMQVNTSUZJQ0FUSU9OX1BST01QVCA9IGBcbiAgQW5hbHl6ZSB0aGUgZG9jdW1lbnQgYmVsb3csIGFuZCBjbGFzc2lmeSB0aGUgdHlwZSBvZiBkb2N1bWVudCBpdCBpcyAoZWcuIElOVk9JQ0UsIElERU5USVRZX0RPQ1VNRU5ULCBSRUNFSVBULCBldGMpLiBUaGUgcmVzdWx0IHNob3VsZCBiZSBpbiBKU09OIGFuZCBzaG91bGQgZm9sbG93IHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGFuZCBkbyBub3QgdXNlIG1hcmtkb3duIHRvIGluZGljYXRlIHRoZSBqc29uLCBqdXN0IG91dHB1dCBwbGFpbiBvbGQganNvbiB3aXRoIG5vdGhpbmcgZWxzZSk6XG5cbiAge1xuICAgICAgZG9jdW1lbnRDbGFzc2lmaWNhdGlvbjogPENMQVNTSUZJQ0FUSU9OPlxuICB9XG5cbiAgQXR0YWNoZWQgZG9jdW1lbnQgaXMgYXMgZm9sbG93czpcblxuICBgO1xuXG4gIHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9QUk9DRVNTSU5HX1BST01QVCA9IGBcbiAgVGhlIGRvY3VtZW50IGJlbG93IGhhcyBiZWVuIGNsYXNzaWZpZWQgYXMgW0FDVFVBTF9DTEFTU0lGSUNBVElPTl0uIEV4dHJhY3QgaW1wb3J0YW50IGVudGl0aWVzIGZyb20gdGhlIGRvY3VtZW50IGFuZCByZXR1cm4gdGhlIHJlc3VsdCBhcyBKU09OIGZvbGxvd2luZyB0aGUgc3RydWN0dXJlIGJlbG93IChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGFuZCBkbyBub3QgdXNlIG1hcmtkb3duIHRvIGluZGljYXRlIHRoZSBqc29uLCBqdXN0IG91dHB1dCBwbGFpbiBvbGQganNvbiB3aXRoIG5vdGhpbmcgZWxzZSk6XG5cbiAge1xuICAgICAgZG9jdW1lbnRDbGFzc2lmaWNhdGlvbjogPENMQVNTSUZJQ0FUSU9OPixcbiAgICAgIHJlc3VsdDoge1xuICAgICAgICBlbnRpdGllczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6IDxUWVBFIE9GIEVOVElUWT5cbiAgICAgICAgICAgICAgICB2YWx1ZTogPFZBTFVFIE9GIEVOVElUWT5cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAuLi5cbiAgICAgICAgXVxuICAgICAgfVxuICB9XG5cbiAgQXR0YWNoZWQgZG9jdW1lbnQgaXMgYXMgZm9sbG93czpcblxuICBgO1xuXG4gIC8qKiBDb25maWd1cmF0aW9uIHByb3BlcnRpZXMgc3BlY2lmaWMgdG8gQmVkcm9jayBkb2N1bWVudCBwcm9jZXNzaW5nICovXG4gIHByb3RlY3RlZCByZWFkb25seSBiZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHM6IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcztcbiAgLyoqIFRoZSBTdGVwIEZ1bmN0aW9ucyBzdGF0ZSBtYWNoaW5lIHRoYXQgb3JjaGVzdHJhdGVzIHRoZSBkb2N1bWVudCBwcm9jZXNzaW5nIHdvcmtmbG93ICovXG4gIHJlYWRvbmx5IHN0YXRlTWFjaGluZTogU3RhdGVNYWNoaW5lO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcgY29uc3RydWN0LlxuICAgKlxuICAgKiBJbml0aWFsaXplcyB0aGUgQmVkcm9jay1wb3dlcmVkIGRvY3VtZW50IHByb2Nlc3NpbmcgcGlwZWxpbmUgd2l0aCBBSSBjbGFzc2lmaWNhdGlvblxuICAgKiBhbmQgZXh0cmFjdGlvbiBjYXBhYmlsaXRpZXMuIENyZWF0ZXMgTGFtYmRhIGZ1bmN0aW9ucyB3aXRoIGFwcHJvcHJpYXRlIElBTSByb2xlc1xuICAgKiBmb3IgQmVkcm9jayBtb2RlbCBpbnZvY2F0aW9uIGFuZCBTMyBhY2Nlc3MuXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSAtIFRoZSBzY29wZSBpbiB3aGljaCB0byBkZWZpbmUgdGhpcyBjb25zdHJ1Y3RcbiAgICogQHBhcmFtIGlkIC0gVGhlIHNjb3BlZCBjb25zdHJ1Y3QgSUQuIE11c3QgYmUgdW5pcXVlIHdpdGhpbiB0aGUgc2NvcGUuXG4gICAqIEBwYXJhbSBwcm9wcyAtIENvbmZpZ3VyYXRpb24gcHJvcGVydGllcyBmb3IgdGhlIEJlZHJvY2sgZG9jdW1lbnQgcHJvY2Vzc2luZyBwaXBlbGluZVxuICAgKi9cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwgcHJvcHMpO1xuICAgIGlmIChwcm9wcy5uZXR3b3JrKSB7XG4gICAgICBwcm9wcy5uZXR3b3JrLmNyZWF0ZVNlcnZpY2VFbmRwb2ludCgndnBjZS1iZWRyb2NrJywgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlLkJFRFJPQ0spO1xuICAgICAgcHJvcHMubmV0d29yay5jcmVhdGVTZXJ2aWNlRW5kcG9pbnQoJ3ZwY2UtYmVkcm9jay1ydW50aW1lJywgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlLkJFRFJPQ0tfUlVOVElNRSk7XG4gICAgfVxuXG4gICAgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMgPSBwcm9wcztcbiAgICB0aGlzLnN0YXRlTWFjaGluZSA9IHRoaXMuaGFuZGxlU3RhdGVNYWNoaW5lQ3JlYXRpb24oJ2JlZHJvY2stZG9jdW1lbnQtcHJvY2Vzc2luZy13b3JrZmxvdycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgdGhlIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uIHN0ZXAgdXNpbmcgQW1hem9uIEJlZHJvY2suXG4gICAqXG4gICAqIENyZWF0ZXMgYSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBjb25maWd1cmVkIEJlZHJvY2sgbW9kZWwgdG8gY2xhc3NpZnlcbiAgICogdGhlIGRvY3VtZW50IHR5cGUuIFRoZSBmdW5jdGlvbiByZWFkcyB0aGUgZG9jdW1lbnQgZnJvbSBTMyBhbmQgc2VuZHMgaXQgdG9cbiAgICogQmVkcm9jayB3aXRoIHRoZSBjbGFzc2lmaWNhdGlvbiBwcm9tcHQuXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGNvbmZpZ3VyZWQgZm9yIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgY2xhc3NpZmljYXRpb25TdGVwKCk6IERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIHtcbiAgICBjb25zdCBwcm9tcHQgPSB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5jbGFzc2lmaWNhdGlvblByb21wdCB8fCBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nLkRFRkFVTFRfQ0xBU1NJRklDQVRJT05fUFJPTVBUO1xuICAgIGNvbnN0IGFkanVzdGVkTW9kZWxJZCA9IEJlZHJvY2tNb2RlbFV0aWxzLmRlcml2ZUFjdHVhbE1vZGVsSWQodGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWwpO1xuICAgIGNvbnN0IHJvbGUgPSB0aGlzLmdlbmVyYXRlTGFtYmRhUm9sZUZvckJlZHJvY2soJ0NsYXNzaWZpY2F0aW9uTGFtYmRhUm9sZScsIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmNsYXNzaWZpY2F0aW9uQmVkcm9ja01vZGVsKTtcbiAgICBjb25zdCB7IHJlZ2lvbiwgYWNjb3VudCB9ID0gU3RhY2sub2YodGhpcyk7XG4gICAgY29uc3QgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMgPSBMYW1iZGFJYW1VdGlscy5jcmVhdGVMb2dzUGVybWlzc2lvbnMoe1xuICAgICAgYWNjb3VudCxcbiAgICAgIGZ1bmN0aW9uTmFtZTogJ2JlZHJvY2staWRwLWNsYXNzaWZpY2F0aW9uJyxcbiAgICAgIHJlZ2lvbixcbiAgICAgIHNjb3BlOiB0aGlzLFxuICAgICAgZW5hYmxlT2JzZXJ2YWJpbGl0eTogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICB9KTtcblxuICAgIHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KHJvbGUpO1xuXG4gICAgY29uc3QgYmVkcm9ja0Z1bmN0aW9uID0gbmV3IFB5dGhvbkZ1bmN0aW9uKHRoaXMsICdCZWRyb2NrQ2xhc3NpZmljYXRpb25GdW5jdGlvbicsIHtcbiAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgIGVudHJ5OiBwYXRoLmpvaW4oX19kaXJuYW1lLCAncmVzb3VyY2VzL2RlZmF1bHQtYmVkcm9jay1pbnZva2UnKSxcbiAgICAgIHJvbGUsXG4gICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICB0aW1lb3V0OiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5zdGVwVGltZW91dHMgfHwgRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIE1PREVMX0lEOiBhZGp1c3RlZE1vZGVsSWQsXG4gICAgICAgIFBST01QVDogcHJvbXB0LFxuICAgICAgICBJTlZPS0VfVFlQRTogJ2NsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgLi4uUG93ZXJ0b29sc0NvbmZpZy5nZW5lcmF0ZURlZmF1bHRMYW1iZGFDb25maWcoXG4gICAgICAgICAgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICAgICAgICB0aGlzLm1ldHJpY05hbWVzcGFjZSxcbiAgICAgICAgICB0aGlzLm1ldHJpY1NlcnZpY2VOYW1lLFxuICAgICAgICApLFxuICAgICAgfSxcbiAgICAgIGVudmlyb25tZW50RW5jcnlwdGlvbjogdGhpcy5lbmNyeXB0aW9uS2V5LFxuICAgICAgdnBjOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay52cGMgOiB1bmRlZmluZWQsXG4gICAgICB2cGNTdWJuZXRzOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay5hcHBsaWNhdGlvblN1Ym5ldFNlbGVjdGlvbigpIDogdW5kZWZpbmVkLFxuICAgIH0pO1xuXG4gICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMucG9saWN5U3RhdGVtZW50cykge1xuICAgICAgYmVkcm9ja0Z1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmspIHtcbiAgICAgIGJlZHJvY2tGdW5jdGlvbi5yb2xlPy5hZGRUb1ByaW5jaXBhbFBvbGljeShMYW1iZGFJYW1VdGlscy5nZW5lcmF0ZUxhbWJkYVZQQ1Blcm1pc3Npb25zKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsICdDbGFzc2lmaWNhdGlvblN0ZXAnLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogYmVkcm9ja0Z1bmN0aW9uLFxuICAgICAgcmVzdWx0UGF0aDogJyQuY2xhc3NpZmljYXRpb25SZXN1bHQnLFxuICAgICAgcmVzdWx0U2VsZWN0b3I6IHtcbiAgICAgICAgJ2RvY3VtZW50Q2xhc3NpZmljYXRpb24uJCc6ICckLlBheWxvYWQuZG9jdW1lbnRDbGFzc2lmaWNhdGlvbicsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgdGhlIGRvY3VtZW50IGV4dHJhY3Rpb24gc3RlcCB1c2luZyBBbWF6b24gQmVkcm9jay5cbiAgICpcbiAgICogQ3JlYXRlcyBhIExhbWJkYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgdGhlIGNvbmZpZ3VyZWQgQmVkcm9jayBtb2RlbCB0byBleHRyYWN0XG4gICAqIHN0cnVjdHVyZWQgZGF0YSBmcm9tIHRoZSBkb2N1bWVudC4gVXNlcyB0aGUgY2xhc3NpZmljYXRpb24gcmVzdWx0IGZyb20gdGhlXG4gICAqIHByZXZpb3VzIHN0ZXAgdG8gcHJvdmlkZSBjb250ZXh0IGZvciBtb3JlIGFjY3VyYXRlIGV4dHJhY3Rpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGNvbmZpZ3VyZWQgZm9yIGRvY3VtZW50IGV4dHJhY3Rpb25cbiAgICovXG4gIHByb3RlY3RlZCBwcm9jZXNzaW5nU3RlcCgpOiBEb2N1bWVudFByb2Nlc3NpbmdTdGVwVHlwZSB7XG4gICAgY29uc3QgcHJvbXB0ID0gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMucHJvY2Vzc2luZ1Byb21wdCB8fCBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nLkRFRkFVTFRfUFJPQ0VTU0lOR19QUk9NUFQ7XG4gICAgY29uc3QgYWRqdXN0ZWRNb2RlbElkID0gQmVkcm9ja01vZGVsVXRpbHMuZGVyaXZlQWN0dWFsTW9kZWxJZCh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wcm9jZXNzaW5nQmVkcm9ja01vZGVsKTtcbiAgICBjb25zdCByb2xlID0gdGhpcy5nZW5lcmF0ZUxhbWJkYVJvbGVGb3JCZWRyb2NrKCdQcm9jZXNzaW5nTGFtYmRhUm9sZScsIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLnByb2Nlc3NpbmdCZWRyb2NrTW9kZWwpO1xuICAgIGNvbnN0IHsgcmVnaW9uLCBhY2NvdW50IH0gPSBTdGFjay5vZih0aGlzKTtcblxuICAgIGNvbnN0IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zID0gTGFtYmRhSWFtVXRpbHMuY3JlYXRlTG9nc1Blcm1pc3Npb25zKHtcbiAgICAgIGFjY291bnQsXG4gICAgICBmdW5jdGlvbk5hbWU6ICdiZWRyb2NrLWlkcC1wcm9jZXNzaW5nJyxcbiAgICAgIHJlZ2lvbixcbiAgICAgIHNjb3BlOiB0aGlzLFxuICAgIH0pO1xuICAgIHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KHJvbGUpO1xuICAgIGNvbnN0IGJlZHJvY2tGdW5jdGlvbiA9IG5ldyBQeXRob25GdW5jdGlvbih0aGlzLCAnQmVkcm9ja0V4dHJhY3Rpb25GdW5jdGlvbicsIHtcbiAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgIGFyY2hpdGVjdHVyZTogQXJjaGl0ZWN0dXJlLlg4Nl82NCxcbiAgICAgIGVudHJ5OiBwYXRoLmpvaW4oX19kaXJuYW1lLCAncmVzb3VyY2VzL2RlZmF1bHQtYmVkcm9jay1pbnZva2UnKSxcbiAgICAgIHJvbGUsXG4gICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICB0aW1lb3V0OiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5zdGVwVGltZW91dHMgfHwgRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIE1PREVMX0lEOiBhZGp1c3RlZE1vZGVsSWQsXG4gICAgICAgIFBST01QVDogcHJvbXB0LFxuICAgICAgICBJTlZPS0VfVFlQRTogJ3Byb2Nlc3NpbmcnLFxuICAgICAgICAuLi5Qb3dlcnRvb2xzQ29uZmlnLmdlbmVyYXRlRGVmYXVsdExhbWJkYUNvbmZpZyhcbiAgICAgICAgICB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5lbmFibGVPYnNlcnZhYmlsaXR5LFxuICAgICAgICAgIHRoaXMubWV0cmljTmFtZXNwYWNlLFxuICAgICAgICAgIHRoaXMubWV0cmljU2VydmljZU5hbWUsXG4gICAgICAgICksXG4gICAgICB9LFxuICAgICAgZW52aXJvbm1lbnRFbmNyeXB0aW9uOiB0aGlzLmVuY3J5cHRpb25LZXksXG4gICAgICB2cGM6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsgPyB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrLnZwYyA6IHVuZGVmaW5lZCxcbiAgICAgIHZwY1N1Ym5ldHM6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsgPyB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrLmFwcGxpY2F0aW9uU3VibmV0U2VsZWN0aW9uKCkgOiB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiBnZW5lcmF0ZWRMb2dQZXJtaXNzaW9ucy5wb2xpY3lTdGF0ZW1lbnRzKSB7XG4gICAgICBiZWRyb2NrRnVuY3Rpb24ucm9sZT8uYWRkVG9QcmluY2lwYWxQb2xpY3koc3RhdGVtZW50KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yaykge1xuICAgICAgYmVkcm9ja0Z1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KExhbWJkYUlhbVV0aWxzLmdlbmVyYXRlTGFtYmRhVlBDUGVybWlzc2lvbnMoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgJ1Byb2Nlc3NpbmdTdGVwJywge1xuICAgICAgbGFtYmRhRnVuY3Rpb246IGJlZHJvY2tGdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLnByb2Nlc3NpbmdSZXN1bHQnLFxuICAgICAgcmVzdWx0U2VsZWN0b3I6IHtcbiAgICAgICAgJ2RvY3VtZW50Q2xhc3NpZmljYXRpb24uJCc6ICckLlBheWxvYWQuZG9jdW1lbnRDbGFzc2lmaWNhdGlvbicsXG4gICAgICAgICdyZXN1bHQuJCc6ICckLlBheWxvYWQucmVzdWx0JyxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2VuZXJhdGVMYW1iZGFSb2xlRm9yQmVkcm9jayhpZDogc3RyaW5nLCBtb2RlbD86IEJlZHJvY2tNb2RlbFByb3BzKSB7XG4gICAgcmV0dXJuIG5ldyBSb2xlKHRoaXMsIGlkLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgICAgaW5saW5lUG9saWNpZXM6IHtcbiAgICAgICAgQmVkcm9ja0ludm9rZVBvbGljeTogbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICAuLi50aGlzLmluZ3Jlc3NBZGFwdGVyLmdlbmVyYXRlQWRhcHRlcklBTVBvbGljaWVzKCksXG4gICAgICAgICAgICBCZWRyb2NrTW9kZWxVdGlscy5nZW5lcmF0ZU1vZGVsSUFNUGVybWlzc2lvbnModGhpcywgbW9kZWwpLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBsZW1lbnRzIHRoZSBvcHRpb25hbCBkb2N1bWVudCBlbnJpY2htZW50IHN0ZXAuXG4gICAqXG4gICAqIElmIGFuIGVucmljaG1lbnQgTGFtYmRhIGZ1bmN0aW9uIGlzIHByb3ZpZGVkIGluIHRoZSBwcm9wcywgY3JlYXRlcyBhIExhbWJkYUludm9rZVxuICAgKiB0YXNrIHRvIHBlcmZvcm0gYWRkaXRpb25hbCBwcm9jZXNzaW5nIG9uIHRoZSBleHRyYWN0ZWQgZGF0YS4gVGhpcyBzdGVwIGlzIHVzZWZ1bFxuICAgKiBmb3IgZGF0YSB2YWxpZGF0aW9uLCB0cmFuc2Zvcm1hdGlvbiwgb3IgaW50ZWdyYXRpb24gd2l0aCBleHRlcm5hbCBzeXN0ZW1zLlxuICAgKlxuICAgKiBAcmV0dXJucyBMYW1iZGFJbnZva2UgdGFzayBmb3IgZW5yaWNobWVudCwgb3IgdW5kZWZpbmVkIHRvIHNraXAgdGhpcyBzdGVwXG4gICAqL1xuICBwcm90ZWN0ZWQgZW5yaWNobWVudFN0ZXAoKTogRG9jdW1lbnRQcm9jZXNzaW5nU3RlcFR5cGUgfCB1bmRlZmluZWQge1xuICAgIGlmICghdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5yaWNobWVudExhbWJkYUZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsICdFbnJpY2htZW50U3RlcCcsIHtcbiAgICAgIGxhbWJkYUZ1bmN0aW9uOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5lbnJpY2htZW50TGFtYmRhRnVuY3Rpb24sXG4gICAgICByZXN1bHRQYXRoOiAnJC5lbnJpY2hlZFJlc3VsdCcsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50cyB0aGUgb3B0aW9uYWwgcG9zdC1wcm9jZXNzaW5nIHN0ZXAuXG4gICAqXG4gICAqIElmIGEgcG9zdC1wcm9jZXNzaW5nIExhbWJkYSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpbiB0aGUgcHJvcHMsIGNyZWF0ZXMgYSBMYW1iZGFJbnZva2VcbiAgICogdGFzayB0byBwZXJmb3JtIGZpbmFsIHByb2Nlc3Npbmcgb24gdGhlIHdvcmtmbG93IHJlc3VsdHMuIFRoaXMgc3RlcCBpcyB1c2VmdWwgZm9yXG4gICAqIGRhdGEgZm9ybWF0dGluZywgbm90aWZpY2F0aW9ucywgb3IgaW50ZWdyYXRpb24gd2l0aCBkb3duc3RyZWFtIHN5c3RlbXMuXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGZvciBwb3N0LXByb2Nlc3NpbmcsIG9yIHVuZGVmaW5lZCB0byBza2lwIHRoaXMgc3RlcFxuICAgKi9cbiAgcHJvdGVjdGVkIHBvc3RQcm9jZXNzaW5nU3RlcCgpOiBEb2N1bWVudFByb2Nlc3NpbmdTdGVwVHlwZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wb3N0UHJvY2Vzc2luZ0xhbWJkYUZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsICdQb3N0UHJvY2Vzc2luZ1N0ZXAnLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMucG9zdFByb2Nlc3NpbmdMYW1iZGFGdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLnBvc3RQcm9jZXNzZWRSZXN1bHQnLFxuICAgIH0pO1xuICB9XG59Il19
|
|
879
|
+
BedrockDocumentProcessing.DEFAULT_AGGREGATION_PROMPT = `
|
|
880
|
+
You are given the processing results from multiple chunks of a large document that was split for processing.
|
|
881
|
+
Your task is to synthesize these chunk results into a single, coherent final result.
|
|
882
|
+
|
|
883
|
+
Instructions:
|
|
884
|
+
1. Review all the chunk results provided below
|
|
885
|
+
2. Merge and deduplicate any overlapping information (chunks may have overlapping pages)
|
|
886
|
+
3. Synthesize the information into a unified, coherent result
|
|
887
|
+
4. Maintain the same output format as the individual chunk results
|
|
888
|
+
5. If the chunks contain summaries, create a comprehensive summary that covers all sections
|
|
889
|
+
6. If the chunks contain entities, deduplicate and consolidate them
|
|
890
|
+
7. Preserve important details from each chunk while avoiding redundancy
|
|
891
|
+
|
|
892
|
+
Return the result as JSON (only respond in JSON without markdown formatting):
|
|
893
|
+
|
|
894
|
+
{
|
|
895
|
+
"result": <SYNTHESIZED_RESULT>
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
The chunk results to aggregate are as follows:
|
|
899
|
+
|
|
900
|
+
`;
|
|
901
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdXNlLWNhc2VzL2RvY3VtZW50LXByb2Nlc3NpbmcvYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUV0Qyw2QkFBNkI7QUFDN0IsOEVBQWtFO0FBQ2xFLDZDQUE4QztBQUM5QyxpREFBcUU7QUFDckUsaURBQTZFO0FBQzdFLHVEQUFnRTtBQUNoRSxxRUFBOEc7QUFDOUcsaUZBQTJHO0FBRTNHLHlFQUE2SDtBQUU3SCw0Q0FBK0M7QUFDL0Msa0RBQTRFO0FBQzVFLDRDQUE4QztBQUM5QyxvRkFBZ0Y7QUFvSGhGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRztBQUNILE1BQWEseUJBQTBCLFNBQVEsaURBQXNCO0lBK0VuRTs7Ozs7Ozs7Ozs7T0FXRztJQUNILFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBcUM7UUFDN0UsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUE3QjFCLDREQUE0RDtRQUNwRCwrQkFBMEIsR0FBRyxDQUFDLENBQUM7UUFDdkMsd0RBQXdEO1FBQ2hELDJCQUFzQixHQUFHLENBQUMsQ0FBQztRQUduQyx5REFBeUQ7UUFDakQsNEJBQXVCLEdBQUcsQ0FBQyxDQUFDO1FBR3BDLHdEQUF3RDtRQUNoRCwyQkFBc0IsR0FBRyxDQUFDLENBQUM7UUFDbkMsNkRBQTZEO1FBQ3JELCtCQUEwQixHQUFHLENBQUMsQ0FBQztRQWtCckMsOENBQThDO1FBQzlDLElBQUksS0FBSyxDQUFDLGNBQWMsSUFBSSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDakQsSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNwRCxDQUFDO1FBRUQsSUFB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QUFtQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNoRCxDQUFDOztBQW4rQkgsOERBbytCQzs7O0FBbitCMkIsdURBQTZCLEdBQUc7Ozs7Ozs7OztHQVN6RCxBQVRzRCxDQVNyRDtBQUV3QixtREFBeUIsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JyRCxBQWxCa0QsQ0FrQmpEO0FBRXdCLG9EQUEwQixHQUFHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQnRELEFBckJtRCxDQXFCbEQiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBQeXRob25GdW5jdGlvbiB9IGZyb20gJ0Bhd3MtY2RrL2F3cy1sYW1iZGEtcHl0aG9uLWFscGhhJztcbmltcG9ydCB7IER1cmF0aW9uLCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IEludGVyZmFjZVZwY0VuZHBvaW50QXdzU2VydmljZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHsgUm9sZSwgU2VydmljZVByaW5jaXBhbCwgUG9saWN5RG9jdW1lbnQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IEZ1bmN0aW9uLCBBcmNoaXRlY3R1cmUgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IElDaGFpbmFibGUsIENob2ljZSwgQ29uZGl0aW9uLCBNYXAsIEpzb25QYXRoLCBUYXNrSW5wdXQsIFBhc3MgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3RlcGZ1bmN0aW9ucyc7XG5pbXBvcnQgeyBEeW5hbW9BdHRyaWJ1dGVWYWx1ZSwgRHluYW1vVXBkYXRlSXRlbSwgTGFtYmRhSW52b2tlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMtdGFza3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nLCBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMsIERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIH0gZnJvbSAnLi9iYXNlLWRvY3VtZW50LXByb2Nlc3NpbmcnO1xuaW1wb3J0IHsgQ2h1bmtpbmdDb25maWcgfSBmcm9tICcuL2NodW5raW5nLWNvbmZpZyc7XG5pbXBvcnQgeyBEZWZhdWx0UnVudGltZXMgfSBmcm9tICcuLi9mcmFtZXdvcmsnO1xuaW1wb3J0IHsgQmVkcm9ja01vZGVsUHJvcHMsIEJlZHJvY2tNb2RlbFV0aWxzIH0gZnJvbSAnLi4vZnJhbWV3b3JrL2JlZHJvY2snO1xuaW1wb3J0IHsgTGFtYmRhSWFtVXRpbHMgfSBmcm9tICcuLi91dGlsaXRpZXMnO1xuaW1wb3J0IHsgUG93ZXJ0b29sc0NvbmZpZyB9IGZyb20gJy4uL3V0aWxpdGllcy9vYnNlcnZhYmlsaXR5L3Bvd2VydG9vbHMtY29uZmlnJztcblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIHByb3BlcnRpZXMgZm9yIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcgY29uc3RydWN0LlxuICogRXh0ZW5kcyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMgd2l0aCBCZWRyb2NrLXNwZWNpZmljIG9wdGlvbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzIGV4dGVuZHMgQmFzZURvY3VtZW50UHJvY2Vzc2luZ1Byb3BzIHtcbiAgLyoqXG4gICAqIEJlZHJvY2sgZm91bmRhdGlvbiBtb2RlbCBmb3IgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24gc3RlcC5cbiAgICovXG4gIHJlYWRvbmx5IGNsYXNzaWZpY2F0aW9uQmVkcm9ja01vZGVsPzogQmVkcm9ja01vZGVsUHJvcHM7XG5cbiAgLyoqXG4gICAqIEJlZHJvY2sgZm91bmRhdGlvbiBtb2RlbCBmb3IgZG9jdW1lbnQgZXh0cmFjdGlvbiBzdGVwLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvY2Vzc2luZ0JlZHJvY2tNb2RlbD86IEJlZHJvY2tNb2RlbFByb3BzO1xuICAvKipcbiAgICogQ3VzdG9tIHByb21wdCB0ZW1wbGF0ZSBmb3IgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24uXG4gICAqIE11c3QgaW5jbHVkZSBwbGFjZWhvbGRlciBmb3IgZG9jdW1lbnQgY29udGVudC5cbiAgICogQGRlZmF1bHQgREVGQVVMVF9DTEFTU0lGSUNBVElPTl9QUk9NUFRcbiAgICovXG4gIHJlYWRvbmx5IGNsYXNzaWZpY2F0aW9uUHJvbXB0Pzogc3RyaW5nO1xuICAvKipcbiAgICogQ3VzdG9tIHByb21wdCB0ZW1wbGF0ZSBmb3IgZG9jdW1lbnQgZXh0cmFjdGlvbi5cbiAgICogTXVzdCBpbmNsdWRlIHBsYWNlaG9sZGVyIGZvciBkb2N1bWVudCBjb250ZW50IGFuZCBjbGFzc2lmaWNhdGlvbiByZXN1bHQuXG4gICAqIEBkZWZhdWx0IERFRkFVTFRfRVhUUkFDVElPTl9QUk9NUFRcbiAgICovXG4gIHJlYWRvbmx5IHByb2Nlc3NpbmdQcm9tcHQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBMYW1iZGEgZnVuY3Rpb24gZm9yIGRvY3VtZW50IGVucmljaG1lbnQgc3RlcC5cbiAgICogSWYgcHJvdmlkZWQsIHdpbGwgYmUgaW52b2tlZCBhZnRlciBleHRyYWN0aW9uIHdpdGggd29ya2Zsb3cgc3RhdGUuXG4gICAqL1xuICByZWFkb25seSBlbnJpY2htZW50TGFtYmRhRnVuY3Rpb24/OiBGdW5jdGlvbjtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIExhbWJkYSBmdW5jdGlvbiBmb3IgcG9zdC1wcm9jZXNzaW5nIHN0ZXAuXG4gICAqIElmIHByb3ZpZGVkLCB3aWxsIGJlIGludm9rZWQgYWZ0ZXIgZW5yaWNobWVudCB3aXRoIHdvcmtmbG93IHN0YXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9zdFByb2Nlc3NpbmdMYW1iZGFGdW5jdGlvbj86IEZ1bmN0aW9uO1xuICAvKipcbiAgICogVGltZW91dCBmb3IgaW5kaXZpZHVhbCBTdGVwIEZ1bmN0aW9ucyB0YXNrcyAoY2xhc3NpZmljYXRpb24sIGV4dHJhY3Rpb24sIGV0Yy4pLlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5taW51dGVzKDUpXG4gICAqL1xuICByZWFkb25seSBzdGVwVGltZW91dHM/OiBEdXJhdGlvbjtcblxuICAvKipcbiAgICogQ3VzdG9tIHByb21wdCB0ZW1wbGF0ZSBmb3IgYWdncmVnYXRpbmcgcmVzdWx0cyBmcm9tIG11bHRpcGxlIGNodW5rcy5cbiAgICogVXNlZCB3aGVuIGNodW5raW5nIGlzIGVuYWJsZWQgdG8gbWVyZ2UgcHJvY2Vzc2luZyByZXN1bHRzIGZyb20gYWxsIGNodW5rc1xuICAgKiBpbnRvIGEgc2luZ2xlIGNvaGVyZW50IHJlc3VsdC5cbiAgICpcbiAgICogVGhlIHByb21wdCByZWNlaXZlcyB0aGUgY29uY2F0ZW5hdGVkIHByb2Nlc3NpbmcgcmVzdWx0cyBmcm9tIGFsbCBjaHVua3NcbiAgICogYW5kIHNob3VsZCBpbnN0cnVjdCB0aGUgbW9kZWwgdG8gc3ludGhlc2l6ZSB0aGVtIGludG8gYSB1bmlmaWVkIG91dHB1dC5cbiAgICpcbiAgICogQGRlZmF1bHQgREVGQVVMVF9BR0dSRUdBVElPTl9QUk9NUFRcbiAgICovXG4gIHJlYWRvbmx5IGFnZ3JlZ2F0aW9uUHJvbXB0Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBFbmFibGUgUERGIGNodW5raW5nIGZvciBsYXJnZSBkb2N1bWVudHMuXG4gICAqXG4gICAqIFdoZW4gZW5hYmxlZCwgZG9jdW1lbnRzIGV4Y2VlZGluZyBjb25maWd1cmVkIHRocmVzaG9sZHMgd2lsbCBiZSBhdXRvbWF0aWNhbGx5XG4gICAqIHNwbGl0IGludG8gY2h1bmtzLCBwcm9jZXNzZWQgaW4gcGFyYWxsZWwgb3Igc2VxdWVudGlhbGx5LCBhbmQgcmVzdWx0cyBhZ2dyZWdhdGVkLlxuICAgKlxuICAgKiBUaGlzIGZlYXR1cmUgaXMgdXNlZnVsIGZvcjpcbiAgICogLSBQcm9jZXNzaW5nIGxhcmdlIFBERnMgKD4xMDAgcGFnZXMpXG4gICAqIC0gSGFuZGxpbmcgZG9jdW1lbnRzIHRoYXQgZXhjZWVkIEJlZHJvY2sgdG9rZW4gbGltaXRzICh+MjAwSyB0b2tlbnMpXG4gICAqIC0gSW1wcm92aW5nIHByb2Nlc3NpbmcgcmVsaWFiaWxpdHkgZm9yIGNvbXBsZXggZG9jdW1lbnRzXG4gICAqIC0gUHJvY2Vzc2luZyBkb2N1bWVudHMgd2l0aCB2YXJpYWJsZSBjb250ZW50IGRlbnNpdHlcbiAgICpcbiAgICogVGhlIGNodW5raW5nIHdvcmtmbG93OlxuICAgKiAxLiBBbmFseXplcyBQREYgdG8gZGV0ZXJtaW5lIHBhZ2UgY291bnQgYW5kIGVzdGltYXRlIHRva2VuIGNvdW50XG4gICAqIDIuIERlY2lkZXMgaWYgY2h1bmtpbmcgaXMgbmVlZGVkIGJhc2VkIG9uIGNvbmZpZ3VyZWQgdGhyZXNob2xkc1xuICAgKiAzLiBJZiBjaHVua2luZyBpcyBuZWVkZWQsIHNwbGl0cyBQREYgaW50byBjaHVua3MgYW5kIHVwbG9hZHMgdG8gUzNcbiAgICogNC4gUHJvY2Vzc2VzIGVhY2ggY2h1bmsgdGhyb3VnaCBjbGFzc2lmaWNhdGlvbiBhbmQgZXh0cmFjdGlvblxuICAgKiA1LiBBZ2dyZWdhdGVzIHJlc3VsdHMgdXNpbmcgbWFqb3JpdHkgdm90aW5nIGZvciBjbGFzc2lmaWNhdGlvblxuICAgKiA2LiBEZWR1cGxpY2F0ZXMgZW50aXRpZXMgYWNyb3NzIGNodW5rc1xuICAgKiA3LiBDbGVhbnMgdXAgdGVtcG9yYXJ5IGNodW5rIGZpbGVzIGZyb20gUzNcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZUNodW5raW5nPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ29uZmlndXJhdGlvbiBmb3IgUERGIGNodW5raW5nIGJlaGF2aW9yLlxuICAgKlxuICAgKiBPbmx5IGFwcGxpZXMgd2hlbiBgZW5hYmxlQ2h1bmtpbmdgIGlzIHRydWUuIEFsbG93cyBjdXN0b21pemF0aW9uIG9mOlxuICAgKiAtICoqQ2h1bmtpbmcgc3RyYXRlZ3kqKjogSG93IGRvY3VtZW50cyBhcmUgc3BsaXQgKGZpeGVkLXBhZ2VzLCB0b2tlbi1iYXNlZCwgb3IgaHlicmlkKVxuICAgKiAtICoqVGhyZXNob2xkcyoqOiBXaGVuIHRvIHRyaWdnZXIgY2h1bmtpbmcgYmFzZWQgb24gcGFnZSBjb3VudCBvciB0b2tlbiBjb3VudFxuICAgKiAtICoqQ2h1bmsgc2l6ZSBhbmQgb3ZlcmxhcCoqOiBDb250cm9sIGNodW5rIGJvdW5kYXJpZXMgYW5kIGNvbnRleHQgcHJlc2VydmF0aW9uXG4gICAqIC0gKipQcm9jZXNzaW5nIG1vZGUqKjogUGFyYWxsZWwgKGZhc3Rlcikgb3Igc2VxdWVudGlhbCAoY29zdC1vcHRpbWl6ZWQpXG4gICAqIC0gKipBZ2dyZWdhdGlvbiBzdHJhdGVneSoqOiBIb3cgdG8gY29tYmluZSByZXN1bHRzIGZyb20gbXVsdGlwbGUgY2h1bmtzXG4gICAqXG4gICAqICMjIERlZmF1bHQgQ29uZmlndXJhdGlvblxuICAgKlxuICAgKiBJZiBub3QgcHJvdmlkZWQsIHVzZXMgc2Vuc2libGUgZGVmYXVsdHMgb3B0aW1pemVkIGZvciBtb3N0IHVzZSBjYXNlczpcbiAgICogLSBTdHJhdGVneTogYCdoeWJyaWQnYCAocmVjb21tZW5kZWQgLSBiYWxhbmNlcyB0b2tlbiBhbmQgcGFnZSBsaW1pdHMpXG4gICAqIC0gUGFnZSB0aHJlc2hvbGQ6IDEwMCBwYWdlc1xuICAgKiAtIFRva2VuIHRocmVzaG9sZDogMTUwLDAwMCB0b2tlbnNcbiAgICogLSBQcm9jZXNzaW5nIG1vZGU6IGAncGFyYWxsZWwnYFxuICAgKiAtIE1heCBjb25jdXJyZW5jeTogMTBcbiAgICogLSBBZ2dyZWdhdGlvbiBzdHJhdGVneTogYCdtYWpvcml0eS12b3RlJ2BcbiAgICpcbiAgICogIyMgU3RyYXRlZ3kgQ29tcGFyaXNvblxuICAgKlxuICAgKiB8IFN0cmF0ZWd5IHwgQmVzdCBGb3IgfCBQcm9zIHwgQ29ucyB8XG4gICAqIHwtLS0tLS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tfC0tLS0tLXxcbiAgICogfCBgaHlicmlkYCB8IE1vc3QgZG9jdW1lbnRzIHwgQmFsYW5jZXMgdG9rZW4vcGFnZSBsaW1pdHMgfCBTbGlnaHRseSBtb3JlIGNvbXBsZXggfFxuICAgKiB8IGB0b2tlbi1iYXNlZGAgfCBWYXJpYWJsZSBkZW5zaXR5IHwgUmVzcGVjdHMgbW9kZWwgbGltaXRzIHwgU2xvd2VyIGFuYWx5c2lzIHxcbiAgICogfCBgZml4ZWQtcGFnZXNgIHwgVW5pZm9ybSBkZW5zaXR5IHwgU2ltcGxlLCBmYXN0IHwgTWF5IGV4Y2VlZCB0b2tlbiBsaW1pdHMgfFxuICAgKlxuICAgKiBAZGVmYXVsdCB1bmRlZmluZWQgKHVzZXMgZGVmYXVsdCBjb25maWd1cmF0aW9uIHdoZW4gZW5hYmxlQ2h1bmtpbmcgaXMgdHJ1ZSlcbiAgICpcbiAgICogQHNlZSB7QGxpbmsgQ2h1bmtpbmdDb25maWd9IGZvciBkZXRhaWxlZCBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IGNodW5raW5nQ29uZmlnPzogQ2h1bmtpbmdDb25maWc7XG59XG5cbi8qKlxuICogRG9jdW1lbnQgcHJvY2Vzc2luZyB3b3JrZmxvdyBwb3dlcmVkIGJ5IEFtYXpvbiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWxzLlxuICpcbiAqIEV4dGVuZHMgQmFzZURvY3VtZW50UHJvY2Vzc2luZyB0byBwcm92aWRlIEFJLXBvd2VyZWQgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24gYW5kIGV4dHJhY3Rpb25cbiAqIHVzaW5nIEFtYXpvbiBCZWRyb2NrIGZvdW5kYXRpb24gbW9kZWxzLiBUaGlzIGltcGxlbWVudGF0aW9uIG9mZmVyczpcbiAqXG4gKiAjIyBLZXkgRmVhdHVyZXNcbiAqIC0gKipBSS1Qb3dlcmVkIENsYXNzaWZpY2F0aW9uKio6IFVzZXMgQ2xhdWRlIDMuNyBTb25uZXQgKGNvbmZpZ3VyYWJsZSkgdG8gY2xhc3NpZnkgZG9jdW1lbnQgdHlwZXNcbiAqIC0gKipJbnRlbGxpZ2VudCBFeHRyYWN0aW9uKio6IEV4dHJhY3RzIHN0cnVjdHVyZWQgZGF0YSBmcm9tIGRvY3VtZW50cyB1c2luZyBmb3VuZGF0aW9uIG1vZGVsc1xuICogLSAqKkNyb3NzLVJlZ2lvbiBJbmZlcmVuY2UqKjogT3B0aW9uYWwgc3VwcG9ydCBmb3IgaW1wcm92ZWQgYXZhaWxhYmlsaXR5IHZpYSBpbmZlcmVuY2UgcHJvZmlsZXNcbiAqIC0gKipGbGV4aWJsZSBQcm9jZXNzaW5nKio6IE9wdGlvbmFsIGVucmljaG1lbnQgYW5kIHBvc3QtcHJvY2Vzc2luZyBMYW1iZGEgZnVuY3Rpb25zXG4gKiAtICoqQ29zdCBPcHRpbWl6ZWQqKjogQ29uZmlndXJhYmxlIHRpbWVvdXRzIGFuZCBtb2RlbCBzZWxlY3Rpb24gZm9yIGNvc3QgY29udHJvbFxuICpcbiAqICMjIFByb2Nlc3NpbmcgV29ya2Zsb3dcbiAqIFMzIFVwbG9hZCDihpIgQ2xhc3NpZmljYXRpb24gKEJlZHJvY2spIOKGkiBFeHRyYWN0aW9uIChCZWRyb2NrKSDihpIgW0VucmljaG1lbnRdIOKGkiBbUG9zdC1Qcm9jZXNzaW5nXSDihpIgUmVzdWx0c1xuICpcbiAqICMjIERlZmF1bHQgTW9kZWxzXG4gKiAtIENsYXNzaWZpY2F0aW9uOiBDbGF1ZGUgMy43IFNvbm5ldCAoYW50aHJvcGljLmNsYXVkZS0zLTctc29ubmV0LTIwMjUwMjE5LXYxOjApXG4gKiAtIEV4dHJhY3Rpb246IENsYXVkZSAzLjcgU29ubmV0IChhbnRocm9waWMuY2xhdWRlLTMtNy1zb25uZXQtMjAyNTAyMTktdjE6MClcbiAqXG4gKiAjIyBQcm9tcHQgVGVtcGxhdGVzXG4gKiBUaGUgY29uc3RydWN0IHVzZXMgZGVmYXVsdCBwcm9tcHRzIHRoYXQgY2FuIGJlIGN1c3RvbWl6ZWQ6XG4gKiAtICoqQ2xhc3NpZmljYXRpb24qKjogQW5hbHl6ZXMgZG9jdW1lbnQgYW5kIHJldHVybnMgSlNPTiB3aXRoIGRvY3VtZW50Q2xhc3NpZmljYXRpb24gZmllbGRcbiAqIC0gKipFeHRyYWN0aW9uKio6IFVzZXMgY2xhc3NpZmljYXRpb24gcmVzdWx0IHRvIGV4dHJhY3QgZW50aXRpZXMgaW4gc3RydWN0dXJlZCBKU09OIGZvcm1hdFxuICpcbiAqICMjIENyb3NzLVJlZ2lvbiBJbmZlcmVuY2VcbiAqIFdoZW4gZW5hYmxlZCwgdXNlcyBCZWRyb2NrIGluZmVyZW5jZSBwcm9maWxlcyBmb3IgaW1wcm92ZWQgYXZhaWxhYmlsaXR5OlxuICogLSBVUyBwcmVmaXg6IFJvdXRlcyB0byBVUy1iYXNlZCByZWdpb25zIGZvciBsb3dlciBsYXRlbmN5XG4gKiAtIEVVIHByZWZpeDogUm91dGVzIHRvIEVVLWJhc2VkIHJlZ2lvbnMgZm9yIGRhdGEgcmVzaWRlbmN5IGNvbXBsaWFuY2VcbiAqL1xuZXhwb3J0IGNsYXNzIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcgZXh0ZW5kcyBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nIHtcbiAgcHJvdGVjdGVkIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0NMQVNTSUZJQ0FUSU9OX1BST01QVCA9IGBcbiAgQW5hbHl6ZSB0aGUgZG9jdW1lbnQgYmVsb3csIGFuZCBjbGFzc2lmeSB0aGUgdHlwZSBvZiBkb2N1bWVudCBpdCBpcyAoZWcuIElOVk9JQ0UsIElERU5USVRZX0RPQ1VNRU5ULCBSRUNFSVBULCBldGMpLiBUaGUgcmVzdWx0IHNob3VsZCBiZSBpbiBKU09OIGFuZCBzaG91bGQgZm9sbG93IHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGFuZCBkbyBub3QgdXNlIG1hcmtkb3duIHRvIGluZGljYXRlIHRoZSBqc29uLCBqdXN0IG91dHB1dCBwbGFpbiBvbGQganNvbiB3aXRoIG5vdGhpbmcgZWxzZSk6XG5cbiAge1xuICAgICAgZG9jdW1lbnRDbGFzc2lmaWNhdGlvbjogPENMQVNTSUZJQ0FUSU9OPlxuICB9XG5cbiAgQXR0YWNoZWQgZG9jdW1lbnQgaXMgYXMgZm9sbG93czpcblxuICBgO1xuXG4gIHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9QUk9DRVNTSU5HX1BST01QVCA9IGBcbiAgVGhlIGRvY3VtZW50IGJlbG93IGhhcyBiZWVuIGNsYXNzaWZpZWQgYXMgW0FDVFVBTF9DTEFTU0lGSUNBVElPTl0uIEV4dHJhY3QgaW1wb3J0YW50IGVudGl0aWVzIGZyb20gdGhlIGRvY3VtZW50IGFuZCByZXR1cm4gdGhlIHJlc3VsdCBhcyBKU09OIGZvbGxvd2luZyB0aGUgc3RydWN0dXJlIGJlbG93IChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGFuZCBkbyBub3QgdXNlIG1hcmtkb3duIHRvIGluZGljYXRlIHRoZSBqc29uLCBqdXN0IG91dHB1dCBwbGFpbiBvbGQganNvbiB3aXRoIG5vdGhpbmcgZWxzZSk6XG5cbiAge1xuICAgICAgZG9jdW1lbnRDbGFzc2lmaWNhdGlvbjogPENMQVNTSUZJQ0FUSU9OPixcbiAgICAgIHJlc3VsdDoge1xuICAgICAgICBlbnRpdGllczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR5cGU6IDxUWVBFIE9GIEVOVElUWT5cbiAgICAgICAgICAgICAgICB2YWx1ZTogPFZBTFVFIE9GIEVOVElUWT5cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAuLi5cbiAgICAgICAgXVxuICAgICAgfVxuICB9XG5cbiAgQXR0YWNoZWQgZG9jdW1lbnQgaXMgYXMgZm9sbG93czpcblxuICBgO1xuXG4gIHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9BR0dSRUdBVElPTl9QUk9NUFQgPSBgXG4gIFlvdSBhcmUgZ2l2ZW4gdGhlIHByb2Nlc3NpbmcgcmVzdWx0cyBmcm9tIG11bHRpcGxlIGNodW5rcyBvZiBhIGxhcmdlIGRvY3VtZW50IHRoYXQgd2FzIHNwbGl0IGZvciBwcm9jZXNzaW5nLlxuICBZb3VyIHRhc2sgaXMgdG8gc3ludGhlc2l6ZSB0aGVzZSBjaHVuayByZXN1bHRzIGludG8gYSBzaW5nbGUsIGNvaGVyZW50IGZpbmFsIHJlc3VsdC5cblxuICBJbnN0cnVjdGlvbnM6XG4gIDEuIFJldmlldyBhbGwgdGhlIGNodW5rIHJlc3VsdHMgcHJvdmlkZWQgYmVsb3dcbiAgMi4gTWVyZ2UgYW5kIGRlZHVwbGljYXRlIGFueSBvdmVybGFwcGluZyBpbmZvcm1hdGlvbiAoY2h1bmtzIG1heSBoYXZlIG92ZXJsYXBwaW5nIHBhZ2VzKVxuICAzLiBTeW50aGVzaXplIHRoZSBpbmZvcm1hdGlvbiBpbnRvIGEgdW5pZmllZCwgY29oZXJlbnQgcmVzdWx0XG4gIDQuIE1haW50YWluIHRoZSBzYW1lIG91dHB1dCBmb3JtYXQgYXMgdGhlIGluZGl2aWR1YWwgY2h1bmsgcmVzdWx0c1xuICA1LiBJZiB0aGUgY2h1bmtzIGNvbnRhaW4gc3VtbWFyaWVzLCBjcmVhdGUgYSBjb21wcmVoZW5zaXZlIHN1bW1hcnkgdGhhdCBjb3ZlcnMgYWxsIHNlY3Rpb25zXG4gIDYuIElmIHRoZSBjaHVua3MgY29udGFpbiBlbnRpdGllcywgZGVkdXBsaWNhdGUgYW5kIGNvbnNvbGlkYXRlIHRoZW1cbiAgNy4gUHJlc2VydmUgaW1wb3J0YW50IGRldGFpbHMgZnJvbSBlYWNoIGNodW5rIHdoaWxlIGF2b2lkaW5nIHJlZHVuZGFuY3lcblxuICBSZXR1cm4gdGhlIHJlc3VsdCBhcyBKU09OIChvbmx5IHJlc3BvbmQgaW4gSlNPTiB3aXRob3V0IG1hcmtkb3duIGZvcm1hdHRpbmcpOlxuXG4gIHtcbiAgICAgIFwicmVzdWx0XCI6IDxTWU5USEVTSVpFRF9SRVNVTFQ+XG4gIH1cblxuICBUaGUgY2h1bmsgcmVzdWx0cyB0byBhZ2dyZWdhdGUgYXJlIGFzIGZvbGxvd3M6XG5cbiAgYDtcblxuICAvKiogQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIHNwZWNpZmljIHRvIEJlZHJvY2sgZG9jdW1lbnQgcHJvY2Vzc2luZyAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzOiBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHM7XG4gIC8qKiBUaGUgU3RlcCBGdW5jdGlvbnMgc3RhdGUgbWFjaGluZSB0aGF0IG9yY2hlc3RyYXRlcyB0aGUgZG9jdW1lbnQgcHJvY2Vzc2luZyB3b3JrZmxvdyAqL1xuICByZWFkb25seSBzdGF0ZU1hY2hpbmU7XG4gIC8qKiBDYWNoZWQgY2xhc3NpZmljYXRpb24gTGFtYmRhIGZ1bmN0aW9uIHRvIGF2b2lkIGR1cGxpY2F0ZSByZXNvdXJjZSBjcmVhdGlvbiAqL1xuICBwcml2YXRlIF9jbGFzc2lmaWNhdGlvbkZ1bmN0aW9uPzogRnVuY3Rpb247XG4gIC8qKiBDYWNoZWQgcHJvY2Vzc2luZyBMYW1iZGEgZnVuY3Rpb24gdG8gYXZvaWQgZHVwbGljYXRlIHJlc291cmNlIGNyZWF0aW9uICovXG4gIHByaXZhdGUgX3Byb2Nlc3NpbmdGdW5jdGlvbj86IEZ1bmN0aW9uO1xuICAvKiogQ291bnRlciBmb3IgZ2VuZXJhdGluZyB1bmlxdWUgY2xhc3NpZmljYXRpb24gc3RlcCBJRHMgKi9cbiAgcHJpdmF0ZSBfY2xhc3NpZmljYXRpb25TdGVwQ291bnRlciA9IDA7XG4gIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBwcm9jZXNzaW5nIHN0ZXAgSURzICovXG4gIHByaXZhdGUgX3Byb2Nlc3NpbmdTdGVwQ291bnRlciA9IDA7XG4gIC8qKiBDYWNoZWQgYWdncmVnYXRpb24gTGFtYmRhIGZ1bmN0aW9uIHRvIGF2b2lkIGR1cGxpY2F0ZSByZXNvdXJjZSBjcmVhdGlvbiAqL1xuICBwcml2YXRlIF9hZ2dyZWdhdGlvbkZ1bmN0aW9uPzogRnVuY3Rpb247XG4gIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBhZ2dyZWdhdGlvbiBzdGVwIElEcyAqL1xuICBwcml2YXRlIF9hZ2dyZWdhdGlvblN0ZXBDb3VudGVyID0gMDtcbiAgLyoqIENhY2hlZCBjbGVhbnVwIExhbWJkYSBmdW5jdGlvbiB0byBhdm9pZCBkdXBsaWNhdGUgcmVzb3VyY2UgY3JlYXRpb24gKi9cbiAgcHJpdmF0ZSBfY2xlYW51cEZ1bmN0aW9uPzogRnVuY3Rpb247XG4gIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBlbnJpY2htZW50IHN0ZXAgSURzICovXG4gIHByaXZhdGUgX2VucmljaG1lbnRTdGVwQ291bnRlciA9IDA7XG4gIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBwb3N0LXByb2Nlc3Npbmcgc3RlcCBJRHMgKi9cbiAgcHJpdmF0ZSBfcG9zdFByb2Nlc3NpbmdTdGVwQ291bnRlciA9IDA7XG5cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nIGNvbnN0cnVjdC5cbiAgICpcbiAgICogSW5pdGlhbGl6ZXMgdGhlIEJlZHJvY2stcG93ZXJlZCBkb2N1bWVudCBwcm9jZXNzaW5nIHBpcGVsaW5lIHdpdGggQUkgY2xhc3NpZmljYXRpb25cbiAgICogYW5kIGV4dHJhY3Rpb24gY2FwYWJpbGl0aWVzLiBDcmVhdGVzIExhbWJkYSBmdW5jdGlvbnMgd2l0aCBhcHByb3ByaWF0ZSBJQU0gcm9sZXNcbiAgICogZm9yIEJlZHJvY2sgbW9kZWwgaW52b2NhdGlvbiBhbmQgUzMgYWNjZXNzLlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgLSBUaGUgc2NvcGUgaW4gd2hpY2ggdG8gZGVmaW5lIHRoaXMgY29uc3RydWN0XG4gICAqIEBwYXJhbSBpZCAtIFRoZSBzY29wZWQgY29uc3RydWN0IElELiBNdXN0IGJlIHVuaXF1ZSB3aXRoaW4gdGhlIHNjb3BlLlxuICAgKiBAcGFyYW0gcHJvcHMgLSBDb25maWd1cmF0aW9uIHByb3BlcnRpZXMgZm9yIHRoZSBCZWRyb2NrIGRvY3VtZW50IHByb2Nlc3NpbmcgcGlwZWxpbmVcbiAgICogQHRocm93cyBFcnJvciBpZiBjaHVua2luZyBjb25maWd1cmF0aW9uIGlzIGludmFsaWRcbiAgICovXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcblxuICAgIC8vIFZhbGlkYXRlIGNodW5raW5nIGNvbmZpZ3VyYXRpb24gaWYgcHJvdmlkZWRcbiAgICBpZiAocHJvcHMuZW5hYmxlQ2h1bmtpbmcgJiYgcHJvcHMuY2h1bmtpbmdDb25maWcpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVDaHVua2luZ0NvbmZpZyhwcm9wcy5jaHVua2luZ0NvbmZpZyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLm5ldHdvcmspIHtcbiAgICAgIHByb3BzLm5ldHdvcmsuY3JlYXRlU2VydmljZUVuZHBvaW50KCd2cGNlLWJlZHJvY2snLCBJbnRlcmZhY2VWcGNFbmRwb2ludEF3c1NlcnZpY2UuQkVEUk9DSyk7XG4gICAgICBwcm9wcy5uZXR3b3JrLmNyZWF0ZVNlcnZpY2VFbmRwb2ludCgndnBjZS1iZWRyb2NrLXJ1bnRpbWUnLCBJbnRlcmZhY2VWcGNFbmRwb2ludEF3c1NlcnZpY2UuQkVEUk9DS19SVU5USU1FKTtcbiAgICB9XG5cbiAgICB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcyA9IHByb3BzO1xuICAgIHRoaXMuc3RhdGVNYWNoaW5lID0gdGhpcy5oYW5kbGVTdGF0ZU1hY2hpbmVDcmVhdGlvbignYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLXdvcmtmbG93Jyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBjaHVua2luZyBjb25maWd1cmF0aW9uIHBhcmFtZXRlcnMuXG4gICAqXG4gICAqIEVuc3VyZXMgdGhhdDpcbiAgICogLSBDaHVuayBzaXplIGlzIGdyZWF0ZXIgdGhhbiAwXG4gICAqIC0gT3ZlcmxhcCBpcyBub24tbmVnYXRpdmUgYW5kIGxlc3MgdGhhbiBjaHVuayBzaXplXG4gICAqIC0gVGhyZXNob2xkcyBhcmUgZ3JlYXRlciB0aGFuIDBcbiAgICogLSBNYXggY29uY3VycmVuY3kgaXMgZ3JlYXRlciB0aGFuIDBcbiAgICogLSBNaW4gc3VjY2VzcyB0aHJlc2hvbGQgaXMgYmV0d2VlbiAwIGFuZCAxXG4gICAqXG4gICAqIEBwYXJhbSBjb25maWcgLSBUaGUgY2h1bmtpbmcgY29uZmlndXJhdGlvbiB0byB2YWxpZGF0ZVxuICAgKiBAdGhyb3dzIEVycm9yIGlmIGFueSBjb25maWd1cmF0aW9uIHBhcmFtZXRlciBpcyBpbnZhbGlkXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlQ2h1bmtpbmdDb25maWcoY29uZmlnOiBDaHVua2luZ0NvbmZpZyk6IHZvaWQge1xuICAgIC8vIFZhbGlkYXRlIGNodW5rIHNpemUgKGZvciBmaXhlZC1wYWdlcyBzdHJhdGVneSlcbiAgICBpZiAoY29uZmlnLmNodW5rU2l6ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoY29uZmlnLmNodW5rU2l6ZSA8PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogY2h1bmtTaXplIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBvdmVybGFwIHBhZ2VzIChmb3IgZml4ZWQtcGFnZXMgc3RyYXRlZ3kpXG4gICAgaWYgKGNvbmZpZy5vdmVybGFwUGFnZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGNvbmZpZy5vdmVybGFwUGFnZXMgPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogb3ZlcmxhcFBhZ2VzIG11c3QgYmUgbm9uLW5lZ2F0aXZlJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBlZmZlY3RpdmVDaHVua1NpemUgPSBjb25maWcuY2h1bmtTaXplIHx8IDUwOyAvLyBkZWZhdWx0IGNodW5rIHNpemVcbiAgICAgIGlmIChjb25maWcub3ZlcmxhcFBhZ2VzID49IGVmZmVjdGl2ZUNodW5rU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG92ZXJsYXBQYWdlcyBtdXN0IGJlIGxlc3MgdGhhbiBjaHVua1NpemUnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBwYWdlIHRocmVzaG9sZFxuICAgIGlmIChjb25maWcucGFnZVRocmVzaG9sZCAhPT0gdW5kZWZpbmVkICYmIGNvbmZpZy5wYWdlVGhyZXNob2xkIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogcGFnZVRocmVzaG9sZCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgdG9rZW4gdGhyZXNob2xkXG4gICAgaWYgKGNvbmZpZy50b2tlblRocmVzaG9sZCAhPT0gdW5kZWZpbmVkICYmIGNvbmZpZy50b2tlblRocmVzaG9sZCA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IHRva2VuVGhyZXNob2xkIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBtYXggdG9rZW5zIHBlciBjaHVuayAoZm9yIHRva2VuLWJhc2VkIHN0cmF0ZWd5KVxuICAgIGlmIChjb25maWcubWF4VG9rZW5zUGVyQ2h1bmsgIT09IHVuZGVmaW5lZCAmJiBjb25maWcubWF4VG9rZW5zUGVyQ2h1bmsgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBtYXhUb2tlbnNQZXJDaHVuayBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgb3ZlcmxhcCB0b2tlbnMgKGZvciB0b2tlbi1iYXNlZCBhbmQgaHlicmlkIHN0cmF0ZWdpZXMpXG4gICAgaWYgKGNvbmZpZy5vdmVybGFwVG9rZW5zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChjb25maWcub3ZlcmxhcFRva2VucyA8IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBvdmVybGFwVG9rZW5zIG11c3QgYmUgbm9uLW5lZ2F0aXZlJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBlZmZlY3RpdmVNYXhUb2tlbnMgPSBjb25maWcubWF4VG9rZW5zUGVyQ2h1bmsgfHwgMTAwMDAwOyAvLyBkZWZhdWx0IG1heCB0b2tlbnNcbiAgICAgIGlmIChjb25maWcub3ZlcmxhcFRva2VucyA+PSBlZmZlY3RpdmVNYXhUb2tlbnMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBvdmVybGFwVG9rZW5zIG11c3QgYmUgbGVzcyB0aGFuIG1heFRva2Vuc1BlckNodW5rJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgbWF4IHBhZ2VzIHBlciBjaHVuayAoZm9yIGh5YnJpZCBzdHJhdGVneSlcbiAgICBpZiAoY29uZmlnLm1heFBhZ2VzUGVyQ2h1bmsgIT09IHVuZGVmaW5lZCAmJiBjb25maWcubWF4UGFnZXNQZXJDaHVuayA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG1heFBhZ2VzUGVyQ2h1bmsgbXVzdCBiZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXRlIHRhcmdldCB0b2tlbnMgcGVyIGNodW5rIChmb3IgaHlicmlkIHN0cmF0ZWd5KVxuICAgIGlmIChjb25maWcudGFyZ2V0VG9rZW5zUGVyQ2h1bmsgIT09IHVuZGVmaW5lZCAmJiBjb25maWcudGFyZ2V0VG9rZW5zUGVyQ2h1bmsgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiB0YXJnZXRUb2tlbnNQZXJDaHVuayBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgbWF4IGNvbmN1cnJlbmN5XG4gICAgaWYgKGNvbmZpZy5tYXhDb25jdXJyZW5jeSAhPT0gdW5kZWZpbmVkICYmIGNvbmZpZy5tYXhDb25jdXJyZW5jeSA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG1heENvbmN1cnJlbmN5IG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBtaW4gc3VjY2VzcyB0aHJlc2hvbGRcbiAgICBpZiAoY29uZmlnLm1pblN1Y2Nlc3NUaHJlc2hvbGQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGNvbmZpZy5taW5TdWNjZXNzVGhyZXNob2xkIDwgMCB8fCBjb25maWcubWluU3VjY2Vzc1RocmVzaG9sZCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBtaW5TdWNjZXNzVGhyZXNob2xkIG11c3QgYmUgYmV0d2VlbiAwIGFuZCAxJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgdGhlIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uIHN0ZXAgdXNpbmcgQW1hem9uIEJlZHJvY2suXG4gICAqXG4gICAqIENyZWF0ZXMgYSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBjb25maWd1cmVkIEJlZHJvY2sgbW9kZWwgdG8gY2xhc3NpZnlcbiAgICogdGhlIGRvY3VtZW50IHR5cGUuIFRoZSBmdW5jdGlvbiByZWFkcyB0aGUgZG9jdW1lbnQgZnJvbSBTMyBhbmQgc2VuZHMgaXQgdG9cbiAgICogQmVkcm9jayB3aXRoIHRoZSBjbGFzc2lmaWNhdGlvbiBwcm9tcHQuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGNhY2hlcyB0aGUgTGFtYmRhIGZ1bmN0aW9uIHRvIGF2b2lkIGNyZWF0aW5nIGR1cGxpY2F0ZSByZXNvdXJjZXMsXG4gICAqIGJ1dCBjcmVhdGVzIGEgbmV3IExhbWJkYUludm9rZSB0YXNrIGVhY2ggdGltZSB0byBhbGxvdyBwcm9wZXIgc3RhdGUgY2hhaW5pbmcuXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGNvbmZpZ3VyZWQgZm9yIGRvY3VtZW50IGNsYXNzaWZpY2F0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgY2xhc3NpZmljYXRpb25TdGVwKCk6IERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIHtcbiAgICAvLyBDcmVhdGUgTGFtYmRhIGZ1bmN0aW9uIG9ubHkgb25jZVxuICAgIGlmICghdGhpcy5fY2xhc3NpZmljYXRpb25GdW5jdGlvbikge1xuICAgICAgY29uc3QgcHJvbXB0ID0gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2xhc3NpZmljYXRpb25Qcm9tcHQgfHwgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZy5ERUZBVUxUX0NMQVNTSUZJQ0FUSU9OX1BST01QVDtcbiAgICAgIGNvbnN0IGFkanVzdGVkTW9kZWxJZCA9IEJlZHJvY2tNb2RlbFV0aWxzLmRlcml2ZUFjdHVhbE1vZGVsSWQodGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWwpO1xuICAgICAgY29uc3Qgcm9sZSA9IHRoaXMuZ2VuZXJhdGVMYW1iZGFSb2xlRm9yQmVkcm9jaygnQ2xhc3NpZmljYXRpb25MYW1iZGFSb2xlJywgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWwpO1xuICAgICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IFN0YWNrLm9mKHRoaXMpO1xuICAgICAgY29uc3QgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMgPSBMYW1iZGFJYW1VdGlscy5jcmVhdGVMb2dzUGVybWlzc2lvbnMoe1xuICAgICAgICBhY2NvdW50LFxuICAgICAgICBmdW5jdGlvbk5hbWU6ICdiZWRyb2NrLWlkcC1jbGFzc2lmaWNhdGlvbicsXG4gICAgICAgIHJlZ2lvbixcbiAgICAgICAgc2NvcGU6IHRoaXMsXG4gICAgICAgIGVuYWJsZU9ic2VydmFiaWxpdHk6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5LmdyYW50RW5jcnlwdERlY3J5cHQocm9sZSk7XG5cbiAgICAgIHRoaXMuX2NsYXNzaWZpY2F0aW9uRnVuY3Rpb24gPSBuZXcgUHl0aG9uRnVuY3Rpb24odGhpcywgJ0JlZHJvY2tDbGFzc2lmaWNhdGlvbkZ1bmN0aW9uJywge1xuICAgICAgICBmdW5jdGlvbk5hbWU6IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zLnVuaXF1ZUZ1bmN0aW9uTmFtZSxcbiAgICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgICBydW50aW1lOiBEZWZhdWx0UnVudGltZXMuUFlUSE9OLFxuICAgICAgICBlbnRyeTogcGF0aC5qb2luKF9fZGlybmFtZSwgJ3Jlc291cmNlcy9kZWZhdWx0LWJlZHJvY2staW52b2tlJyksXG4gICAgICAgIHJvbGUsXG4gICAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgdGltZW91dDogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuc3RlcFRpbWVvdXRzIHx8IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgTU9ERUxfSUQ6IGFkanVzdGVkTW9kZWxJZCxcbiAgICAgICAgICBQUk9NUFQ6IHByb21wdCxcbiAgICAgICAgICBJTlZPS0VfVFlQRTogJ2NsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgICAuLi5Qb3dlcnRvb2xzQ29uZmlnLmdlbmVyYXRlRGVmYXVsdExhbWJkYUNvbmZpZyhcbiAgICAgICAgICAgIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgICAgICAgICB0aGlzLm1ldHJpY05hbWVzcGFjZSxcbiAgICAgICAgICAgIHRoaXMubWV0cmljU2VydmljZU5hbWUsXG4gICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgZW52aXJvbm1lbnRFbmNyeXB0aW9uOiB0aGlzLmVuY3J5cHRpb25LZXksXG4gICAgICAgIHZwYzogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICAgID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay52cGNcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgdnBjU3VibmV0czogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICAgID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay5hcHBsaWNhdGlvblN1Ym5ldFNlbGVjdGlvbigpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICB9KTtcblxuICAgICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMucG9saWN5U3RhdGVtZW50cykge1xuICAgICAgICB0aGlzLl9jbGFzc2lmaWNhdGlvbkZ1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrKSB7XG4gICAgICAgIHRoaXMuX2NsYXNzaWZpY2F0aW9uRnVuY3Rpb24ucm9sZT8uYWRkVG9QcmluY2lwYWxQb2xpY3koTGFtYmRhSWFtVXRpbHMuZ2VuZXJhdGVMYW1iZGFWUENQZXJtaXNzaW9ucygpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbHdheXMgY3JlYXRlIGEgbmV3IExhbWJkYUludm9rZSB0YXNrIHRvIGFsbG93IHByb3BlciBzdGF0ZSBjaGFpbmluZ1xuICAgIGNvbnN0IHN0ZXBJZCA9IGBDbGFzc2lmaWNhdGlvblN0ZXAtJHt0aGlzLl9jbGFzc2lmaWNhdGlvblN0ZXBDb3VudGVyfWA7XG4gICAgdGhpcy5fY2xhc3NpZmljYXRpb25TdGVwQ291bnRlcisrO1xuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgc3RlcElkLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy5fY2xhc3NpZmljYXRpb25GdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLmNsYXNzaWZpY2F0aW9uUmVzdWx0JyxcbiAgICAgIHJlc3VsdFNlbGVjdG9yOiB7XG4gICAgICAgICdkb2N1bWVudENsYXNzaWZpY2F0aW9uLiQnOiAnJC5QYXlsb2FkLmRvY3VtZW50Q2xhc3NpZmljYXRpb24nLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBsZW1lbnRzIHRoZSBkb2N1bWVudCBleHRyYWN0aW9uIHN0ZXAgdXNpbmcgQW1hem9uIEJlZHJvY2suXG4gICAqXG4gICAqIENyZWF0ZXMgYSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBjb25maWd1cmVkIEJlZHJvY2sgbW9kZWwgdG8gZXh0cmFjdFxuICAgKiBzdHJ1Y3R1cmVkIGRhdGEgZnJvbSB0aGUgZG9jdW1lbnQuIFVzZXMgdGhlIGNsYXNzaWZpY2F0aW9uIHJlc3VsdCBmcm9tIHRoZVxuICAgKiBwcmV2aW91cyBzdGVwIHRvIHByb3ZpZGUgY29udGV4dCBmb3IgbW9yZSBhY2N1cmF0ZSBleHRyYWN0aW9uLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjYWNoZXMgdGhlIExhbWJkYSBmdW5jdGlvbiB0byBhdm9pZCBjcmVhdGluZyBkdXBsaWNhdGUgcmVzb3VyY2VzLFxuICAgKiBidXQgY3JlYXRlcyBhIG5ldyBMYW1iZGFJbnZva2UgdGFzayBlYWNoIHRpbWUgdG8gYWxsb3cgcHJvcGVyIHN0YXRlIGNoYWluaW5nLlxuICAgKlxuICAgKiBAcmV0dXJucyBMYW1iZGFJbnZva2UgdGFzayBjb25maWd1cmVkIGZvciBkb2N1bWVudCBleHRyYWN0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJvY2Vzc2luZ1N0ZXAoKTogRG9jdW1lbnRQcm9jZXNzaW5nU3RlcFR5cGUge1xuICAgIC8vIENyZWF0ZSBMYW1iZGEgZnVuY3Rpb24gb25seSBvbmNlXG4gICAgaWYgKCF0aGlzLl9wcm9jZXNzaW5nRnVuY3Rpb24pIHtcbiAgICAgIGNvbnN0IHByb21wdCA9IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLnByb2Nlc3NpbmdQcm9tcHQgfHwgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZy5ERUZBVUxUX1BST0NFU1NJTkdfUFJPTVBUO1xuICAgICAgY29uc3QgYWRqdXN0ZWRNb2RlbElkID0gQmVkcm9ja01vZGVsVXRpbHMuZGVyaXZlQWN0dWFsTW9kZWxJZCh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wcm9jZXNzaW5nQmVkcm9ja01vZGVsKTtcbiAgICAgIGNvbnN0IHJvbGUgPSB0aGlzLmdlbmVyYXRlTGFtYmRhUm9sZUZvckJlZHJvY2soJ1Byb2Nlc3NpbmdMYW1iZGFSb2xlJywgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMucHJvY2Vzc2luZ0JlZHJvY2tNb2RlbCk7XG4gICAgICBjb25zdCB7IHJlZ2lvbiwgYWNjb3VudCB9ID0gU3RhY2sub2YodGhpcyk7XG5cbiAgICAgIGNvbnN0IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zID0gTGFtYmRhSWFtVXRpbHMuY3JlYXRlTG9nc1Blcm1pc3Npb25zKHtcbiAgICAgICAgYWNjb3VudCxcbiAgICAgICAgZnVuY3Rpb25OYW1lOiAnYmVkcm9jay1pZHAtcHJvY2Vzc2luZycsXG4gICAgICAgIHJlZ2lvbixcbiAgICAgICAgc2NvcGU6IHRoaXMsXG4gICAgICB9KTtcbiAgICAgIHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KHJvbGUpO1xuICAgICAgdGhpcy5fcHJvY2Vzc2luZ0Z1bmN0aW9uID0gbmV3IFB5dGhvbkZ1bmN0aW9uKHRoaXMsICdCZWRyb2NrRXh0cmFjdGlvbkZ1bmN0aW9uJywge1xuICAgICAgICBmdW5jdGlvbk5hbWU6IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zLnVuaXF1ZUZ1bmN0aW9uTmFtZSxcbiAgICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgICBlbnRyeTogcGF0aC5qb2luKF9fZGlybmFtZSwgJ3Jlc291cmNlcy9kZWZhdWx0LWJlZHJvY2staW52b2tlJyksXG4gICAgICAgIHJvbGUsXG4gICAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgdGltZW91dDogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuc3RlcFRpbWVvdXRzIHx8IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgTU9ERUxfSUQ6IGFkanVzdGVkTW9kZWxJZCxcbiAgICAgICAgICBQUk9NUFQ6IHByb21wdCxcbiAgICAgICAgICBJTlZPS0VfVFlQRTogJ3Byb2Nlc3NpbmcnLFxuICAgICAgICAgIC4uLlBvd2VydG9vbHNDb25maWcuZ2VuZXJhdGVEZWZhdWx0TGFtYmRhQ29uZmlnKFxuICAgICAgICAgICAgdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICAgICAgICAgIHRoaXMubWV0cmljTmFtZXNwYWNlLFxuICAgICAgICAgICAgdGhpcy5tZXRyaWNTZXJ2aWNlTmFtZSxcbiAgICAgICAgICApLFxuICAgICAgICB9LFxuICAgICAgICBlbnZpcm9ubWVudEVuY3J5cHRpb246IHRoaXMuZW5jcnlwdGlvbktleSxcbiAgICAgICAgdnBjOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrXG4gICAgICAgICAgPyB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrLnZwY1xuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICB2cGNTdWJuZXRzOiB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrXG4gICAgICAgICAgPyB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrLmFwcGxpY2F0aW9uU3VibmV0U2VsZWN0aW9uKClcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIH0pO1xuXG4gICAgICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiBnZW5lcmF0ZWRMb2dQZXJtaXNzaW9ucy5wb2xpY3lTdGF0ZW1lbnRzKSB7XG4gICAgICAgIHRoaXMuX3Byb2Nlc3NpbmdGdW5jdGlvbi5yb2xlPy5hZGRUb1ByaW5jaXBhbFBvbGljeShzdGF0ZW1lbnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yaykge1xuICAgICAgICB0aGlzLl9wcm9jZXNzaW5nRnVuY3Rpb24ucm9sZT8uYWRkVG9QcmluY2lwYWxQb2xpY3koTGFtYmRhSWFtVXRpbHMuZ2VuZXJhdGVMYW1iZGFWUENQZXJtaXNzaW9ucygpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbHdheXMgY3JlYXRlIGEgbmV3IExhbWJkYUludm9rZSB0YXNrIHRvIGFsbG93IHByb3BlciBzdGF0ZSBjaGFpbmluZ1xuICAgIGNvbnN0IHN0ZXBJZCA9IGBQcm9jZXNzaW5nU3RlcC0ke3RoaXMuX3Byb2Nlc3NpbmdTdGVwQ291bnRlcn1gO1xuICAgIHRoaXMuX3Byb2Nlc3NpbmdTdGVwQ291bnRlcisrO1xuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgc3RlcElkLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy5fcHJvY2Vzc2luZ0Z1bmN0aW9uLFxuICAgICAgcmVzdWx0UGF0aDogJyQucHJvY2Vzc2luZ1Jlc3VsdCcsXG4gICAgICByZXN1bHRTZWxlY3Rvcjoge1xuICAgICAgICAnZG9jdW1lbnRDbGFzc2lmaWNhdGlvbi4kJzogJyQuUGF5bG9hZC5kb2N1bWVudENsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgJ3Jlc3VsdC4kJzogJyQuUGF5bG9hZC5yZXN1bHQnLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZW5lcmF0ZUxhbWJkYVJvbGVGb3JCZWRyb2NrKGlkOiBzdHJpbmcsIG1vZGVsPzogQmVkcm9ja01vZGVsUHJvcHMpIHtcbiAgICByZXR1cm4gbmV3IFJvbGUodGhpcywgaWQsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IFNlcnZpY2VQcmluY2lwYWwoJ2xhbWJkYS5hbWF6b25hd3MuY29tJyksXG4gICAgICBpbmxpbmVQb2xpY2llczoge1xuICAgICAgICBCZWRyb2NrSW52b2tlUG9saWN5OiBuZXcgUG9saWN5RG9jdW1lbnQoe1xuICAgICAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgICAgIC8vIFMzIHJlYWQtb25seSBhY2Nlc3MgZm9yIGRvY3VtZW50IHJldHJpZXZhbCAtIGxlYXN0IHByaXZpbGVnZVxuICAgICAgICAgICAgLi4udGhpcy5pbmdyZXNzQWRhcHRlci5nZW5lcmF0ZUFkYXB0ZXJJQU1Qb2xpY2llcygpLFxuICAgICAgICAgICAgQmVkcm9ja01vZGVsVXRpbHMuZ2VuZXJhdGVNb2RlbElBTVBlcm1pc3Npb25zKHRoaXMsIG1vZGVsKSxcbiAgICAgICAgICBdLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50cyB0aGUgb3B0aW9uYWwgZG9jdW1lbnQgZW5yaWNobWVudCBzdGVwLlxuICAgKlxuICAgKiBJZiBhbiBlbnJpY2htZW50IExhbWJkYSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpbiB0aGUgcHJvcHMsIGNyZWF0ZXMgYSBMYW1iZGFJbnZva2VcbiAgICogdGFzayB0byBwZXJmb3JtIGFkZGl0aW9uYWwgcHJvY2Vzc2luZyBvbiB0aGUgZXh0cmFjdGVkIGRhdGEuIFRoaXMgc3RlcCBpcyB1c2VmdWxcbiAgICogZm9yIGRhdGEgdmFsaWRhdGlvbiwgdHJhbnNmb3JtYXRpb24sIG9yIGludGVncmF0aW9uIHdpdGggZXh0ZXJuYWwgc3lzdGVtcy5cbiAgICpcbiAgICogQHJldHVybnMgTGFtYmRhSW52b2tlIHRhc2sgZm9yIGVucmljaG1lbnQsIG9yIHVuZGVmaW5lZCB0byBza2lwIHRoaXMgc3RlcFxuICAgKi9cbiAgcHJvdGVjdGVkIGVucmljaG1lbnRTdGVwKCk6IERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVucmljaG1lbnRMYW1iZGFGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBzdGVwSWQgPSBgRW5yaWNobWVudFN0ZXAtJHt0aGlzLl9lbnJpY2htZW50U3RlcENvdW50ZXJ9YDtcbiAgICB0aGlzLl9lbnJpY2htZW50U3RlcENvdW50ZXIrKztcblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsIHN0ZXBJZCwge1xuICAgICAgbGFtYmRhRnVuY3Rpb246IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVucmljaG1lbnRMYW1iZGFGdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLmVucmljaGVkUmVzdWx0JyxcbiAgICAgIG91dHB1dFBhdGg6ICckJyxcbiAgICAgIHBheWxvYWRSZXNwb25zZU9ubHk6IHRydWUsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wbGVtZW50cyB0aGUgb3B0aW9uYWwgcG9zdC1wcm9jZXNzaW5nIHN0ZXAuXG4gICAqXG4gICAqIElmIGEgcG9zdC1wcm9jZXNzaW5nIExhbWJkYSBmdW5jdGlvbiBpcyBwcm92aWRlZCBpbiB0aGUgcHJvcHMsIGNyZWF0ZXMgYSBMYW1iZGFJbnZva2VcbiAgICogdGFzayB0byBwZXJmb3JtIGZpbmFsIHByb2Nlc3Npbmcgb24gdGhlIHdvcmtmbG93IHJlc3VsdHMuIFRoaXMgc3RlcCBpcyB1c2VmdWwgZm9yXG4gICAqIGRhdGEgZm9ybWF0dGluZywgbm90aWZpY2F0aW9ucywgb3IgaW50ZWdyYXRpb24gd2l0aCBkb3duc3RyZWFtIHN5c3RlbXMuXG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGZvciBwb3N0LXByb2Nlc3NpbmcsIG9yIHVuZGVmaW5lZCB0byBza2lwIHRoaXMgc3RlcFxuICAgKi9cbiAgcHJvdGVjdGVkIHBvc3RQcm9jZXNzaW5nU3RlcCgpOiBEb2N1bWVudFByb2Nlc3NpbmdTdGVwVHlwZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wb3N0UHJvY2Vzc2luZ0xhbWJkYUZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IHN0ZXBJZCA9IGBQb3N0UHJvY2Vzc2luZ1N0ZXAtJHt0aGlzLl9wb3N0UHJvY2Vzc2luZ1N0ZXBDb3VudGVyfWA7XG4gICAgdGhpcy5fcG9zdFByb2Nlc3NpbmdTdGVwQ291bnRlcisrO1xuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgc3RlcElkLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMucG9zdFByb2Nlc3NpbmdMYW1iZGFGdW5jdGlvbixcbiAgICAgIHJlc3VsdFBhdGg6ICckLnBvc3RQcm9jZXNzZWRSZXN1bHQnLFxuICAgICAgb3V0cHV0UGF0aDogJyQnLFxuICAgICAgcGF5bG9hZFJlc3BvbnNlT25seTogdHJ1ZSxcbiAgICB9KTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEltcGxlbWVudHMgdGhlIG9wdGlvbmFsIHByZXByb2Nlc3Npbmcgc3RlcCBmb3IgUERGIGNodW5raW5nLlxuICAgKlxuICAgKiBXaGVuIGNodW5raW5nIGlzIGVuYWJsZWQsIGNyZWF0ZXMgYSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBhbmFseXplcyBQREZzIGFuZFxuICAgKiBzcGxpdHMgbGFyZ2UgZG9jdW1lbnRzIGludG8gbWFuYWdlYWJsZSBjaHVua3MuIFRoZSBmdW5jdGlvbjpcbiAgICogMS4gQW5hbHl6ZXMgdGhlIFBERiB0byBkZXRlcm1pbmUgcGFnZSBjb3VudCBhbmQgdG9rZW4gZXN0aW1hdGVzXG4gICAqIDIuIERlY2lkZXMgaWYgY2h1bmtpbmcgaXMgbmVlZGVkIGJhc2VkIG9uIGNvbmZpZ3VyZWQgdGhyZXNob2xkc1xuICAgKiAzLiBJZiBjaHVua2luZyBpcyBuZWVkZWQsIHNwbGl0cyB0aGUgUERGIGFuZCB1cGxvYWRzIGNodW5rcyB0byBTM1xuICAgKlxuICAgKiBAcmV0dXJucyBMYW1iZGFJbnZva2UgdGFzayBmb3IgUERGIGFuYWx5c2lzIGFuZCBjaHVua2luZywgb3IgdW5kZWZpbmVkIGlmIGNodW5raW5nIGlzIGRpc2FibGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJlcHJvY2Vzc2luZ1N0ZXAoKTogRG9jdW1lbnRQcm9jZXNzaW5nU3RlcFR5cGUgfCB1bmRlZmluZWQge1xuICAgIC8vIE9ubHkgZW5hYmxlIGNodW5raW5nIGlmIGV4cGxpY2l0bHkgY29uZmlndXJlZFxuICAgIGlmICghdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlQ2h1bmtpbmcpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IGNodW5raW5nQ29uZmlnID0gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuY2h1bmtpbmdDb25maWcgfHwge307XG5cbiAgICAvLyBDcmVhdGUgSUFNIHJvbGUgZm9yIGNodW5raW5nIExhbWJkYSB3aXRoIGxlYXN0IHByaXZpbGVnZSBwZXJtaXNzaW9uc1xuICAgIC8vIENodW5raW5nIExhbWJkYSBuZWVkczogR2V0T2JqZWN0IChyZWFkIHJhdyBQREZzKSwgUHV0T2JqZWN0ICh3cml0ZSBjaHVua3MpXG4gICAgY29uc3Qgcm9sZSA9IG5ldyBSb2xlKHRoaXMsICdDaHVua2luZ0xhbWJkYVJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgICAgaW5saW5lUG9saWNpZXM6IHtcbiAgICAgICAgQ2h1bmtpbmdQb2xpY3k6IG5ldyBQb2xpY3lEb2N1bWVudCh7XG4gICAgICAgICAgc3RhdGVtZW50czogW1xuICAgICAgICAgICAgLi4udGhpcy5pbmdyZXNzQWRhcHRlci5nZW5lcmF0ZUFkYXB0ZXJJQU1Qb2xpY2llcygpLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zID0gTGFtYmRhSWFtVXRpbHMuY3JlYXRlTG9nc1Blcm1pc3Npb25zKHtcbiAgICAgIGFjY291bnQsXG4gICAgICBmdW5jdGlvbk5hbWU6ICdiZWRyb2NrLWlkcC1jaHVua2luZycsXG4gICAgICByZWdpb24sXG4gICAgICBzY29wZTogdGhpcyxcbiAgICAgIGVuYWJsZU9ic2VydmFiaWxpdHk6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgfSk7XG5cbiAgICB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnRFbmNyeXB0RGVjcnlwdChyb2xlKTtcblxuICAgIC8vIENyZWF0ZSBQREYgQW5hbHlzaXMgJiBDaHVua2luZyBMYW1iZGFcbiAgICBjb25zdCBjaHVua2luZ0xhbWJkYSA9IG5ldyBQeXRob25GdW5jdGlvbih0aGlzLCAnUERGQ2h1bmtpbmdGdW5jdGlvbicsIHtcbiAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgZW50cnk6IHBhdGguam9pbihfX2Rpcm5hbWUsICdyZXNvdXJjZXMvcGRmLWNodW5raW5nJyksXG4gICAgICBpbmRleDogJ2hhbmRsZXIucHknLFxuICAgICAgaGFuZGxlcjogJ2hhbmRsZXInLFxuICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgIGFyY2hpdGVjdHVyZTogQXJjaGl0ZWN0dXJlLlg4Nl82NCxcbiAgICAgIHJvbGUsXG4gICAgICBtZW1vcnlTaXplOiAyMDQ4LFxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcygxMCksXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBDSFVOS0lOR19TVFJBVEVHWTogY2h1bmtpbmdDb25maWcuc3RyYXRlZ3kgfHwgJ2h5YnJpZCcsXG4gICAgICAgIFBBR0VfVEhSRVNIT0xEOiBTdHJpbmcoY2h1bmtpbmdDb25maWcucGFnZVRocmVzaG9sZCB8fCAxMDApLFxuICAgICAgICBUT0tFTl9USFJFU0hPTEQ6IFN0cmluZyhjaHVua2luZ0NvbmZpZy50b2tlblRocmVzaG9sZCB8fCAxNTAwMDApLFxuICAgICAgICBDSFVOS19TSVpFOiBTdHJpbmcoY2h1bmtpbmdDb25maWcuY2h1bmtTaXplIHx8IDUwKSxcbiAgICAgICAgT1ZFUkxBUF9QQUdFUzogU3RyaW5nKGNodW5raW5nQ29uZmlnLm92ZXJsYXBQYWdlcyB8fCA1KSxcbiAgICAgICAgTUFYX1RPS0VOU19QRVJfQ0hVTks6IFN0cmluZyhjaHVua2luZ0NvbmZpZy5tYXhUb2tlbnNQZXJDaHVuayB8fCAxMDAwMDApLFxuICAgICAgICBPVkVSTEFQX1RPS0VOUzogU3RyaW5nKGNodW5raW5nQ29uZmlnLm92ZXJsYXBUb2tlbnMgfHwgNTAwMCksXG4gICAgICAgIFRBUkdFVF9UT0tFTlNfUEVSX0NIVU5LOiBTdHJpbmcoY2h1bmtpbmdDb25maWcudGFyZ2V0VG9rZW5zUGVyQ2h1bmsgfHwgODAwMDApLFxuICAgICAgICBNQVhfUEFHRVNfUEVSX0NIVU5LOiBTdHJpbmcoY2h1bmtpbmdDb25maWcubWF4UGFnZXNQZXJDaHVuayB8fCA5OSksXG4gICAgICAgIC4uLlBvd2VydG9vbHNDb25maWcuZ2VuZXJhdGVEZWZhdWx0TGFtYmRhQ29uZmlnKFxuICAgICAgICAgIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgICAgICAgdGhpcy5tZXRyaWNOYW1lc3BhY2UsXG4gICAgICAgICAgdGhpcy5tZXRyaWNTZXJ2aWNlTmFtZSxcbiAgICAgICAgKSxcbiAgICAgIH0sXG4gICAgICBlbnZpcm9ubWVudEVuY3J5cHRpb246IHRoaXMuZW5jcnlwdGlvbktleSxcbiAgICAgIHZwYzogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICA/IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsudnBjXG4gICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgdnBjU3VibmV0czogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICA/IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsuYXBwbGljYXRpb25TdWJuZXRTZWxlY3Rpb24oKVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICB9KTtcblxuICAgIGZvciAoY29uc3Qgc3RhdGVtZW50IG9mIGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zLnBvbGljeVN0YXRlbWVudHMpIHtcbiAgICAgIGNodW5raW5nTGFtYmRhLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmspIHtcbiAgICAgIGNodW5raW5nTGFtYmRhLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KExhbWJkYUlhbVV0aWxzLmdlbmVyYXRlTGFtYmRhVlBDUGVybWlzc2lvbnMoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBMYW1iZGFJbnZva2UodGhpcywgJ1BERkFuYWx5c2lzQW5kQ2h1bmtpbmcnLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogY2h1bmtpbmdMYW1iZGEsXG4gICAgICByZXN1bHRQYXRoOiAnJC5jaHVua2luZ1Jlc3VsdCcsXG4gICAgICByZXN1bHRTZWxlY3Rvcjoge1xuICAgICAgICAncmVxdWlyZXNDaHVua2luZy4kJzogJyQuUGF5bG9hZC5yZXF1aXJlc0NodW5raW5nJyxcbiAgICAgICAgJ3Rva2VuQW5hbHlzaXMuJCc6ICckLlBheWxvYWQudG9rZW5BbmFseXNpcycsXG4gICAgICAgICdzdHJhdGVneS4kJzogJyQuUGF5bG9hZC5zdHJhdGVneScsXG4gICAgICAgICdjaHVua3MuJCc6ICckLlBheWxvYWQuY2h1bmtzJyxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUHJvdmlkZXMgYWRkaXRpb25hbCBtZXRhZGF0YSBmaWVsZHMgZm9yIGNodW5raW5nIHRvIGJlIHN0b3JlZCBpbiBEeW5hbW9EQi5cbiAgICpcbiAgICogV2hlbiBjaHVua2luZyBpcyBlbmFibGVkLCBhZGRzIGZpZWxkcyBmb3I6XG4gICAqIC0gQ2h1bmtpbmdFbmFibGVkOiBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYm9vbGVhbiBmbGFnXG4gICAqIC0gQ2h1bmtpbmdTdHJhdGVneTogc3RyYXRlZ3kgdXNlZCAoZml4ZWQtcGFnZXMsIHRva2VuLWJhc2VkLCBoeWJyaWQpXG4gICAqIC0gVG9rZW5BbmFseXNpczogSlNPTiBzdHJpbmcgd2l0aCB0b2tlbiBhbmFseXNpcyByZXN1bHRzXG4gICAqIC0gQ2h1bmtNZXRhZGF0YTogSlNPTiBzdHJpbmcgYXJyYXkgd2l0aCBjaHVuayBpbmZvcm1hdGlvblxuICAgKlxuICAgKiBAcmV0dXJucyBSZWNvcmQgb2YgRHluYW1vREIgYXR0cmlidXRlIHZhbHVlcyBmb3IgY2h1bmtpbmcgbWV0YWRhdGFcbiAgICovXG4gIHByb3RlY3RlZCBwcmVwcm9jZXNzaW5nTWV0YWRhdGEoKTogUmVjb3JkPHN0cmluZywgRHluYW1vQXR0cmlidXRlVmFsdWU+IHtcbiAgICBpZiAoIXRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZUNodW5raW5nKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIENodW5raW5nRW5hYmxlZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhcbiAgICAgICAgSnNvblBhdGguc3RyaW5nQXQoJ1N0YXRlcy5Gb3JtYXQoXFwne31cXCcsICQuY2h1bmtpbmdSZXN1bHQucmVxdWlyZXNDaHVua2luZyknKSxcbiAgICAgICksXG4gICAgICBDaHVua2luZ1N0cmF0ZWd5OiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKFxuICAgICAgICBKc29uUGF0aC5zdHJpbmdBdCgnJC5jaHVua2luZ1Jlc3VsdC5zdHJhdGVneScpLFxuICAgICAgKSxcbiAgICAgIFRva2VuQW5hbHlzaXM6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoXG4gICAgICAgIEpzb25QYXRoLmpzb25Ub1N0cmluZyhKc29uUGF0aC5vYmplY3RBdCgnJC5jaHVua2luZ1Jlc3VsdC50b2tlbkFuYWx5c2lzJykpLFxuICAgICAgKSxcbiAgICAgIENodW5rTWV0YWRhdGE6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoXG4gICAgICAgIEpzb25QYXRoLmpzb25Ub1N0cmluZyhKc29uUGF0aC5vYmplY3RBdCgnJC5jaHVua2luZ1Jlc3VsdC5jaHVua3MnKSksXG4gICAgICApLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgcHJvY2Vzc2luZyB3b3JrZmxvdyB3aXRoIGNvbmRpdGlvbmFsIGJyYW5jaGluZyBmb3IgY2h1bmtlZCBkb2N1bWVudHMuXG4gICAqXG4gICAqIFdoZW4gY2h1bmtpbmcgaXMgZW5hYmxlZCwgY3JlYXRlcyBhIENob2ljZSBTdGF0ZSB0aGF0OlxuICAgKiAtIFJvdXRlcyB0byBjaHVua2VkIHByb2Nlc3NpbmcgZmxvdyBpZiBkb2N1bWVudCB3YXMgY2h1bmtlZFxuICAgKiAtIFJvdXRlcyB0byBzdGFuZGFyZCBwcm9jZXNzaW5nIGZsb3cgaWYgZG9jdW1lbnQgd2FzIG5vdCBjaHVua2VkXG4gICAqXG4gICAqIFdoZW4gY2h1bmtpbmcgaXMgZGlzYWJsZWQsIHJldHVybnMgdGhlIHN0YW5kYXJkIHByb2Nlc3Npbmcgd29ya2Zsb3cuXG4gICAqXG4gICAqIEByZXR1cm5zIFN0ZXAgRnVuY3Rpb25zIGNoYWluIGZvciBwcm9jZXNzaW5nIHRoZSBkb2N1bWVudFxuICAgKi9cbiAgcHJvdGVjdGVkIGNyZWF0ZVByb2Nlc3NpbmdXb3JrZmxvdygpOiBJQ2hhaW5hYmxlIHtcbiAgICAvLyBJZiBjaHVua2luZyBpcyBub3QgZW5hYmxlZCwgdXNlIHN0YW5kYXJkIHdvcmtmbG93XG4gICAgaWYgKCF0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5lbmFibGVDaHVua2luZykge1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlU3RhbmRhcmRQcm9jZXNzaW5nV29ya2Zsb3coKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgQ2hvaWNlIFN0YXRlIHRvIGNoZWNrIGlmIGNodW5raW5nIHdhcyBhcHBsaWVkXG4gICAgY29uc3QgY2hvaWNlU3RhdGUgPSBuZXcgQ2hvaWNlKHRoaXMsICdDaGVja0lmQ2h1bmtlZCcpO1xuXG4gICAgY2hvaWNlU3RhdGVcbiAgICAgIC53aGVuKFxuICAgICAgICBDb25kaXRpb24uYm9vbGVhbkVxdWFscygnJC5jaHVua2luZ1Jlc3VsdC5yZXF1aXJlc0NodW5raW5nJywgdHJ1ZSksXG4gICAgICAgIHRoaXMuY3JlYXRlQ2h1bmtlZFByb2Nlc3NpbmdGbG93KCksXG4gICAgICApXG4gICAgICAub3RoZXJ3aXNlKFxuICAgICAgICAvLyBQYXNzICdTdGFuZGFyZCcgcHJlZml4IHRvIGF2b2lkIGNvbnN0cnVjdCBJRCBjb2xsaXNpb25zIHdpdGggY2h1bmtlZCBmbG93XG4gICAgICAgIHRoaXMuY3JlYXRlU3RhbmRhcmRQcm9jZXNzaW5nV29ya2Zsb3coJ1N0YW5kYXJkJyksXG4gICAgICApO1xuXG4gICAgcmV0dXJuIGNob2ljZVN0YXRlO1xuICB9XG5cblxuICAvKipcbiAgICogQ3JlYXRlcyB0aGUgY2h1bmtlZCBwcm9jZXNzaW5nIGZsb3cgZm9yIGxhcmdlIGRvY3VtZW50cy5cbiAgICpcbiAgICogVGhpcyBmbG93OlxuICAgKiAxLiBVc2VzIGEgTWFwIFN0YXRlIHRvIHByb2Nlc3MgZWFjaCBjaHVuayBpbiBwYXJhbGxlbCAob3Igc2VxdWVudGlhbGx5KVxuICAgKiAyLiBFYWNoIGNodW5rIGdvZXMgdGhyb3VnaCBjbGFzc2lmaWNhdGlvbiBhbmQgcHJvY2Vzc2luZ1xuICAgKiAzLiBSZXN1bHRzIGFyZSBhZ2dyZWdhdGVkIHVzaW5nIHRoZSBhZ2dyZWdhdGlvbiBMYW1iZGFcbiAgICogNC4gRHluYW1vREIgaXMgdXBkYXRlZCB3aXRoIHRoZSBhZ2dyZWdhdGVkIHJlc3VsdFxuICAgKiA1LiBUZW1wb3JhcnkgY2h1bmtzIGFyZSBjbGVhbmVkIHVwIGZyb20gUzNcbiAgICpcbiAgICogQHJldHVybnMgU3RlcCBGdW5jdGlvbnMgY2hhaW4gZm9yIGNodW5rZWQgZG9jdW1lbnQgcHJvY2Vzc2luZ1xuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVDaHVua2VkUHJvY2Vzc2luZ0Zsb3coKTogSUNoYWluYWJsZSB7XG4gICAgY29uc3QgY2h1bmtpbmdDb25maWcgPSB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5jaHVua2luZ0NvbmZpZyB8fCB7fTtcbiAgICBjb25zdCBtYXhDb25jdXJyZW5jeSA9IGNodW5raW5nQ29uZmlnLnByb2Nlc3NpbmdNb2RlID09PSAnc2VxdWVudGlhbCdcbiAgICAgID8gMVxuICAgICAgOiAoY2h1bmtpbmdDb25maWcubWF4Q29uY3VycmVuY3kgfHwgMTApO1xuXG4gICAgLy8gQ3JlYXRlIE1hcCBTdGF0ZSBmb3IgcHJvY2Vzc2luZyBjaHVua3NcbiAgICBjb25zdCBtYXBTdGF0ZSA9IG5ldyBNYXAodGhpcywgJ1Byb2Nlc3NDaHVua3MnLCB7XG4gICAgICBpdGVtc1BhdGg6ICckLmNodW5raW5nUmVzdWx0LmNodW5rcycsXG4gICAgICBtYXhDb25jdXJyZW5jeSxcbiAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgJ2RvY3VtZW50SWQuJCc6ICckLmRvY3VtZW50SWQnLFxuICAgICAgICAnY2h1bmsuJCc6ICckJC5NYXAuSXRlbS5WYWx1ZScsXG4gICAgICAgICdjaHVua0luZGV4LiQnOiAnJCQuTWFwLkl0ZW0uSW5kZXgnLFxuICAgICAgICAndG90YWxDaHVua3MuJCc6ICdTdGF0ZXMuQXJyYXlMZW5ndGgoJC5jaHVua2luZ1Jlc3VsdC5jaHVua3MpJyxcbiAgICAgICAgLy8gT3ZlcnJpZGUgY29udGVudCB0byBwb2ludCB0byB0aGUgY2h1bmsgUERGLCBub3QgdGhlIG9yaWdpbmFsIGRvY3VtZW50XG4gICAgICAgICdjb250ZW50Jzoge1xuICAgICAgICAgICdsb2NhdGlvbic6ICdzMycsXG4gICAgICAgICAgJ2J1Y2tldC4kJzogJyQkLk1hcC5JdGVtLlZhbHVlLmJ1Y2tldCcsXG4gICAgICAgICAgJ2tleS4kJzogJyQkLk1hcC5JdGVtLlZhbHVlLmtleScsXG4gICAgICAgICAgJ2ZpbGVuYW1lLiQnOiAnJC5jb250ZW50LmZpbGVuYW1lJyxcbiAgICAgICAgfSxcbiAgICAgICAgJ2NvbnRlbnRUeXBlLiQnOiAnJC5jb250ZW50VHlwZScsXG4gICAgICB9LFxuICAgICAgcmVzdWx0UGF0aDogJyQuY2h1bmtSZXN1bHRzJyxcbiAgICB9KTtcblxuICAgIC8vIERlZmluZSBwZXItY2h1bmsgcHJvY2Vzc2luZzogY2xhc3NpZmljYXRpb24g4oaSIHByb2Nlc3NpbmdcbiAgICBjb25zdCBjaHVua0NsYXNzaWZpY2F0aW9uID0gdGhpcy5jbGFzc2lmaWNhdGlvblN0ZXAoKTtcbiAgICBjb25zdCBjaHVua1Byb2Nlc3NpbmcgPSB0aGlzLnByb2Nlc3NpbmdTdGVwKCk7XG5cbiAgICBtYXBTdGF0ZS5pdGVtUHJvY2Vzc29yKFxuICAgICAgY2h1bmtDbGFzc2lmaWNhdGlvbi5uZXh0KGNodW5rUHJvY2Vzc2luZyksXG4gICAgKTtcblxuICAgIC8vIENyZWF0ZSBhZ2dyZWdhdGlvbiBzdGVwIChMYW1iZGEgaW52b2tlIG9ubHksIG5vcm1hbGl6YXRpb24gYWRkZWQgc2VwYXJhdGVseSlcbiAgICBjb25zdCBhZ2dyZWdhdGlvbkxhbWJkYVN0ZXAgPSB0aGlzLmNyZWF0ZUFnZ3JlZ2F0aW9uU3RlcCgpO1xuXG4gICAgLy8gQWRkIGEgUGFzcyBzdGF0ZSB0byBub3JtYWxpemUgdGhlIGFnZ3JlZ2F0ZWQgcmVzdWx0IGZvciBkb3duc3RyZWFtIGNvbXBhdGliaWxpdHlcbiAgICAvLyBUaGlzIGNvcGllcyBhZ2dyZWdhdGVkUmVzdWx0IHRvIHByb2Nlc3NpbmdSZXN1bHQgc28gZW5yaWNobWVudC9wb3N0LXByb2Nlc3NpbmdcbiAgICAvLyBzZWUgYSBjb25zaXN0ZW50IHN0cnVjdHVyZSByZWdhcmRsZXNzIG9mIHdoZXRoZXIgY2h1bmtpbmcgd2FzIHVzZWRcbiAgICBjb25zdCBub3JtYWxpemVTdGF0ZSA9IG5ldyBQYXNzKHRoaXMsICdOb3JtYWxpemVBZ2dyZWdhdGVkUmVzdWx0Jywge1xuICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAnZG9jdW1lbnRJZC4kJzogJyQuZG9jdW1lbnRJZCcsXG4gICAgICAgICdjb250ZW50VHlwZS4kJzogJyQuY29udGVudFR5cGUnLFxuICAgICAgICAnY29udGVudC4kJzogJyQuY29udGVudCcsXG4gICAgICAgICdjaHVua2luZ1Jlc3VsdC4kJzogJyQuY2h1bmtpbmdSZXN1bHQnLFxuICAgICAgICAnY2h1bmtSZXN1bHRzLiQnOiAnJC5jaHVua1Jlc3VsdHMnLFxuICAgICAgICAnYWdncmVnYXRlZFJlc3VsdC4kJzogJyQuYWdncmVnYXRlZFJlc3VsdCcsXG4gICAgICAgIC8vIENvcHkgYWdncmVnYXRlZCByZXN1bHQgdG8gcHJvY2Vzc2luZ1Jlc3VsdCBmb3IgZG93bnN0cmVhbSBjb21wYXRpYmlsaXR5XG4gICAgICAgICdwcm9jZXNzaW5nUmVzdWx0Jzoge1xuICAgICAgICAgICdyZXN1bHQuJCc6ICckLmFnZ3JlZ2F0ZWRSZXN1bHQucmVzdWx0JyxcbiAgICAgICAgfSxcbiAgICAgICAgLy8gQWxzbyBzZXQgY2xhc3NpZmljYXRpb25SZXN1bHQgZnJvbSB0aGUgZmlyc3Qgc3VjY2Vzc2Z1bCBjaHVuayBmb3IgY29uc2lzdGVuY3lcbiAgICAgICAgJ2NsYXNzaWZpY2F0aW9uUmVzdWx0LiQnOiAnJC5jaHVua1Jlc3VsdHNbMF0uY2xhc3NpZmljYXRpb25SZXN1bHQnLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBEeW5hbW9EQiB1cGRhdGUgc3RlcCBmb3IgYWdncmVnYXRlZCByZXN1bHRcbiAgICBjb25zdCB1cGRhdGVBZ2dyZWdhdGVkUmVzdWx0U3RlcCA9IHRoaXMuY3JlYXRlVXBkYXRlQWdncmVnYXRlZFJlc3VsdFN0ZXAoKTtcblxuICAgIC8vIENyZWF0ZSBjbGVhbnVwIHN0ZXBcbiAgICBjb25zdCBjbGVhbnVwU3RlcCA9IHRoaXMuY3JlYXRlQ2xlYW51cFN0ZXAoKTtcblxuICAgIC8vIENyZWF0ZSBtb3ZlIHRvIHByb2Nlc3NlZCBjaGFpbiB3aXRoICdDaHVua2VkJyBwcmVmaXggdG8gYXZvaWQgSUQgY29sbGlzaW9uc1xuICAgIGNvbnN0IG1vdmVUb1Byb2Nlc3NlZCA9IHRoaXMuaW5ncmVzc0FkYXB0ZXIuY3JlYXRlU3VjY2Vzc0NoYWluKHRoaXMsICdDaHVua2VkJyk7XG5cbiAgICAvLyBDcmVhdGUgZXJyb3IgaGFuZGxlciBmb3IgYWdncmVnYXRpb24gZmFpbHVyZXNcbiAgICBjb25zdCBhZ2dyZWdhdGlvbkVycm9ySGFuZGxlciA9IHRoaXMuY3JlYXRlQWdncmVnYXRpb25FcnJvckhhbmRsZXIoKTtcblxuICAgIC8vIEdldCBvcHRpb25hbCBlbnJpY2htZW50IGFuZCBwb3N0LXByb2Nlc3Npbmcgc3RlcHNcbiAgICBjb25zdCBlbnJpY2htZW50U3RlcCA9IHRoaXMuZW5yaWNobWVudFN0ZXAoKTtcbiAgICBjb25zdCBwb3N0UHJvY2Vzc2luZ1N0ZXAgPSB0aGlzLnBvc3RQcm9jZXNzaW5nU3RlcCgpO1xuXG4gICAgLy8gQnVpbGQgdGhlIGZpbmFsIGNoYWluIGFmdGVyIGFnZ3JlZ2F0aW9uXG4gICAgLy8gQ2hhaW46IE1hcCBTdGF0ZSDihpIgQWdncmVnYXRpb24g4oaSIER5bmFtb0RCIFVwZGF0ZSDihpIgW0VucmljaG1lbnRdIOKGkiBbUG9zdFByb2Nlc3NpbmddIOKGkiBDbGVhbnVwIOKGkiBNb3ZlIHRvIFByb2Nlc3NlZFxuICAgIGxldCBmaW5hbENoYWluOiBJQ2hhaW5hYmxlID0gY2xlYW51cFN0ZXBcbiAgICAgIC5hZGRSZXRyeSh7XG4gICAgICAgIGVycm9yczogWydMYW1iZGEuU2VydmljZUV4Y2VwdGlvbicsICdMYW1iZGEuVG9vTWFueVJlcXVlc3RzRXhjZXB0aW9uJ10sXG4gICAgICAgIGludGVydmFsOiBEdXJhdGlvbi5zZWNvbmRzKDIpLFxuICAgICAgICBtYXhBdHRlbXB0czogMyxcbiAgICAgICAgYmFja29mZlJhdGU6IDIsXG4gICAgICB9KVxuICAgICAgLm5leHQobW92ZVRvUHJvY2Vzc2VkKTtcblxuICAgIC8vIEFkZCBwb3N0LXByb2Nlc3NpbmcgaWYgcHJvdmlkZWQgKGluc2VydCBiZWZvcmUgY2xlYW51cClcbiAgICBpZiAocG9zdFByb2Nlc3NpbmdTdGVwKSB7XG4gICAgICBjb25zdCBwb3N0UHJvY2Vzc2luZ0Vycm9ySGFuZGxlciA9IG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdDaHVua2VkUG9zdFByb2Nlc3NpbmdGYWlsRERCVXBkYXRlJywge1xuICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAga2V5OiB7XG4gICAgICAgICAgRG9jdW1lbnRJZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5zdHJpbmdBdCgnJC5kb2N1bWVudElkJykpLFxuICAgICAgICB9LFxuICAgICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cycsXG4gICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAnOm5ld1N0YXR1cyc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ3Bvc3QtcHJvY2Vzc2luZy1mYWlsdXJlJyksXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICB9KS5uZXh0KHRoaXMuaW5ncmVzc0FkYXB0ZXIuY3JlYXRlRmFpbGVkQ2hhaW4odGhpcywgJ0NodW5rZWRQb3N0UHJvYycpKTtcblxuICAgICAgZmluYWxDaGFpbiA9IHBvc3RQcm9jZXNzaW5nU3RlcFxuICAgICAgICAuYWRkQ2F0Y2gocG9zdFByb2Nlc3NpbmdFcnJvckhhbmRsZXIsIHtcbiAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICB9KVxuICAgICAgICAubmV4dChcbiAgICAgICAgICBuZXcgRHluYW1vVXBkYXRlSXRlbSh0aGlzLCAnQ2h1bmtlZFBvc3RQcm9jZXNzaW5nU3VjY2Vzc1VwZGF0ZScsIHtcbiAgICAgICAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAgICAgICAga2V5OiB7XG4gICAgICAgICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cywgUG9zdFByb2Nlc3NpbmdSZXN1bHQgPSA6cG9zdFByb2Nlc3NpbmdSZXN1bHQnLFxuICAgICAgICAgICAgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICAgICAnOm5ld1N0YXR1cyc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ3Bvc3QtcHJvY2Vzc2luZy1jb21wbGV0ZScpLFxuICAgICAgICAgICAgICAnOnBvc3RQcm9jZXNzaW5nUmVzdWx0JzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5qc29uVG9TdHJpbmcoSnNvblBhdGgub2JqZWN0QXQoJyQucG9zdFByb2Nlc3NlZFJlc3VsdCcpKSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVzdWx0UGF0aDogSnNvblBhdGguRElTQ0FSRCxcbiAgICAgICAgICB9KS5uZXh0KGZpbmFsQ2hhaW4pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8vIEFkZCBlbnJpY2htZW50IGlmIHByb3ZpZGVkIChpbnNlcnQgYmVmb3JlIHBvc3QtcHJvY2Vzc2luZyBvciBjbGVhbnVwKVxuICAgIGlmIChlbnJpY2htZW50U3RlcCkge1xuICAgICAgY29uc3QgZW5yaWNobWVudEVycm9ySGFuZGxlciA9IG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdDaHVua2VkRW5yaWNobWVudEZhaWxEREJVcGRhdGUnLCB7XG4gICAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAgICBrZXk6IHtcbiAgICAgICAgICBEb2N1bWVudElkOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLnN0cmluZ0F0KCckLmRvY3VtZW50SWQnKSksXG4gICAgICAgIH0sXG4gICAgICAgIHVwZGF0ZUV4cHJlc3Npb246ICdTRVQgV29ya2Zsb3dTdGF0dXMgPSA6bmV3U3RhdHVzJyxcbiAgICAgICAgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICc6bmV3U3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnZW5yaWNobWVudC1mYWlsdXJlJyksXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICB9KS5uZXh0KHRoaXMuaW5ncmVzc0FkYXB0ZXIuY3JlYXRlRmFpbGVkQ2hhaW4odGhpcywgJ0NodW5rZWRFbnJpY2gnKSk7XG5cbiAgICAgIGZpbmFsQ2hhaW4gPSBlbnJpY2htZW50U3RlcFxuICAgICAgICAuYWRkQ2F0Y2goZW5yaWNobWVudEVycm9ySGFuZGxlciwge1xuICAgICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICAgIH0pXG4gICAgICAgIC5uZXh0KFxuICAgICAgICAgIG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdDaHVua2VkRW5yaWNobWVudFN1Y2Nlc3NVcGRhdGUnLCB7XG4gICAgICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAgICAgIGtleToge1xuICAgICAgICAgICAgICBEb2N1bWVudElkOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLnN0cmluZ0F0KCckLmRvY3VtZW50SWQnKSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdXBkYXRlRXhwcmVzc2lvbjogJ1NFVCBXb3JrZmxvd1N0YXR1cyA9IDpuZXdTdGF0dXMsIEVucmljaG1lbnRSZXN1bHQgPSA6ZW5yaWNobWVudFJlc3VsdCcsXG4gICAgICAgICAgICBleHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICAgICAgICc6bmV3U3RhdHVzJzogcG9zdFByb2Nlc3NpbmdTdGVwXG4gICAgICAgICAgICAgICAgPyBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKCdlbnJpY2htZW50LWNvbXBsZXRlJylcbiAgICAgICAgICAgICAgICA6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ2NvbXBsZXRlJyksXG4gICAgICAgICAgICAgICc6ZW5yaWNobWVudFJlc3VsdCc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguanNvblRvU3RyaW5nKEpzb25QYXRoLm9iamVjdEF0KCckLmVucmljaGVkUmVzdWx0JykpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICAgIH0pLm5leHQoZmluYWxDaGFpbiksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gQ2hhaW46IE1hcCBTdGF0ZSDihpIgQWdncmVnYXRpb24g4oaSIE5vcm1hbGl6ZSDihpIgRHluYW1vREIgVXBkYXRlIOKGkiBbRW5yaWNobWVudF0g4oaSIFtQb3N0UHJvY2Vzc2luZ10g4oaSIENsZWFudXAg4oaSIE1vdmUgdG8gUHJvY2Vzc2VkXG4gICAgcmV0dXJuIG1hcFN0YXRlXG4gICAgICAuYWRkQ2F0Y2goYWdncmVnYXRpb25FcnJvckhhbmRsZXIsIHtcbiAgICAgICAgcmVzdWx0UGF0aDogJyQuZXJyb3InLFxuICAgICAgfSlcbiAgICAgIC5uZXh0KFxuICAgICAgICBhZ2dyZWdhdGlvbkxhbWJkYVN0ZXBcbiAgICAgICAgICAuYWRkQ2F0Y2goYWdncmVnYXRpb25FcnJvckhhbmRsZXIsIHtcbiAgICAgICAgICAgIHJlc3VsdFBhdGg6ICckLmVycm9yJyxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5hZGRSZXRyeSh7XG4gICAgICAgICAgICBlcnJvcnM6IFsnTGFtYmRhLlNlcnZpY2VFeGNlcHRpb24nLCAnTGFtYmRhLlRvb01hbnlSZXF1ZXN0c0V4Y2VwdGlvbiddLFxuICAgICAgICAgICAgaW50ZXJ2YWw6IER1cmF0aW9uLnNlY29uZHMoMiksXG4gICAgICAgICAgICBtYXhBdHRlbXB0czogMyxcbiAgICAgICAgICAgIGJhY2tvZmZSYXRlOiAyLFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLm5leHQoXG4gICAgICAgICAgICBub3JtYWxpemVTdGF0ZS5uZXh0KFxuICAgICAgICAgICAgICB1cGRhdGVBZ2dyZWdhdGVkUmVzdWx0U3RlcFxuICAgICAgICAgICAgICAgIC5hZGRSZXRyeSh7XG4gICAgICAgICAgICAgICAgICBlcnJvcnM6IFsnRHluYW1vREIuUHJvdmlzaW9uZWRUaHJvdWdocHV0RXhjZWVkZWRFeGNlcHRpb24nXSxcbiAgICAgICAgICAgICAgICAgIGludGVydmFsOiBEdXJhdGlvbi5zZWNvbmRzKDEpLFxuICAgICAgICAgICAgICAgICAgbWF4QXR0ZW1wdHM6IDMsXG4gICAgICAgICAgICAgICAgICBiYWNrb2ZmUmF0ZTogMixcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5uZXh0KGZpbmFsQ2hhaW4pLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApLFxuICAgICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSBhZ2dyZWdhdGlvbiBzdGVwIGZvciBjb21iaW5pbmcgY2h1bmsgcmVzdWx0cyB1c2luZyBCZWRyb2NrLlxuICAgKlxuICAgKiBVc2VzIHRoZSBzYW1lIEJlZHJvY2sgaW52b2tlIExhbWJkYSBwYXR0ZXJuIGFzIHRoZSBwcm9jZXNzaW5nIHN0ZXAgYnV0IHdpdGhcbiAgICogYSBkaWZmZXJlbnQgcHJvbXB0IGRlc2lnbmVkIGZvciBhZ2dyZWdhdGluZyBtdWx0aXBsZSBjaHVuayByZXN1bHRzLlxuICAgKiBUaGUgY2h1bmsgcHJvY2Vzc2luZyByZXN1bHRzIGFyZSBwYXNzZWQgYXMgdGV4dCBkYXRhIHRvIHRoZSBtb2RlbC5cbiAgICpcbiAgICogQHJldHVybnMgTGFtYmRhSW52b2tlIHRhc2sgZm9yIHJlc3VsdCBhZ2dyZWdhdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVBZ2dyZWdhdGlvblN0ZXAoKTogTGFtYmRhSW52b2tlIHtcbiAgICAvLyBDcmVhdGUgTGFtYmRhIGZ1bmN0aW9uIG9ubHkgb25jZSAocmV1c2VzIGJlZHJvY2staW52b2tlIHBhdHRlcm4pXG4gICAgaWYgKCF0aGlzLl9hZ2dyZWdhdGlvbkZ1bmN0aW9uKSB7XG4gICAgICBjb25zdCBwcm9tcHQgPSB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5hZ2dyZWdhdGlvblByb21wdCB8fCBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nLkRFRkFVTFRfQUdHUkVHQVRJT05fUFJPTVBUO1xuICAgICAgY29uc3QgYWRqdXN0ZWRNb2RlbElkID0gQmVkcm9ja01vZGVsVXRpbHMuZGVyaXZlQWN0dWFsTW9kZWxJZCh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5wcm9jZXNzaW5nQmVkcm9ja01vZGVsKTtcbiAgICAgIGNvbnN0IHJvbGUgPSB0aGlzLmdlbmVyYXRlTGFtYmRhUm9sZUZvckJlZHJvY2soJ0FnZ3JlZ2F0aW9uTGFtYmRhUm9sZScsIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLnByb2Nlc3NpbmdCZWRyb2NrTW9kZWwpO1xuICAgICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgICBjb25zdCBnZW5lcmF0ZWRMb2dQZXJtaXNzaW9ucyA9IExhbWJkYUlhbVV0aWxzLmNyZWF0ZUxvZ3NQZXJtaXNzaW9ucyh7XG4gICAgICAgIGFjY291bnQsXG4gICAgICAgIGZ1bmN0aW9uTmFtZTogJ2JlZHJvY2staWRwLWFnZ3JlZ2F0aW9uJyxcbiAgICAgICAgcmVnaW9uLFxuICAgICAgICBzY29wZTogdGhpcyxcbiAgICAgICAgZW5hYmxlT2JzZXJ2YWJpbGl0eTogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnRFbmNyeXB0RGVjcnlwdChyb2xlKTtcblxuICAgICAgdGhpcy5fYWdncmVnYXRpb25GdW5jdGlvbiA9IG5ldyBQeXRob25GdW5jdGlvbih0aGlzLCAnQmVkcm9ja0FnZ3JlZ2F0aW9uRnVuY3Rpb24nLCB7XG4gICAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgICBhcmNoaXRlY3R1cmU6IEFyY2hpdGVjdHVyZS5YODZfNjQsXG4gICAgICAgIHJ1bnRpbWU6IERlZmF1bHRSdW50aW1lcy5QWVRIT04sXG4gICAgICAgIGVudHJ5OiBwYXRoLmpvaW4oX19kaXJuYW1lLCAncmVzb3VyY2VzL2RlZmF1bHQtYmVkcm9jay1pbnZva2UnKSxcbiAgICAgICAgcm9sZSxcbiAgICAgICAgbWVtb3J5U2l6ZTogMTAyNCxcbiAgICAgICAgdGltZW91dDogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuc3RlcFRpbWVvdXRzIHx8IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgTU9ERUxfSUQ6IGFkanVzdGVkTW9kZWxJZCxcbiAgICAgICAgICBQUk9NUFQ6IHByb21wdCxcbiAgICAgICAgICBJTlZPS0VfVFlQRTogJ2FnZ3JlZ2F0aW9uJyxcbiAgICAgICAgICBJTlZPS0VfTUFYX1RPS0VOUzogJzY0MDAwJywgLy8gQWdncmVnYXRpb24gbWF5IG5lZWQgbW9yZSB0b2tlbnMgZm9yIG1lcmdlZCBvdXRwdXRcbiAgICAgICAgICAuLi5Qb3dlcnRvb2xzQ29uZmlnLmdlbmVyYXRlRGVmYXVsdExhbWJkYUNvbmZpZyhcbiAgICAgICAgICAgIHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLmVuYWJsZU9ic2VydmFiaWxpdHksXG4gICAgICAgICAgICB0aGlzLm1ldHJpY05hbWVzcGFjZSxcbiAgICAgICAgICAgIHRoaXMubWV0cmljU2VydmljZU5hbWUsXG4gICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgZW52aXJvbm1lbnRFbmNyeXB0aW9uOiB0aGlzLmVuY3J5cHRpb25LZXksXG4gICAgICAgIHZwYzogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICAgID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay52cGNcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgdnBjU3VibmV0czogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29ya1xuICAgICAgICAgID8gdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMubmV0d29yay5hcHBsaWNhdGlvblN1Ym5ldFNlbGVjdGlvbigpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICB9KTtcblxuICAgICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMucG9saWN5U3RhdGVtZW50cykge1xuICAgICAgICB0aGlzLl9hZ2dyZWdhdGlvbkZ1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrKSB7XG4gICAgICAgIHRoaXMuX2FnZ3JlZ2F0aW9uRnVuY3Rpb24ucm9sZT8uYWRkVG9QcmluY2lwYWxQb2xpY3koTGFtYmRhSWFtVXRpbHMuZ2VuZXJhdGVMYW1iZGFWUENQZXJtaXNzaW9ucygpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbHdheXMgY3JlYXRlIGEgbmV3IExhbWJkYUludm9rZSB0YXNrIHRvIGFsbG93IHByb3BlciBzdGF0ZSBjaGFpbmluZ1xuICAgIGNvbnN0IHN0ZXBJZCA9IGBBZ2dyZWdhdGlvblN0ZXAtJHt0aGlzLl9hZ2dyZWdhdGlvblN0ZXBDb3VudGVyfWA7XG4gICAgdGhpcy5fYWdncmVnYXRpb25TdGVwQ291bnRlcisrO1xuXG4gICAgLy8gUGFzcyBjaHVuayByZXN1bHRzIGFzIGRhdGEgY29udGVudCAtIHRoZSBMYW1iZGEgd2lsbCBmb3JtYXQgdGhlbSBmb3IgQmVkcm9ja1xuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsIHN0ZXBJZCwge1xuICAgICAgbGFtYmRhRnVuY3Rpb246IHRoaXMuX2FnZ3JlZ2F0aW9uRnVuY3Rpb24sXG4gICAgICBwYXlsb2FkOiBUYXNrSW5wdXQuZnJvbU9iamVjdCh7XG4gICAgICAgICdkb2N1bWVudElkLiQnOiAnJC5kb2N1bWVudElkJyxcbiAgICAgICAgJ2NvbnRlbnRUeXBlJzogJ2RhdGEnLFxuICAgICAgICAnY29udGVudCc6IHtcbiAgICAgICAgICAvLyBQYXNzIHRoZSBjaHVuayByZXN1bHRzIGFzIEpTT04gc3RyaW5nIGZvciB0aGUgTGFtYmRhIHRvIHByb2Nlc3NcbiAgICAgICAgICAnZGF0YS4kJzogJ1N0YXRlcy5Kc29uVG9TdHJpbmcoJC5jaHVua1Jlc3VsdHMpJyxcbiAgICAgICAgfSxcbiAgICAgIH0pLFxuICAgICAgLy8gU3RvcmUgaW4gYm90aCBhZ2dyZWdhdGVkUmVzdWx0IEFORCBwcm9jZXNzaW5nUmVzdWx0IGZvciBjb25zaXN0ZW5jeSB3aXRoIG5vbi1jaHVua2VkIGZsb3dcbiAgICAgIC8vIFRoaXMgYWxsb3dzIGVucmljaG1lbnQvcG9zdC1wcm9jZXNzaW5nIHN0ZXBzIHRvIHVzZSAkLnByb2Nlc3NpbmdSZXN1bHQgcmVnYXJkbGVzcyBvZiBjaHVua2luZ1xuICAgICAgcmVzdWx0UGF0aDogJyQuYWdncmVnYXRlZFJlc3VsdCcsXG4gICAgICByZXN1bHRTZWxlY3Rvcjoge1xuICAgICAgICAncmVzdWx0LiQnOiAnJC5QYXlsb2FkLnJlc3VsdCcsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIER5bmFtb0RCIHVwZGF0ZSBzdGVwIGZvciBzdG9yaW5nIGFnZ3JlZ2F0ZWQgcmVzdWx0cy5cbiAgICpcbiAgICogVXBkYXRlcyB0aGUgZG9jdW1lbnQgcmVjb3JkIHdpdGg6XG4gICAqIC0gQWdncmVnYXRlZFJlc3VsdDogSlNPTiBzdHJpbmcgd2l0aCBjbGFzc2lmaWNhdGlvbiwgZW50aXRpZXMsIGFuZCBzdW1tYXJ5XG4gICAqIC0gV29ya2Zsb3dTdGF0dXM6ICdjb21wbGV0ZSdcbiAgICpcbiAgICogQHJldHVybnMgRHluYW1vVXBkYXRlSXRlbSB0YXNrIGZvciBzdG9yaW5nIGFnZ3JlZ2F0ZWQgcmVzdWx0c1xuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVVcGRhdGVBZ2dyZWdhdGVkUmVzdWx0U3RlcCgpOiBEeW5hbW9VcGRhdGVJdGVtIHtcbiAgICByZXR1cm4gbmV3IER5bmFtb1VwZGF0ZUl0ZW0odGhpcywgJ1N0b3JlQWdncmVnYXRlZFJlc3VsdCcsIHtcbiAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAga2V5OiB7XG4gICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgIH0sXG4gICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIEFnZ3JlZ2F0ZWRSZXN1bHQgPSA6cmVzdWx0LCBXb3JrZmxvd1N0YXR1cyA9IDpzdGF0dXMnLFxuICAgICAgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAnOnJlc3VsdCc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoXG4gICAgICAgICAgSnNvblBhdGguanNvblRvU3RyaW5nKEpzb25QYXRoLm9iamVjdEF0KCckLmFnZ3JlZ2F0ZWRSZXN1bHQnKSksXG4gICAgICAgICksXG4gICAgICAgICc6c3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnY29tcGxldGUnKSxcbiAgICAgIH0sXG4gICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGNsZWFudXAgTGFtYmRhIHN0ZXAgZm9yIHJlbW92aW5nIHRlbXBvcmFyeSBjaHVuayBmaWxlcy5cbiAgICpcbiAgICogVGhlIGNsZWFudXAgTGFtYmRhOlxuICAgKiAtIERlbGV0ZXMgYWxsIGNodW5rIGZpbGVzIGZyb20gUzMgY2h1bmtzLyBwcmVmaXhcbiAgICogLSBVc2VzIGJhdGNoIGRlbGV0ZSBmb3IgZWZmaWNpZW5jeSAodXAgdG8gMTAwMCBvYmplY3RzIHBlciByZXF1ZXN0KVxuICAgKiAtIExvZ3MgZXJyb3JzIGJ1dCBkb2Vzbid0IGZhaWwgdGhlIHdvcmtmbG93XG4gICAqXG4gICAqIEByZXR1cm5zIExhbWJkYUludm9rZSB0YXNrIGZvciBjaHVuayBjbGVhbnVwXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUNsZWFudXBTdGVwKCk6IExhbWJkYUludm9rZSB7XG4gICAgLy8gQ3JlYXRlIExhbWJkYSBmdW5jdGlvbiBvbmx5IG9uY2VcbiAgICBpZiAoIXRoaXMuX2NsZWFudXBGdW5jdGlvbikge1xuICAgICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgICBjb25zdCByb2xlID0gbmV3IFJvbGUodGhpcywgJ0NsZWFudXBMYW1iZGFSb2xlJywge1xuICAgICAgICBhc3N1bWVkQnk6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgICAgICBpbmxpbmVQb2xpY2llczoge1xuICAgICAgICAgIENsZWFudXBQb2xpY3k6IG5ldyBQb2xpY3lEb2N1bWVudCh7XG4gICAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICAgIC8vIFMzIGFjY2VzcyBmb3IgZGVsZXRpbmcgY2h1bmtzIG9ubHkgLSBsZWFzdCBwcml2aWxlZ2VcbiAgICAgICAgICAgICAgLi4udGhpcy5pbmdyZXNzQWRhcHRlci5nZW5lcmF0ZUFkYXB0ZXJJQU1Qb2xpY2llcyhbJ3MzOkRlbGV0ZU9iamVjdCddLCB0cnVlKSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMgPSBMYW1iZGFJYW1VdGlscy5jcmVhdGVMb2dzUGVybWlzc2lvbnMoe1xuICAgICAgICBhY2NvdW50LFxuICAgICAgICBmdW5jdGlvbk5hbWU6ICdiZWRyb2NrLWlkcC1jbGVhbnVwJyxcbiAgICAgICAgcmVnaW9uLFxuICAgICAgICBzY29wZTogdGhpcyxcbiAgICAgICAgZW5hYmxlT2JzZXJ2YWJpbGl0eTogdGhpcy5iZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnRFbmNyeXB0RGVjcnlwdChyb2xlKTtcblxuICAgICAgdGhpcy5fY2xlYW51cEZ1bmN0aW9uID0gbmV3IFB5dGhvbkZ1bmN0aW9uKHRoaXMsICdDbGVhbnVwRnVuY3Rpb24nLCB7XG4gICAgICAgIGZ1bmN0aW9uTmFtZTogZ2VuZXJhdGVkTG9nUGVybWlzc2lvbnMudW5pcXVlRnVuY3Rpb25OYW1lLFxuICAgICAgICBlbnRyeTogcGF0aC5qb2luKF9fZGlybmFtZSwgJ3Jlc291cmNlcy9jbGVhbnVwJyksXG4gICAgICAgIGluZGV4OiAnaGFuZGxlci5weScsXG4gICAgICAgIGhhbmRsZXI6ICdoYW5kbGVyJyxcbiAgICAgICAgcnVudGltZTogRGVmYXVsdFJ1bnRpbWVzLlBZVEhPTixcbiAgICAgICAgYXJjaGl0ZWN0dXJlOiBBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgICByb2xlLFxuICAgICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgICAgLi4uUG93ZXJ0b29sc0NvbmZpZy5nZW5lcmF0ZURlZmF1bHRMYW1iZGFDb25maWcoXG4gICAgICAgICAgICB0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5lbmFibGVPYnNlcnZhYmlsaXR5LFxuICAgICAgICAgICAgdGhpcy5tZXRyaWNOYW1lc3BhY2UsXG4gICAgICAgICAgICB0aGlzLm1ldHJpY1NlcnZpY2VOYW1lLFxuICAgICAgICAgICksXG4gICAgICAgIH0sXG4gICAgICAgIGVudmlyb25tZW50RW5jcnlwdGlvbjogdGhpcy5lbmNyeXB0aW9uS2V5LFxuICAgICAgICB2cGM6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmtcbiAgICAgICAgICA/IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsudnBjXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIHZwY1N1Ym5ldHM6IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmtcbiAgICAgICAgICA/IHRoaXMuYmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzLm5ldHdvcmsuYXBwbGljYXRpb25TdWJuZXRTZWxlY3Rpb24oKVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgfSk7XG5cbiAgICAgIGZvciAoY29uc3Qgc3RhdGVtZW50IG9mIGdlbmVyYXRlZExvZ1Blcm1pc3Npb25zLnBvbGljeVN0YXRlbWVudHMpIHtcbiAgICAgICAgdGhpcy5fY2xlYW51cEZ1bmN0aW9uLnJvbGU/LmFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcy5uZXR3b3JrKSB7XG4gICAgICAgIHRoaXMuX2NsZWFudXBGdW5jdGlvbi5yb2xlPy5hZGRUb1ByaW5jaXBhbFBvbGljeShMYW1iZGFJYW1VdGlscy5nZW5lcmF0ZUxhbWJkYVZQQ1Blcm1pc3Npb25zKCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhSW52b2tlKHRoaXMsICdDbGVhbnVwQ2h1bmtzJywge1xuICAgICAgbGFtYmRhRnVuY3Rpb246IHRoaXMuX2NsZWFudXBGdW5jdGlvbixcbiAgICAgIHBheWxvYWQ6IFRhc2tJbnB1dC5mcm9tT2JqZWN0KHtcbiAgICAgICAgJ2RvY3VtZW50SWQuJCc6ICckLmRvY3VtZW50SWQnLFxuICAgICAgICAnY2h1bmtzLiQnOiAnJC5jaHVua2luZ1Jlc3VsdC5jaHVua3MnLFxuICAgICAgfSksXG4gICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGVycm9yIGhhbmRsZXIgZm9yIGFnZ3JlZ2F0aW9uIGZhaWx1cmVzLlxuICAgKlxuICAgKiBXaGVuIGFnZ3JlZ2F0aW9uIGZhaWxzOlxuICAgKiAtIFVwZGF0ZXMgRHluYW1vREIgd2l0aCAnYWdncmVnYXRpb24tZmFpbHVyZScgc3RhdHVzXG4gICAqIC0gTW92ZXMgZG9jdW1lbnQgdG8gZmFpbGVkLyBwcmVmaXhcbiAgICpcbiAgICogQHJldHVybnMgU3RlcCBGdW5jdGlvbnMgY2hhaW4gZm9yIGhhbmRsaW5nIGFnZ3JlZ2F0aW9uIGVycm9yc1xuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVBZ2dyZWdhdGlvbkVycm9ySGFuZGxlcigpOiBJQ2hhaW5hYmxlIHtcbiAgICBjb25zdCB1cGRhdGVGYWlsdXJlU3RhdHVzID0gbmV3IER5bmFtb1VwZGF0ZUl0ZW0odGhpcywgJ0FnZ3JlZ2F0aW9uRmFpbEREQlVwZGF0ZScsIHtcbiAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAga2V5OiB7XG4gICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgIH0sXG4gICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cycsXG4gICAgICBleHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICc6bmV3U3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnYWdncmVnYXRpb24tZmFpbHVyZScpLFxuICAgICAgfSxcbiAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgfSk7XG5cbiAgICAvLyBVc2UgJ0NodW5rZWQnIHByZWZpeCB0byBhdm9pZCBJRCBjb2xsaXNpb25zIHdpdGggc3RhbmRhcmQgd29ya2Zsb3dcbiAgICBjb25zdCBtb3ZlVG9GYWlsZWQgPSB0aGlzLmluZ3Jlc3NBZGFwdGVyLmNyZWF0ZUZhaWxlZENoYWluKHRoaXMsICdDaHVua2VkJyk7XG5cbiAgICByZXR1cm4gdXBkYXRlRmFpbHVyZVN0YXR1cy5uZXh0KG1vdmVUb0ZhaWxlZCk7XG4gIH1cbn1cbiJdfQ==
|