UNPKG

@aws-cdk/aws-bedrock-agentcore-alpha

Version:

The CDK Construct Library for Amazon Bedrock

589 lines 82.4 kB
"use strict"; 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; }; 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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Runtime = 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 bedrockagentcore = require("aws-cdk-lib/aws-bedrockagentcore"); const ec2 = require("aws-cdk-lib/aws-ec2"); const iam = require("aws-cdk-lib/aws-iam"); const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource"); const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable"); const perms_1 = require("./perms"); const runtime_base_1 = require("./runtime-base"); const runtime_endpoint_1 = require("./runtime-endpoint"); const network_configuration_1 = require("../network/network-configuration"); const types_1 = require("./types"); const validation_helpers_1 = require("./validation-helpers"); /****************************************************************************** * Class *****************************************************************************/ /** * Bedrock Agent Core Runtime * Enables running containerized agents with specific network configurations, * security settings, and runtime artifacts. * * @resource AWS::BedrockAgentCore::Runtime * @see https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime.html */ let Runtime = (() => { let _classDecorators = [prop_injectable_1.propertyInjectable]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = runtime_base_1.RuntimeBase; let _instanceExtraInitializers = []; let _addEndpoint_decorators; var Runtime = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _addEndpoint_decorators = [(0, metadata_resource_1.MethodMetadata)()]; __esDecorate(this, null, _addEndpoint_decorators, { kind: "method", name: "addEndpoint", static: false, private: false, access: { has: obj => "addEndpoint" in obj, get: obj => obj.addEndpoint }, metadata: _metadata }, null, _instanceExtraInitializers); __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Runtime = _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.Runtime", version: "2.227.0-alpha.0" }; /** Uniquely identifies this class. */ static PROPERTY_INJECTION_ID = '@aws-cdk.aws-bedrock-agentcore-alpha.Runtime'; /** * Import an existing Agent Runtime using attributes * This allows you to reference an Agent Runtime that was created outside of CDK * * @param scope The construct scope * @param id The construct id * @param attrs The attributes of the existing Agent Runtime * @returns An IBedrockAgentRuntime instance representing the imported runtime */ static fromAgentRuntimeAttributes(scope, id, attrs) { try { jsiiDeprecationWarnings._aws_cdk_aws_bedrock_agentcore_alpha_AgentRuntimeAttributes(attrs); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromAgentRuntimeAttributes); } throw error; } class ImportedBedrockAgentRuntime extends runtime_base_1.RuntimeBase { agentRuntimeArn = attrs.agentRuntimeArn; agentRuntimeId = attrs.agentRuntimeId; agentRuntimeName = attrs.agentRuntimeName; agentRuntimeVersion = attrs.agentRuntimeVersion; agentStatus = attrs.agentStatus; description = attrs.description; createdAt = attrs.createdAt; lastUpdatedAt = attrs.lastUpdatedAt; role; grantPrincipal; constructor(s, i) { super(s, i); this.role = iam.Role.fromRoleArn(this, 'Role', attrs.roleArn); this.grantPrincipal = this.role; if (attrs.securityGroups) { this._connections = new ec2.Connections({ securityGroups: attrs.securityGroups, }); } } } return new ImportedBedrockAgentRuntime(scope, id); } /** * The ARN of the agent runtime * @attribute * @returns a token representing the ARN of this agent runtime */ agentRuntimeArn = __runInitializers(this, _instanceExtraInitializers); /** * The unique identifier of the agent runtime * @attribute * @returns a token representing the ID of this agent runtime */ agentRuntimeId; /** * The name of the agent runtime * @attribute * @returns a token representing the name of this agent runtime */ agentRuntimeName; role; /** * The version of the agent runtime * @attribute * @returns a token representing the version of this agent runtime */ agentRuntimeVersion; /** * The status of the agent runtime * @attribute * @returns a token representing the status of this agent runtime */ agentStatus; /** * Optional description for the agent runtime */ description; /** * The timestamp when the agent runtime was created * @attribute * @returns a token representing the creation timestamp of this agent runtime */ createdAt; /** * The timestamp when the agent runtime was last updated * @attribute * @returns a token representing the last update timestamp of this agent runtime */ lastUpdatedAt; grantPrincipal; runtimeResource; /** * The artifact configuration for the agent runtime */ agentRuntimeArtifact; networkConfiguration; protocolConfiguration; authorizerConfiguration; constructor(scope, id, props) { super(scope, id); try { jsiiDeprecationWarnings._aws_cdk_aws_bedrock_agentcore_alpha_RuntimeProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, Runtime); } throw error; } // CDK Analytics Telemetry (0, metadata_resource_1.addConstructMetadata)(this, props); this.agentRuntimeName = props.runtimeName; this.validateRuntimeName(); this.description = props.description; if (this.description) { this.validateDescription(); } if (props.environmentVariables) { this.validateEnvironmentVariables(props.environmentVariables); } if (props.tags) { this.validateTags(props.tags); } if (props.executionRole) { this.role = props.executionRole; if (!aws_cdk_lib_1.Token.isUnresolved(props.executionRole.roleArn)) { this.validateRoleArn(props.executionRole.roleArn); } } else { this.role = new iam.Role(this, 'ExecutionRole', { assumedBy: new iam.ServicePrincipal('bedrock-agentcore.amazonaws.com'), description: 'Execution role for Bedrock Agent Core Runtime', maxSessionDuration: aws_cdk_lib_1.Duration.hours(8), }); } this.addExecutionRolePermissions(); this.grantPrincipal = this.role; this.agentRuntimeArtifact = props.agentRuntimeArtifact; // Set up network configuration with VPC support this.networkConfiguration = props.networkConfiguration ?? network_configuration_1.RuntimeNetworkConfiguration.usingPublicNetwork(); // 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; } this.protocolConfiguration = props.protocolConfiguration ?? types_1.ProtocolType.HTTP; this.authorizerConfiguration = props.authorizerConfiguration; const cfnProps = { agentRuntimeName: this.agentRuntimeName, roleArn: this.role.roleArn, agentRuntimeArtifact: aws_cdk_lib_1.Lazy.any({ produce: () => this.renderAgentRuntimeArtifact(), }), networkConfiguration: aws_cdk_lib_1.Lazy.any({ produce: () => this.networkConfiguration._render(this._connections), }), protocolConfiguration: aws_cdk_lib_1.Lazy.string({ produce: () => this.protocolConfiguration, }), description: props.description, environmentVariables: aws_cdk_lib_1.Lazy.any({ produce: () => this.renderEnvironmentVariables(props.environmentVariables), }), tags: props.tags ?? {}, }; if (props.authorizerConfiguration) { cfnProps.authorizerConfiguration = aws_cdk_lib_1.Lazy.any({ produce: () => this.authorizerConfiguration._render(), }); } this.runtimeResource = new bedrockagentcore.CfnRuntime(this, 'Resource', cfnProps); // Add dependency on the role (for both custom and auto-created roles) // This ensures the Runtime waits for the role and all its policies (including ECR permissions) to be created this.runtimeResource.node.addDependency(this.role); this.agentRuntimeId = this.runtimeResource.attrAgentRuntimeId; this.agentRuntimeArn = this.runtimeResource.attrAgentRuntimeArn; this.agentStatus = this.runtimeResource.attrStatus; this.agentRuntimeVersion = this.runtimeResource.attrAgentRuntimeVersion; this.createdAt = this.runtimeResource.attrCreatedAt; this.lastUpdatedAt = this.runtimeResource.attrLastUpdatedAt; } /** * Renders the environment variables for CloudFormation * @internal */ renderEnvironmentVariables(envVars) { if (!envVars || Object.keys(envVars).length === 0) { return undefined; } return envVars; } /** * Adds proper permissions to the execution role for the agent runtime * Based on: https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html */ addExecutionRolePermissions() { const region = aws_cdk_lib_1.Stack.of(this).region; const account = aws_cdk_lib_1.Stack.of(this).account; // CloudWatch Logs - Log Group operations this.role.addToPrincipalPolicy(new iam.PolicyStatement({ sid: 'LogGroupAccess', effect: iam.Effect.ALLOW, actions: perms_1.RUNTIME_LOGS_GROUP_ACTIONS, resources: [`arn:${aws_cdk_lib_1.Stack.of(this).partition}:logs:${region}:${account}:log-group:/aws/bedrock-agentcore/runtimes/*`], })); // CloudWatch Logs - Describe all log groups this.role.addToPrincipalPolicy(new iam.PolicyStatement({ sid: 'DescribeLogGroups', effect: iam.Effect.ALLOW, actions: perms_1.RUNTIME_LOGS_DESCRIBE_ACTIONS, resources: [`arn:${aws_cdk_lib_1.Stack.of(this).partition}:logs:${region}:${account}:log-group:*`], })); // CloudWatch Logs - Log Stream operations this.role.addToPrincipalPolicy(new iam.PolicyStatement({ sid: 'LogStreamAccess', effect: iam.Effect.ALLOW, actions: perms_1.RUNTIME_LOGS_STREAM_ACTIONS, resources: [`arn:${aws_cdk_lib_1.Stack.of(this).partition}:logs:${region}:${account}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*`], })); // X-Ray Tracing - must be * for tracing this.role.addToPrincipalPolicy(new iam.PolicyStatement({ sid: 'XRayAccess', effect: iam.Effect.ALLOW, actions: perms_1.RUNTIME_XRAY_ACTIONS, resources: ['*'], })); // CloudWatch Metrics - scoped to bedrock-agentcore namespace this.role.addToPrincipalPolicy(new iam.PolicyStatement({ sid: 'CloudWatchMetrics', effect: iam.Effect.ALLOW, actions: perms_1.RUNTIME_CLOUDWATCH_METRICS_ACTIONS, resources: ['*'], conditions: { StringEquals: { 'cloudwatch:namespace': perms_1.RUNTIME_CLOUDWATCH_NAMESPACE, }, }, })); // Bedrock AgentCore Workload Identity Access // Note: The agent name will be determined at runtime, so we use a wildcard pattern this.role.addToPrincipalPolicy(new iam.PolicyStatement({ sid: 'GetAgentAccessToken', effect: iam.Effect.ALLOW, actions: perms_1.RUNTIME_WORKLOAD_IDENTITY_ACTIONS, resources: [ `arn:${aws_cdk_lib_1.Stack.of(this).partition}:bedrock-agentcore:${region}:${account}:workload-identity-directory/default`, `arn:${aws_cdk_lib_1.Stack.of(this).partition}:bedrock-agentcore:${region}:${account}:workload-identity-directory/default/workload-identity/*`, ], })); } /** * Renders the artifact configuration for CloudFormation * @internal */ renderAgentRuntimeArtifact() { // set permission with bind this.agentRuntimeArtifact.bind(this, this); const config = this.agentRuntimeArtifact._render(); const containerUri = config.containerUri; if (containerUri) { this.validateContainerUri(containerUri); } return { containerConfiguration: { containerUri: containerUri, }, }; } /** * Validates the runtime name format * Pattern: ^[a-zA-Z][a-zA-Z0-9_]{0,47}$ * @throws Error if validation fails */ validateRuntimeName() { // Skip validation if the name contains CDK tokens (unresolved values) if (aws_cdk_lib_1.Token.isUnresolved(this.agentRuntimeName)) { return; } // Validate length const lengthErrors = (0, validation_helpers_1.validateStringField)({ value: this.agentRuntimeName, fieldName: 'Runtime name', minLength: 1, maxLength: 48, }); // Validate pattern const patternErrors = (0, validation_helpers_1.validateFieldPattern)(this.agentRuntimeName, 'Runtime name', /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, 'Runtime name must start with a letter and contain only letters, numbers, and underscores'); // Combine and throw if any errors const allErrors = [...lengthErrors, ...patternErrors]; if (allErrors.length > 0) { throw new validation_helpers_1.ValidationError(allErrors.join('\n')); } } /** * Validates the description format * Must be between 1 and 1200 characters (per CloudFormation specification) * @throws Error if validation fails */ validateDescription() { // Skip validation if the description contains CDK tokens (unresolved values) if (aws_cdk_lib_1.Token.isUnresolved(this.description)) { return; } if (this.description) { const errors = (0, validation_helpers_1.validateStringField)({ value: this.description, fieldName: 'Description', minLength: 1, maxLength: 1200, }); if (errors.length > 0) { throw new validation_helpers_1.ValidationError(errors.join('\n')); } } } /** * Validates environment variables * - Maximum 50 entries * - Key: 1-100 characters * - Value: 0-2048 characters (per CloudFormation specification) * @throws Error if validation fails */ validateEnvironmentVariables(envVars) { const entries = Object.entries(envVars); // Validate number of entries (0-50) if (entries.length > 50) { throw new validation_helpers_1.ValidationError(`Too many environment variables: ${entries.length}. Maximum allowed is 50`); } for (const [key, value] of entries) { // Skip validation if key or value contains CDK tokens if (aws_cdk_lib_1.Token.isUnresolved(key) || aws_cdk_lib_1.Token.isUnresolved(value)) { continue; } // Validate key length const lengthErrors = (0, validation_helpers_1.validateStringField)({ value: key, fieldName: `Environment variable key '${key}'`, minLength: 1, maxLength: 100, }); // Validate key pattern const patternErrors = (0, validation_helpers_1.validateFieldPattern)(key, `Environment variable key '${key}'`, /^[a-zA-Z_][a-zA-Z0-9_]*$/, `Environment variable key '${key}' must start with a letter or underscore and contain only letters, numbers, and underscores`); // Combine and throw if any errors const allErrors = [...lengthErrors, ...patternErrors]; if (allErrors.length > 0) { throw new validation_helpers_1.ValidationError(allErrors.join('\n')); } // Validate value length (0-2048 characters per CloudFormation) if (value.length > 2048) { throw new validation_helpers_1.ValidationError(`Invalid environment variable value length for key '${key}': ${value.length} characters. ` + 'Values must not exceed 2048 characters'); } } } /** * Validates the tags format * @param tags The tags object to validate * @throws Error if validation fails */ validateTags(tags) { // Validate each tag key and value for (const [key, value] of Object.entries(tags)) { // Skip validation if key or value contains CDK tokens if (aws_cdk_lib_1.Token.isUnresolved(key) || aws_cdk_lib_1.Token.isUnresolved(value)) { continue; } // Validate tag key length const keyLengthErrors = (0, validation_helpers_1.validateStringField)({ value: key, fieldName: `Tag key "${key}"`, minLength: 1, maxLength: 256, }); // Validate tag key pattern const keyPatternErrors = (0, validation_helpers_1.validateFieldPattern)(key, `Tag key "${key}"`, /^[a-zA-Z0-9\s._:/=+@-]*$/, `Tag key "${key}" can only contain letters (a-z, A-Z), numbers (0-9), spaces, and special characters (._:/=+@-)`); // Combine key errors and throw if any const keyErrors = [...keyLengthErrors, ...keyPatternErrors]; if (keyErrors.length > 0) { throw new validation_helpers_1.ValidationError(keyErrors.join('\n')); } if (value === undefined || value === null) { throw new validation_helpers_1.ValidationError(`Tag value for key "${key}" cannot be null or undefined`); } // Validate tag value length const valueLengthErrors = (0, validation_helpers_1.validateStringField)({ value: value, fieldName: `Tag value for key "${key}"`, minLength: 0, maxLength: 256, }); // Validate tag value pattern const valuePatternErrors = (0, validation_helpers_1.validateFieldPattern)(value, `Tag value for key "${key}"`, /^[a-zA-Z0-9\s._:/=+@-]*$/, `Tag value for key "${key}" can only contain letters (a-z, A-Z), numbers (0-9), spaces, and special characters (._:/=+@-)`); // Combine value errors and throw if any const valueErrors = [...valueLengthErrors, ...valuePatternErrors]; if (valueErrors.length > 0) { throw new validation_helpers_1.ValidationError(valueErrors.join('\n')); } } } /** * Validates the container URI format */ validateContainerUri(uri) { // Skip validation if the URI contains CDK tokens (unresolved values) if (aws_cdk_lib_1.Token.isUnresolved(uri)) { // Add a warning that validation will be skipped for token-based URIs aws_cdk_lib_1.Annotations.of(this).addInfo('Container URI validation skipped as it contains unresolved CDK tokens. ' + 'The URI will be validated at deployment time.'); return; } // Only validate if the URI is a concrete string (not a token) const pattern = /^\d{12}\.dkr\.ecr\.([a-z0-9-]+)\.amazonaws\.com\/((?:[a-z0-9]+(?:[._-][a-z0-9]+)*\/)*[a-z0-9]+(?:[._-][a-z0-9]+)*)([:@]\S+)$/; if (!pattern.test(uri)) { throw new validation_helpers_1.ValidationError(`Invalid container URI format: ${uri}. Must be a valid ECR URI (e.g., 123456789012.dkr.ecr.us-west-2.amazonaws.com/my-agent:latest)`); } } /** * Validates the IAM role ARN format and structure * @throws Error if validation fails */ validateRoleArn(roleArn) { // Validate basic ARN format for IAM roles const arnPattern = /^arn:[a-z\-]+:iam::\d{12}:role\/[a-zA-Z0-9+=,.@\-_\/]+$/; if (!arnPattern.test(roleArn)) { throw new validation_helpers_1.ValidationError(`Invalid IAM role ARN format: ${roleArn}. ` + 'Expected format: arn:<partition>:iam::<account-id>:role/<role-name> or arn:<partition>:iam::<account-id>:role/<path>/<role-name>'); } // Parse the ARN components using CDK's Arn.split() // Use SLASH_RESOURCE_NAME format for IAM roles (which use format: role/role-name or role/path/to/role-name) const arnComponents = aws_cdk_lib_1.Arn.split(roleArn, aws_cdk_lib_1.ArnFormat.SLASH_RESOURCE_NAME); if (arnComponents.service !== 'iam') { throw new validation_helpers_1.ValidationError(`Invalid service in ARN: ${arnComponents.service}. Expected 'iam' for IAM role ARN.`); } const accountId = arnComponents.account; if (!accountId || !/^\d{12}$/.test(accountId)) { throw new validation_helpers_1.ValidationError(`Invalid AWS account ID in role ARN: ${accountId}. Must be a 12-digit number.`); } // Extract role name from resource // For IAM roles, resource will be "role" and resourceName will be the role name (with optional path) const resource = arnComponents.resource; const resourceName = arnComponents.resourceName; if (resource !== 'role') { throw new validation_helpers_1.ValidationError(`Invalid resource type in ARN: ${resource}. Expected 'role' for IAM role ARN.`); } if (!resourceName) { throw new validation_helpers_1.ValidationError('Role name is missing in the ARN'); } else { const rolePathParts = resourceName.split('/'); const roleName = rolePathParts[rolePathParts.length - 1]; if (roleName.length > 64) { throw new validation_helpers_1.ValidationError(`Role name exceeds maximum length of 64 characters: ${roleName}`); } } const stackAccount = aws_cdk_lib_1.Stack.of(this).account; if (!aws_cdk_lib_1.Token.isUnresolved(stackAccount) && accountId !== stackAccount) { aws_cdk_lib_1.Annotations.of(this).addWarning(`IAM role is from a different account (${accountId}) than the stack account (${stackAccount}). ` + 'Ensure cross-account permissions are properly configured.'); } // Validate the region (IAM is global, so region should be empty) const region = arnComponents.region; const stackRegion = aws_cdk_lib_1.Stack.of(this).region; if (region && region !== '' && region !== stackRegion && !aws_cdk_lib_1.Token.isUnresolved(stackRegion)) { aws_cdk_lib_1.Annotations.of(this).addWarning(`IAM role ARN contains a region (${region}) that doesn't match the stack region (${stackRegion}). ` + 'IAM is a global service, so this might be intentional.'); } } /** * Add an endpoint to this runtime * This is a convenience method that creates a RuntimeEndpoint associated with this runtime * * @param endpointName The name of the endpoint * @param options Optional configuration for the endpoint * @returns The created RuntimeEndpoint */ addEndpoint(endpointName, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_bedrock_agentcore_alpha_AddEndpointOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addEndpoint); } throw error; } // Create the endpoint (security configuration is no longer supported) const endpoint = new runtime_endpoint_1.RuntimeEndpoint(this, `Endpoint${endpointName}`, { endpointName: endpointName, agentRuntimeId: this.agentRuntimeId, agentRuntimeVersion: options?.version ?? this.agentRuntimeVersion ?? '1', description: options?.description, }); // Add dependency: endpoint must wait for runtime to be created endpoint.node.addDependency(this.runtimeResource); return endpoint; } static { __runInitializers(_classThis, _classExtraInitializers); } }; return Runtime = _classThis; })(); exports.Runtime = Runtime; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJ1bnRpbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQ0EsNkNBQXdGO0FBQ3hGLHFFQUFxRTtBQUNyRSwyQ0FBMkM7QUFDM0MsMkNBQTJDO0FBQzNDLDhFQUE4RjtBQUM5RiwwRUFBMEU7QUFFMUUsbUNBUWlCO0FBR2pCLGlEQUEyRjtBQUMzRix5REFBcUQ7QUFDckQsNEVBQStFO0FBQy9FLG1DQUF1QztBQUN2Qyw2REFBa0c7QUEwRmxHOzsrRUFFK0U7QUFFL0U7Ozs7Ozs7R0FPRztJQUVVLE9BQU87NEJBRG5CLG9DQUFrQjs7OztzQkFDVSwwQkFBVzs7O3VCQUFuQixTQUFRLFdBQVc7Ozs7dUNBNmlCckMsSUFBQSxrQ0FBYyxHQUFFO1lBQ2pCLG9MQUFPLFdBQVcsNkRBZ0JqQjtZQTlqQkgsNktBK2pCQzs7Ozs7UUE5akJDLHNDQUFzQztRQUMvQixNQUFNLENBQVUscUJBQXFCLEdBQVcsOENBQThDLENBQUM7UUFFdEc7Ozs7Ozs7O1dBUUc7UUFDSSxNQUFNLENBQUMsMEJBQTBCLENBQ3RDLEtBQWdCLEVBQ2hCLEVBQVUsRUFDVixLQUE2Qjs7Ozs7Ozs7OztZQUU3QixNQUFNLDJCQUE0QixTQUFRLDBCQUFXO2dCQUNuQyxlQUFlLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQztnQkFDeEMsY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUM7Z0JBQ3RDLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQztnQkFDMUMsbUJBQW1CLEdBQUcsS0FBSyxDQUFDLG1CQUFtQixDQUFDO2dCQUNoRCxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztnQkFDaEMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7Z0JBQ2hDLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO2dCQUM1QixhQUFhLEdB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QyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUM7WUFDMUMsSUFBSSxNQUFNLElBQUksTUFBTSxLQUFLLEVBQUUsSUFBSSxNQUFNLEtBQUssV0FBVyxJQUFJLENBQUMsbUJBQUssQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztnQkFDMUYseUJBQVcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUM3QixtQ0FBbUMsTUFBTSwwQ0FBMEMsV0FBVyxLQUFLO29CQUNuRyx3REFBd0QsQ0FDekQsQ0FBQztZQUNKLENBQUM7U0FDRjtRQUVEOzs7Ozs7O1dBT0c7UUFFSSxXQUFXLENBQ2hCLFlBQW9CLEVBQ3BCLE9BQTRCOzs7Ozs7Ozs7O1lBRTVCLHNFQUFzRTtZQUN0RSxNQUFNLFFBQVEsR0FBRyxJQUFJLGtDQUFlLENBQUMsSUFBSSxFQUFFLFdBQVcsWUFBWSxFQUFFLEVBQUU7Z0JBQ3BFLFlBQVksRUFBRSxZQUFZO2dCQUMxQixjQUFjLEVBQUUsSUFBSSxDQUFDLGNBQWM7Z0JBQ25DLG1CQUFtQixFQUFFLE9BQU8sRUFBRSxPQUFPLElBQUksSUFBSSxDQUFDLG1CQUFtQixJQUFJLEdBQUc7Z0JBQ3hFLFdBQVcsRUFBRSxPQUFPLEVBQUUsV0FBVzthQUNsQyxDQUFDLENBQUM7WUFFSCwrREFBK0Q7WUFDL0QsUUFBUSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRWxELE9BQU8sUUFBUSxDQUFDO1NBQ2pCOztZQTlqQlUsdURBQU87Ozs7O0FBQVAsMEJBQU8iLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCB7IER1cmF0aW9uLCBTdGFjaywgQW5ub3RhdGlvbnMsIFRva2VuLCBBcm4sIEFybkZvcm1hdCwgTGF6eSB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGJlZHJvY2thZ2VudGNvcmUgZnJvbSAnYXdzLWNkay1saWIvYXdzLWJlZHJvY2thZ2VudGNvcmUnO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgYWRkQ29uc3RydWN0TWV0YWRhdGEsIE1ldGhvZE1ldGFkYXRhIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvbWV0YWRhdGEtcmVzb3VyY2UnO1xuaW1wb3J0IHsgcHJvcGVydHlJbmplY3RhYmxlIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvcHJvcC1pbmplY3RhYmxlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHtcbiAgUlVOVElNRV9MT0dTX0dST1VQX0FDVElPTlMsXG4gIFJVTlRJTUVfTE9HU19ERVNDUklCRV9BQ1RJT05TLFxuICBSVU5USU1FX0xPR1NfU1RSRUFNX0FDVElPTlMsXG4gIFJVTlRJTUVfWFJBWV9BQ1RJT05TLFxuICBSVU5USU1FX0NMT1VEV0FUQ0hfTUVUUklDU19BQ1RJT05TLFxuICBSVU5USU1FX0NMT1VEV0FUQ0hfTkFNRVNQQUNFLFxuICBSVU5USU1FX1dPUktMT0FEX0lERU5USVRZX0FDVElPTlMsXG59IGZyb20gJy4vcGVybXMnO1xuaW1wb3J0IHsgQWdlbnRSdW50aW1lQXJ0aWZhY3QgfSBmcm9tICcuL3J1bnRpbWUtYXJ0aWZhY3QnO1xuaW1wb3J0IHsgUnVudGltZUF1dGhvcml6ZXJDb25maWd1cmF0aW9uIH0gZnJvbSAnLi9ydW50aW1lLWF1dGhvcml6ZXItY29uZmlndXJhdGlvbic7XG5pbXBvcnQgeyBSdW50aW1lQmFzZSwgSUJlZHJvY2tBZ2VudFJ1bnRpbWUsIEFnZW50UnVudGltZUF0dHJpYnV0ZXMgfSBmcm9tICcuL3J1bnRpbWUtYmFzZSc7XG5pbXBvcnQgeyBSdW50aW1lRW5kcG9pbnQgfSBmcm9tICcuL3J1bnRpbWUtZW5kcG9pbnQnO1xuaW1wb3J0IHsgUnVudGltZU5ldHdvcmtDb25maWd1cmF0aW9uIH0gZnJvbSAnLi4vbmV0d29yay9uZXR3b3JrLWNvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgUHJvdG9jb2xUeXBlIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyB2YWxpZGF0ZVN0cmluZ0ZpZWxkLCBWYWxpZGF0aW9uRXJyb3IsIHZhbGlkYXRlRmllbGRQYXR0ZXJuIH0gZnJvbSAnLi92YWxpZGF0aW9uLWhlbHBlcnMnO1xuXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC