@aws-cdk/aws-bedrock-agentcore-alpha
Version:
The CDK Construct Library for Amazon Bedrock
641 lines • 84.6 kB
JavaScript
"use strict";
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserCustom = exports.BrowserCustomBase = void 0;
const jsiiDeprecationWarnings = require("../../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
const iam = require("aws-cdk-lib/aws-iam");
const s3 = require("aws-cdk-lib/aws-s3");
const ec2 = require("aws-cdk-lib/aws-ec2");
const agent_core = require("aws-cdk-lib/aws-bedrockagentcore");
const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource");
const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable");
// Internal Libs
const perms = require("./perms");
const validation_helpers_1 = require("./validation-helpers");
const network_configuration_1 = require("../network/network-configuration");
/******************************************************************************
* CONSTANTS
*****************************************************************************/
/**
* Minimum length for browser name
* @internal
*/
const BROWSER_NAME_MIN_LENGTH = 1;
/**
* Maximum length for browser name
* @internal
*/
const BROWSER_NAME_MAX_LENGTH = 48;
/**
* Minimum length for browser tags
* @internal
*/
const BROWSER_TAG_MIN_LENGTH = 1;
/**
* Maximum length for browser tags
* @internal
*/
const BROWSER_TAG_MAX_LENGTH = 256;
/******************************************************************************
* ABSTRACT BASE CLASS
*****************************************************************************/
/**
* Abstract base class for a Browser.
* Contains methods and attributes valid for Browsers either created with CDK or imported.
*/
class BrowserCustomBase extends aws_cdk_lib_1.Resource {
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-bedrock-agentcore-alpha.BrowserCustomBase", version: "2.227.0-alpha.0" };
/**
* An accessor for the Connections object that will fail if this Browser does not have a VPC
* configured.
*/
get connections() {
if (!this._connections) {
throw new aws_cdk_lib_1.ValidationError('Cannot manage network access without configuring a VPC', this);
}
return this._connections;
}
/**
* The actual Connections object for this Browser. This may be unset in the event that a VPC has not
* been configured.
* @internal
*/
_connections;
constructor(scope, id) {
super(scope, id);
}
/**
* Grants IAM actions to the IAM Principal
* @param grantee - The IAM principal to grant permissions to
* @param actions - The actions to grant
* @returns An IAM Grant object representing the granted permissions
*/
grant(grantee, ...actions) {
return iam.Grant.addToPrincipal({
grantee: grantee,
resourceArns: [this.browserArn],
actions: actions,
});
}
/**
* Grant read permissions on this browser to an IAM principal.
* This includes both read permissions on the specific browser and list permissions on all browsers.
*
* @param grantee - The IAM principal to grant read permissions to
* @default - Default grant configuration:
* - actions: ['bedrock-agentcore:GetBrowser', 'bedrock-agentcore:GetBrowserSession'] on this.browserArn
* - actions: ['bedrock-agentcore:ListBrowsers', 'bedrock-agentcore:ListBrowserSessions'] on all resources (*)
* @returns An IAM Grant object representing the granted permissions
*/
grantRead(grantee) {
const resourceSpecificGrant = this.grant(grantee, ...perms.BROWSER_READ_PERMS);
const allResourceGrant = iam.Grant.addToPrincipal({
grantee: grantee,
resourceArns: ['*'],
actions: perms.BROWSER_LIST_PERMS,
});
// Return combined grant
return resourceSpecificGrant.combine(allResourceGrant);
}
/**
* Grant invoke permissions on this browser to an IAM principal.
*
* @param grantee - The IAM principal to grant invoke permissions to
* @default - Default grant configuration:
* - actions: ['bedrock-agentcore:StartBrowserSession', 'bedrock-agentcore:UpdateBrowserStream', 'bedrock-agentcore:StopBrowserSession']
* - resourceArns: [this.browserArn]
* @returns An IAM Grant object representing the granted permissions
*/
grantUse(grantee) {
return this.grant(grantee, ...perms.BROWSER_USE_PERMS);
}
// ------------------------------------------------------
// Metrics
// ------------------------------------------------------
/**
* Return the given named metric for this browser.
*
* By default, the metric will be calculated as a sum over a period of 5 minutes.
* You can customize this by using the `statistic` and `period` properties.
*/
metric(metricName, dimensions, props) {
const metricProps = {
namespace: 'AWS/Bedrock-AgentCore',
metricName,
dimensionsMap: { ...dimensions, Resource: this.browserArn },
...props,
};
return this.configureMetric(metricProps);
}
/**
* Creates a CloudWatch metric for tracking browser api operations..
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: metricName
* - dimensionsMap: { BrowserId: this.browserId }
* @returns A CloudWatch Metric configured for browser api operations
*/
metricForApiOperation(metricName, operation, props) {
return this.metric(metricName, { Operation: operation }, props);
}
/**
* Creates a CloudWatch metric for tracking browser latencies.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: Latency
* @returns A CloudWatch Metric configured for browser latencies
*/
metricLatencyForApiOperation(operation, props) {
return this.metricForApiOperation('Latency', operation, { statistic: aws_cloudwatch_1.Stats.AVERAGE, ...props });
}
/**
* Creates a CloudWatch metric for tracking browser invocations.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: Invocations
* @returns A CloudWatch Metric configured for browser latencies
*/
metricInvocationsForApiOperation(operation, props) {
return this.metricForApiOperation('Invocations', operation, {
statistic: aws_cloudwatch_1.Stats.SUM,
...props,
});
}
/**
* Creates a CloudWatch metric for tracking browser errors.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: Errors
* @returns A CloudWatch Metric configured for browser errors
*/
metricErrorsForApiOperation(operation, props) {
return this.metricForApiOperation('Errors', operation, { statistic: aws_cloudwatch_1.Stats.SUM, ...props });
}
/**
* Creates a CloudWatch metric for tracking browser throttles.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: Throttles
* @returns A CloudWatch Metric configured for browser throttles
*/
metricThrottlesForApiOperation(operation, props) {
return this.metricForApiOperation('Throttles', operation, { statistic: aws_cloudwatch_1.Stats.SUM, ...props });
}
/**
* Creates a CloudWatch metric for tracking browser system errors.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: SystemErrors
* @returns A CloudWatch Metric configured for browser system errors
*/
metricSystemErrorsForApiOperation(operation, props) {
return this.metricForApiOperation('SystemErrors', operation, { statistic: aws_cloudwatch_1.Stats.SUM, ...props });
}
/**
* Creates a CloudWatch metric for tracking browser user errors.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: UserErrors
* @returns A CloudWatch Metric configured for browser user errors
*/
metricUserErrorsForApiOperation(operation, props) {
return this.metricForApiOperation('UserErrors', operation, { statistic: aws_cloudwatch_1.Stats.SUM, ...props });
}
/**
* Creates a CloudWatch metric for tracking browser session duration.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: Duration
* @returns A CloudWatch Metric configured for browser session duration
*/
metricSessionDuration(props) {
return this.metric('Duration', { Operation: 'BrowserSession' }, { statistic: aws_cloudwatch_1.Stats.AVERAGE, ...props });
}
/**
* Creates a CloudWatch metric for tracking browser user takeovers.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: TakeOverCount
* @returns A CloudWatch Metric configured for browser user takeovers
*/
metricTakeOverCount(props) {
return this.metric('TakeOverCount', {}, { statistic: aws_cloudwatch_1.Stats.SUM, ...props });
}
/**
* Creates a CloudWatch metric for tracking browser user takeovers released.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: TakeOverReleaseCount
* @returns A CloudWatch Metric configured for browser user takeovers released
*/
metricTakeOverReleaseCount(props) {
return this.metric('TakeOverReleaseCount', {}, { statistic: aws_cloudwatch_1.Stats.SUM, ...props });
}
/**
* Creates a CloudWatch metric for tracking browser user takeovers duration.
*
* @param props - Configuration options for the metric
* @default - Default metric configuration:
* - namespace: 'AWS/Bedrock-AgentCore'
* - metricName: TakeOverDuration
* @returns A CloudWatch Metric configured for browser user takeovers duration
*/
metricTakeOverDuration(props) {
return this.metric('TakeOverDuration', {}, { statistic: aws_cloudwatch_1.Stats.AVERAGE, ...props });
}
/**
* Internal method to create a metric.
*
* @param props - Configuration options for the metric
* @returns A CloudWatch Metric configured for browser api operations
*/
configureMetric(props) {
return new aws_cloudwatch_1.Metric({
...props,
region: props?.region ?? this.stack.region,
account: props?.account ?? this.stack.account,
});
}
}
exports.BrowserCustomBase = BrowserCustomBase;
/******************************************************************************
* Class
*****************************************************************************/
/**
* Browser resource for AWS Bedrock Agent Core.
* Provides a browser environment for web automation and interaction.
*
* @see https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/browser.html
* @resource AWS::BedrockAgentCore::BrowserCustom
*/
let BrowserCustom = (() => {
let _classDecorators = [prop_injectable_1.propertyInjectable];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _classSuper = BrowserCustomBase;
var BrowserCustom = class extends _classSuper {
static { _classThis = this; }
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
BrowserCustom = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-bedrock-agentcore-alpha.BrowserCustom", version: "2.227.0-alpha.0" };
/** Uniquely identifies this class. */
static PROPERTY_INJECTION_ID = '@aws-cdk.aws-bedrock-agentcore-alpha.BrowserCustom';
/**
* Static Method for importing an existing Bedrock AgentCore Browser Custom.
*/
/**
* Creates an Browser Custom reference from an existing browser's attributes.
*
* @param scope - The construct scope
* @param id - Identifier of the construct
* @param attrs - Attributes of the existing browser custom
* @returns An IBrowserCustom reference to the existing browser
*/
static fromBrowserCustomAttributes(scope, id, attrs) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_bedrock_agentcore_alpha_BrowserCustomAttributes(attrs);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromBrowserCustomAttributes);
}
throw error;
}
class Import extends BrowserCustomBase {
browserArn = attrs.browserArn;
browserId = aws_cdk_lib_1.Arn.split(attrs.browserArn, aws_cdk_lib_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
executionRole = iam.Role.fromRoleArn(scope, `${id}Role`, attrs.roleArn);
lastUpdatedAt = attrs.lastUpdatedAt;
grantPrincipal = this.executionRole;
status = attrs.status;
createdAt = attrs.createdAt;
constructor(s, i) {
super(s, i);
this.grantPrincipal = this.executionRole || new iam.UnknownPrincipal({ resource: this });
if (attrs.securityGroups) {
this._connections = new ec2.Connections({
securityGroups: attrs.securityGroups,
});
}
}
}
// Return new Browser Custom
return new Import(scope, id);
}
// ------------------------------------------------------
// Attributes
// ------------------------------------------------------
/**
* The ARN of the browser resource.
* @attribute
*/
browserArn;
/**
* The id of the browser
* @attribute
*/
browserId;
/**
* The name of the browser
*/
name;
/**
* The description of the browser
*/
description;
/**
* The last updated timestamp of the browser
* @attribute
*/
lastUpdatedAt;
/**
* The status of the browser
* @attribute
*/
status;
/**
* The created timestamp of the browser
* @attribute
*/
createdAt;
/**
* The failure reason of the browser
* @attribute
*/
failureReason;
/**
* The IAM role associated to the browser.
*/
executionRole;
/**
* Tags applied to this browser resource
* A map of key-value pairs for resource tagging
* @default - No tags applied
*/
tags;
/**
* The principal to grant permissions to
*/
grantPrincipal;
/**
* The network configuration of the browser
*/
networkConfiguration;
/**
* The recording configuration of the browser
*/
recordingConfig;
// ------------------------------------------------------
// Internal Only
// ------------------------------------------------------
__resource;
// ------------------------------------------------------
// CONSTRUCTOR
// ------------------------------------------------------
constructor(scope, id, props) {
super(scope, id);
try {
jsiiDeprecationWarnings._aws_cdk_aws_bedrock_agentcore_alpha_BrowserCustomProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, BrowserCustom);
}
throw error;
}
// Enhanced CDK Analytics Telemetry
(0, metadata_resource_1.addConstructMetadata)(this, props);
// ------------------------------------------------------
// Set properties and defaults
// ------------------------------------------------------
this.name = props.browserCustomName;
this.description = props.description;
this.networkConfiguration = props.networkConfiguration ?? network_configuration_1.BrowserNetworkConfiguration.usingPublicNetwork();
this.recordingConfig = props.recordingConfig ?? { enabled: false };
this.executionRole = props.executionRole ?? this._createBrowserRole();
this.grantPrincipal = this.executionRole;
this.tags = props.tags;
// Validate browser name
(0, validation_helpers_1.throwIfInvalid)(this._validateBrowserName, this.name);
// Validate browser tags
(0, validation_helpers_1.throwIfInvalid)(this._validateBrowserTags, this.tags);
// Validate recording configuration
(0, validation_helpers_1.throwIfInvalid)(this._validateRecordingConfig, this.recordingConfig);
// Network configuration and validation is done in the network configuration class
// So we don't need to validate it here
// Set connections - create a shared connections object
if (this.networkConfiguration.connections) {
// Use the network configuration's connections as the shared object
this._connections = this.networkConfiguration.connections;
}
// ------------------------------------------------------
// CFN Props - With Lazy support
// ------------------------------------------------------
const cfnProps = {
name: this.name,
description: this.description,
networkConfiguration: aws_cdk_lib_1.Lazy.any({ produce: () => this.networkConfiguration._render(this._connections) }),
recordingConfig: this._renderRecordingConfig(),
executionRoleArn: this.executionRole?.roleArn,
tags: this.tags,
};
// L1 instantiation
this.__resource = new agent_core.CfnBrowserCustom(this, 'Resource', cfnProps);
// Get attributes directly from the CloudFormation resource
this.browserId = this.__resource.attrBrowserId;
this.browserArn = this.__resource.attrBrowserArn;
this.status = this.__resource.attrStatus;
this.createdAt = this.__resource.attrCreatedAt;
this.lastUpdatedAt = this.__resource.attrLastUpdatedAt;
this.failureReason = this.__resource.attrFailureReason;
// if recording is configured, add permissions to the execution role
if (this.recordingConfig && this.recordingConfig.s3Location) {
if (!aws_cdk_lib_1.Token.isUnresolved(this.recordingConfig.s3Location.bucketName)) {
aws_cdk_lib_1.Stack.of(this).resolve(this.recordingConfig.s3Location.bucketName);
}
const bucket = s3.Bucket.fromBucketName(this, `${this.name}RecordingBucket`, this.recordingConfig.s3Location.bucketName);
// Ensure the policy is applied before the browser resource is created
const grant = bucket.grantReadWrite(this.executionRole);
grant.applyBefore(this.__resource);
}
}
/**
* Render the recording configuration.
*
* @returns RecordingConfigProperty object in CloudFormation format, or undefined if no recording configuration is defined
* @default - undefined if no recording configuration is provided
* @internal This is an internal core function and should not be called directly.
*/
_renderRecordingConfig() {
return this.recordingConfig ? {
enabled: this.recordingConfig.enabled,
s3Location: this.recordingConfig.s3Location ? {
bucket: this.recordingConfig.s3Location.bucketName,
prefix: this.recordingConfig.s3Location.objectKey,
} : undefined,
} : undefined;
}
/**
* Creates execution role needed for the browser to access AWS services
* @returns The created role
* @internal This is an internal core function and should not be called directly.
*/
_createBrowserRole() {
const role = new iam.Role(this, 'ServiceRole', {
assumedBy: new iam.ServicePrincipal('bedrock-agentcore.amazonaws.com'),
});
return role;
}
// ------------------------------------------------------
// Validators
// ------------------------------------------------------
/**
* Validates the browser name format
* @param name The browser name to validate
* @returns Array of validation error messages, empty if valid
*/
_validateBrowserName = (name) => {
let errors = [];
errors.push(...(0, validation_helpers_1.validateStringFieldLength)({
value: name,
fieldName: 'Browser name',
minLength: BROWSER_NAME_MIN_LENGTH,
maxLength: BROWSER_NAME_MAX_LENGTH,
}));
// Check if name matches the AWS API pattern: [a-zA-Z][a-zA-Z0-9_]{0,47}
// Must start with a letter, followed by up to 47 letters, numbers, or underscores
const validNamePattern = /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/;
errors.push(...(0, validation_helpers_1.validateFieldPattern)(name, 'Browser name', validNamePattern));
return errors;
};
/**
* Validates the browser tags format
* @param tags The tags object to validate
* @returns Array of validation error messages, empty if valid
*/
_validateBrowserTags = (tags) => {
let errors = [];
if (!tags) {
return errors; // Tags are optional
}
// Validate each tag key and value
for (const [key, value] of Object.entries(tags)) {
errors.push(...(0, validation_helpers_1.validateStringFieldLength)({
value: key,
fieldName: 'Tag key',
minLength: BROWSER_TAG_MIN_LENGTH,
maxLength: BROWSER_TAG_MAX_LENGTH,
}));
// Validate tag key pattern: ^[a-zA-Z0-9\s._:/=+@-]*$
const validKeyPattern = /^[a-zA-Z0-9\s._:/=+@-]*$/;
errors.push(...(0, validation_helpers_1.validateFieldPattern)(key, 'Tag key', validKeyPattern));
// Validate tag value
errors.push(...(0, validation_helpers_1.validateStringFieldLength)({
value: value,
fieldName: 'Tag value',
minLength: BROWSER_TAG_MIN_LENGTH,
maxLength: BROWSER_TAG_MAX_LENGTH,
}));
// Validate tag value pattern: ^[a-zA-Z0-9\s._:/=+@-]*$
const validValuePattern = /^[a-zA-Z0-9\s._:/=+@-]*$/;
errors.push(...(0, validation_helpers_1.validateFieldPattern)(value, 'Tag value', validValuePattern));
}
return errors;
};
/**
* Validates the recording configuration
* @param recordingConfig The recording configuration to validate
* @returns Array of validation error messages, empty if valid
*/
_validateRecordingConfig = (recordingConfig) => {
let errors = [];
if (!recordingConfig) {
return errors; // No validation needed if no recording config is provided
}
const s3Location = recordingConfig.s3Location;
// Only validate S3 location if it's actually provided
if (s3Location) {
// Both bucket name and object key are required when S3 location is provided
if (!s3Location.bucketName) {
errors.push('S3 bucket name is required when S3 location is provided for recording configuration');
}
else {
// Validate bucket name pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$
const bucketNamePattern = /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;
errors.push(...(0, validation_helpers_1.validateFieldPattern)(s3Location.bucketName, 'S3 bucket name', bucketNamePattern));
}
if (!s3Location.objectKey) {
errors.push('S3 object key (prefix) is required when S3 location is provided for recording configuration');
}
}
return errors;
};
static {
__runInitializers(_classThis, _classExtraInitializers);
}
};
return BrowserCustom = _classThis;
})();
exports.BrowserCustom = BrowserCustom;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJvd3Nlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImJyb3dzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsNkNBU3FCO0FBQ3JCLCtEQU1vQztBQUNwQywyQ0FBMkM7QUFDM0MseUNBQXlDO0FBQ3pDLDJDQUEyQztBQUMzQywrREFBK0Q7QUFHL0QsOEVBQThFO0FBQzlFLDBFQUEwRTtBQUMxRSxnQkFBZ0I7QUFDaEIsaUNBQWlDO0FBQ2pDLDZEQUF1RztBQUN2Ryw0RUFBK0U7QUFFL0U7OytFQUUrRTtBQUMvRTs7O0dBR0c7QUFDSCxNQUFNLHVCQUF1QixHQUFHLENBQUMsQ0FBQztBQUVsQzs7O0dBR0c7QUFDSCxNQUFNLHVCQUF1QixHQUFHLEVBQUUsQ0FBQztBQUVuQzs7O0dBR0c7QUFDSCxNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQztBQUVqQzs7O0dBR0c7QUFDSCxNQUFNLHNCQUFzQixHQUFHLEdBQUcsQ0FBQztBQXlIbkM7OytFQUUrRTtBQUMvRTs7O0dBR0c7QUFDSCxNQUFzQixpQkFBa0IsU0FBUSxzQkFBUTs7SUFXdEQ7OztPQUdHO0lBQ0gsSUFBVyxXQUFXO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDdkIsTUFBTSxJQUFJLDZCQUFlLENBQUMsd0RBQXdELEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDNUYsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztLQUMxQjtJQUNEOzs7O09BSUc7SUFDTyxZQUFZLENBQThCO0lBRXBELFlBQVksS0FBZ0IsRUFBRSxFQUFVO1FBQ3RDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7S0FDbEI7SUFFRDs7Ozs7T0FLRztJQUNJLEtBQUssQ0FBQyxPQUF1QixFQUFFLEdBQUcsT0FBaUI7UUFDeEQsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLGNB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O1lBRUQsTUFBTSxVQUFVLEdBQUcsZUFBZSxDQUFDLFVBQVUsQ0FBQztZQUU5QyxzREFBc0Q7WUFDdEQsSUFBSSxVQUFVLEVBQUUsQ0FBQztnQkFDZiw0RUFBNEU7Z0JBQzVFLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7b0JBQzNCLE1BQU0sQ0FBQyxJQUFJLENBQUMscUZBQXFGLENBQUMsQ0FBQztnQkFDckcsQ0FBQztxQkFBTSxDQUFDO29CQUNOLG1FQUFtRTtvQkFDbkUsTUFBTSxpQkFBaUIsR0FBRyxvQ0FBb0MsQ0FBQztvQkFDL0QsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUEseUNBQW9CLEVBQUMsVUFBVSxDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7Z0JBQ25HLENBQUM7Z0JBRUQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsQ0FBQztvQkFDMUIsTUFBTSxDQUFDLElBQUksQ0FBQyw2RkFBNkYsQ0FBQyxDQUFDO2dCQUM3RyxDQUFDO1lBQ0gsQ0FBQztZQUVELE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUMsQ0FBQzs7WUF2VFMsdURBQWE7Ozs7O0FBQWIsc0NBQWEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBcm4sXG4gIEFybkZvcm1hdCxcbiAgSVJlc291cmNlLFxuICBMYXp5LFxuICBSZXNvdXJjZSxcbiAgVG9rZW4sXG4gIFN0YWNrLFxuICBWYWxpZGF0aW9uRXJyb3IsXG59IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7XG4gIERpbWVuc2lvbnNNYXAsXG4gIE1ldHJpYyxcbiAgTWV0cmljT3B0aW9ucyxcbiAgTWV0cmljUHJvcHMsXG4gIFN0YXRzLFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgYWdlbnRfY29yZSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtYmVkcm9ja2FnZW50Y29yZSc7XG5pbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IGFkZENvbnN0cnVjdE1ldGFkYXRhIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvbWV0YWRhdGEtcmVzb3VyY2UnO1xuaW1wb3J0IHsgcHJvcGVydHlJbmplY3RhYmxlIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvcHJvcC1pbmplY3RhYmxlJztcbi8vIEludGVybmFsIExpYnNcbmltcG9ydCAqIGFzIHBlcm1zIGZyb20gJy4vcGVybXMnO1xuaW1wb3J0IHsgdmFsaWRhdGVGaWVsZFBhdHRlcm4sIHZhbGlkYXRlU3RyaW5nRmllbGRMZW5ndGgsIHRocm93SWZJbnZhbGlkIH0gZnJvbSAnLi92YWxpZGF0aW9uLWhlbHBlcnMnO1xuaW1wb3J0IHsgQnJvd3Nlck5ldHdvcmtDb25maWd1cmF0aW9uIH0gZnJvbSAnLi4vbmV0d29yay9uZXR3b3JrLWNvbmZpZ3VyYXRpb24nO1xuXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENPTlNUQU5UU1xuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuLyoqXG4gKiBNaW5pbXVtIGxlbmd0aCBmb3IgYnJvd3NlciBuYW1lXG4gKiBAaW50ZXJuYWxcbiAqL1xuY29uc3QgQlJPV1NFUl9OQU1FX01JTl9MRU5HVEggPSAxO1xuXG4vKipcbiAqIE1heGltdW0gbGVuZ3RoIGZvciBicm93c2VyIG5hbWVcbiAqIEBpbnRlcm5hbFxuICovXG5jb25zdCBCUk9XU0VSX05BTUVfTUFYX0xFTkdUSCA9IDQ4O1xuXG4vKipcbiAqIE1pbmltdW0gbGVuZ3RoIGZvciBicm93c2VyIHRhZ3NcbiAqIEBpbnRlcm5hbFxuICovXG5jb25zdCBCUk9XU0VSX1RBR19NSU5fTEVOR1RIID0gMTtcblxuLyoqXG4gKiBNYXhpbXVtIGxlbmd0aCBmb3IgYnJvd3NlciB0YWdzXG4gKiBAaW50ZXJuYWxcbiAqL1xuY29uc3QgQlJPV1NFUl9UQUdfTUFYX0xFTkdUSCA9IDI1NjtcblxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEludGVyZmFjZVxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuLyoqXG4gKiBJbnRlcmZhY2UgZm9yIEJyb3dzZXIgcmVzb3VyY2VzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSUJyb3dzZXJDdXN0b20gZXh0ZW5kcyBJUmVzb3VyY2UsIGlhbS5JR3JhbnRhYmxlLCBlYzIuSUNvbm5lY3RhYmxlIHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGJyb3dzZXIgcmVzb3VyY2VcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgYnJvd3NlckFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgaWQgb2YgdGhlIGJyb3dzZXJcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgYnJvd3NlcklkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBJQU0gcm9sZSB0aGF0IHByb3ZpZGVzIHBlcm1pc3Npb25zIGZvciB0aGUgYnJvd3NlciB0byBhY2Nlc3MgQVdTIHNlcnZpY2VzXG4gICAqL1xuICByZWFkb25seSBleGVjdXRpb25Sb2xlOiBpYW0uSVJvbGU7XG5cbiAgLyoqXG4gICAqIFRpbWVzdGFtcCB3aGVuIHRoZSBicm93c2VyIHdhcyBsYXN0IHVwZGF0ZWRcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgbGFzdFVwZGF0ZWRBdD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHN0YXR1cyBvZiB0aGUgYnJvd3NlclxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSBzdGF0dXM/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRpbWVzdGFtcCB3aGVuIHRoZSBicm93c2VyIHdhcyBjcmVhdGVkXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IGNyZWF0ZWRBdD86IHN0cmluZztcblxuICAvKipcbiAgICogR3JhbnRzIElBTSBhY3Rpb25zIHRvIHRoZSBJQU0gUHJpbmNpcGFsXG4gICAqL1xuICBncmFudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQ7XG4gIC8qKlxuICAgKiBHcmFudHMgYEdldGAgYW5kIGBMaXN0YCBhY3Rpb25zIG9uIHRoZSBCcm93c2VyXG4gICAqL1xuICBncmFudFJlYWQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQ7XG4gIC8qKlxuICAgKiBHcmFudHMgYEludm9rZWAsIGBTdGFydGAsIGFuZCBgVXBkYXRlYCBhY3Rpb25zIG9uIHRoZSBCcm93c2VyXG4gICAqL1xuICBncmFudFVzZShncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudDtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gTWV0cmljc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgZ2l2ZW4gbmFtZWQgbWV0cmljIGZvciB0aGlzIGJyb3dzZXIuXG4gICAqL1xuICBtZXRyaWMobWV0cmljTmFtZTogc3RyaW5nLCBkaW1lbnNpb25zOiBEaW1lbnNpb25zTWFwLCBwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgZ2l2ZW4gbmFtZWQgbWV0cmljIHJlbGF0ZWQgdG8gdGhlIEFQSSBvcGVyYXRpb24gcGVyZm9ybWVkIG9uIHRoaXMgYnJvd3Nlci5cbiAgICovXG4gIG1ldHJpY0ZvckFwaU9wZXJhdGlvbihtZXRyaWNOYW1lOiBzdHJpbmcsIG9wZXJhdGlvbjogc3RyaW5nLCBwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIG1ldHJpYyBtZWFzdXJpbmcgdGhlIGxhdGVuY3kgb2YgYSBzcGVjaWZpYyBBUEkgb3BlcmF0aW9uIHBlcmZvcm1lZCBvbiB0aGlzIGJyb3dzZXIuXG4gICAqL1xuICBtZXRyaWNMYXRlbmN5Rm9yQXBpT3BlcmF0aW9uKG9wZXJhdGlvbjogc3RyaW5nLCBwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIG1ldHJpYyBjb250YWluaW5nIHRoZSB0b3RhbCBudW1iZXIgb2YgQVBJIHJlcXVlc3RzIG1hZGUgZm9yIGEgc3BlY2lmaWMgYnJvd3NlciBvcGVyYXRpb24uXG4gICAqL1xuICBtZXRyaWNJbnZvY2F0aW9uc0ZvckFwaU9wZXJhdGlvbihvcGVyYXRpb246IHN0cmluZywgcHJvcHM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljO1xuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBtZXRyaWMgY29udGFpbmluZyB0aGUgbnVtYmVyIG9mIGVycm9ycyBmb3IgYSBzcGVjaWZpYyBBUEkgb3BlcmF0aW9uIHBlcmZvcm1lZCBvbiB0aGlzIGJyb3dzZXIuXG4gICAqL1xuICBtZXRyaWNFcnJvcnNGb3JBcGlPcGVyYXRpb24ob3BlcmF0aW9uOiBzdHJpbmcsIHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYztcblxuICAvKipcbiAgICogUmV0dXJuIGEgbWV0cmljIGNvbnRhaW5pbmcgdGhlIG51bWJlciBvZiB0aHJvdHRsZWQgcmVxdWVzdHMgZm9yIGEgc3BlY2lmaWMgQVBJIG9wZXJhdGlvbiBwZXJmb3JtZWQgb24gdGhpcyBicm93c2VyLlxuICAgKi9cbiAgbWV0cmljVGhyb3R0bGVzRm9yQXBpT3BlcmF0aW9uKG9wZXJhdGlvbjogc3RyaW5nLCBwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIG1ldHJpYyBjb250YWluaW5nIHRoZSBudW1iZXIgb2Ygc3lzdGVtIGVycm9ycyBmb3IgYSBzcGVjaWZpYyBBUEkgb3BlcmF0aW9uIHBlcmZvcm1lZCBvbiB0aGlzIGJyb3dzZXIuXG4gICAqL1xuICBtZXRyaWNTeXN0ZW1FcnJvcnNGb3JBcGlPcGVyYXRpb24ob3BlcmF0aW9uOiBzdHJpbmcsIHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYztcblxuICAvKipcbiAgICogUmV0dXJuIGEgbWV0cmljIGNvbnRhaW5pbmcgdGhlIG51bWJlciBvZiB1c2VyIGVycm9ycyBmb3IgYSBzcGVjaWZpYyBBUEkgb3BlcmF0aW9uIHBlcmZvcm1lZCBvbiB0aGlzIGJyb3dzZXIuXG4gICAqL1xuICBtZXRyaWNVc2VyRXJyb3JzRm9yQXBpT3BlcmF0aW9uKG9wZXJhdGlvbjogc3RyaW5nLCBwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIG1ldHJpYyBtZWFzdXJpbmcgdGhlIGR1cmF0aW9uIG9mIGJyb3dzZXIgc2Vzc2lvbnMuXG4gICAqL1xuICBtZXRyaWNTZXNzaW9uRHVyYXRpb24ocHJvcHM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljO1xuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBtZXRyaWMgY29udGFpbmluZyB0aGUgbnVtYmVyIG9mIHVzZXIgdGFrZW92ZXJzLlxuICAgKi9cbiAgbWV0cmljVGFrZU92ZXJDb3VudChwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIG1ldHJpYyBjb250YWluaW5nIHRoZSBudW1iZXIgb2YgdXNlciB0YWtlb3ZlcnMgcmVsZWFzZWQuXG4gICAqL1xuICBtZXRyaWNUYWtlT3ZlclJlbGVhc2VDb3VudChwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIG1ldHJpYyBtZWFzdXJpbmcgdGhlIGR1cmF0aW9uIG9mIHVzZXIgdGFrZW92ZXJzLlxuICAgKi9cbiAgbWV0cmljVGFrZU92ZXJEdXJhdGlvbihwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG59XG5cbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAqICAgICAgICAgICAgICA