kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
353 lines (351 loc) • 59.7 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AiAssistantConfig = AiAssistantConfig;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
var _react = _interopRequireWildcard(require("react"));
var _styledComponents = _interopRequireDefault(require("styled-components"));
var _reactRedux = require("react-redux");
var _components = require("@kepler.gl/components");
var _apiKey = _interopRequireDefault(require("../icons/api-key"));
var _models = require("../config/models");
var _usehooksTs = require("usehooks-ts");
var _core = require("@openassistant/core");
var _actions = require("../actions");
var _reactIntl = require("react-intl");
var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8; // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
var SectionTitle = _styledComponents["default"].div(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2["default"])(["\n font-size: ", ";\n color: ", ";\n text-transform: capitalize;\n"])), function (props) {
return props.theme.inputFontSize;
}, function (props) {
return props.theme.effectPanelTextSecondary1;
});
var StyledAiAssistantConfig = _styledComponents["default"].div(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2["default"])(["\n padding: 12px;\n font-size: ", ";\n display: flex;\n flex-direction: column;\n gap: 12px;\n width: 100%;\n height: 100%;\n\n .api-key-input {\n box-shadow: ", ";\n width: 100%;\n .api-key-input__icon {\n position: absolute;\n height: ", "px;\n width: 30px;\n padding-left: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: ", ";\n }\n\n input {\n padding: 4px 36px;\n height: ", "px;\n caret-color: unset;\n }\n }\n"])), function (props) {
return props.theme.primaryBtnFontSizeDefault;
}, function (props) {
return props.theme.boxShadow;
}, function (props) {
return props.theme.geocoderInputHeight;
}, function (props) {
return props.theme.subtextColor;
}, function (props) {
return props.theme.geocoderInputHeight;
});
// Ollama model input wrapper: checkbox + 'Input Model Name:' + input
// all children element have width based on the content
var OllamaModelInputWrapper = _styledComponents["default"].div(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2["default"])(["\n display: flex;\n flex-direction: row;\n gap: 4px;\n align-items: center;\n"])));
var StyledWrapper = _styledComponents["default"].div(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2["default"])(["\n display: flex;\n justify-content: space-between;\n align-items: center;\n"])));
var StyledItemSelector = (0, _styledComponents["default"])(_components.ItemSelector)(_templateObject5 || (_templateObject5 = (0, _taggedTemplateLiteral2["default"])(["\n .item-selector__dropdown {\n padding-left: 10px;\n border-radius: 4px;\n }\n .active {\n border-color: ", ";\n border-radius: 4px 4px 0px 0px !important;\n }\n width: 100%;\n"])), function (props) {
return props.theme.activeColor;
});
var StyleSliderWrapper = _styledComponents["default"].div(_templateObject6 || (_templateObject6 = (0, _taggedTemplateLiteral2["default"])(["\n width: 100%;\n align-self: flex-start;\n height: 32px;\n display: flex;\n align-items: center;\n .kg-range-slider__input {\n height: 32px;\n text-align: center;\n padding: 3px 6px;\n }\n .kg-slider {\n padding-left: 6px;\n }\n .kg-range-slider {\n padding: 0px !important;\n }\n"])));
var StyledButton = _styledComponents["default"].div(_templateObject7 || (_templateObject7 = (0, _taggedTemplateLiteral2["default"])(["\n width: 100%;\n align-self: flex-start;\n margin-top: 12px;\n\n button div {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-right: 4px;\n }\n"])));
var StyleErrorMessage = _styledComponents["default"].div(_templateObject8 || (_templateObject8 = (0, _taggedTemplateLiteral2["default"])(["\n font-size: ", ";\n background-color: ", ";\n border-radius: 4px;\n padding: 4px 8px;\n color: ", ";\n"])), function (props) {
return props.theme.primaryBtnFontSizeDefault;
}, function (props) {
return props.theme.errorColor;
}, function (props) {
return props.theme.errorTextColor;
});
var RangeSlider = _components.appInjector.get(_components.RangeSliderFactory);
function AiAssistantConfig() {
var dispatch = (0, _reactRedux.useDispatch)();
var aiAssistantConfig = (0, _reactRedux.useSelector)(function (state) {
return state.demo.aiAssistant.config;
});
var intl = (0, _reactIntl.useIntl)();
var _useLocalStorage = (0, _usehooksTs.useLocalStorage)('ai-assistant-provider', aiAssistantConfig.provider || 'openai'),
_useLocalStorage2 = (0, _slicedToArray2["default"])(_useLocalStorage, 2),
provider = _useLocalStorage2[0],
setProvider = _useLocalStorage2[1];
var _useLocalStorage3 = (0, _usehooksTs.useLocalStorage)('ai-assistant-model', aiAssistantConfig.model || _models.PROVIDER_MODELS[provider][0]),
_useLocalStorage4 = (0, _slicedToArray2["default"])(_useLocalStorage3, 2),
model = _useLocalStorage4[0],
setModel = _useLocalStorage4[1];
var _useLocalStorage5 = (0, _usehooksTs.useLocalStorage)('ai-assistant-api-key', aiAssistantConfig.apiKey || ''),
_useLocalStorage6 = (0, _slicedToArray2["default"])(_useLocalStorage5, 2),
apiKey = _useLocalStorage6[0],
setApiKey = _useLocalStorage6[1];
var _useLocalStorage7 = (0, _usehooksTs.useLocalStorage)('ai-assistant-temperature', aiAssistantConfig.temperature || 0.0),
_useLocalStorage8 = (0, _slicedToArray2["default"])(_useLocalStorage7, 2),
temperature = _useLocalStorage8[0],
setTemperature = _useLocalStorage8[1];
var _useLocalStorage9 = (0, _usehooksTs.useLocalStorage)('ai-assistant-top-p', aiAssistantConfig.topP || 1.0),
_useLocalStorage10 = (0, _slicedToArray2["default"])(_useLocalStorage9, 2),
topP = _useLocalStorage10[0],
setTopP = _useLocalStorage10[1];
var _useLocalStorage11 = (0, _usehooksTs.useLocalStorage)('ai-assistant-base-url', aiAssistantConfig.baseUrl || _models.PROVIDER_DEFAULT_BASE_URLS[provider]),
_useLocalStorage12 = (0, _slicedToArray2["default"])(_useLocalStorage11, 2),
baseUrl = _useLocalStorage12[0],
setBaseUrl = _useLocalStorage12[1];
var _useLocalStorage13 = (0, _usehooksTs.useLocalStorage)('ai-assistant-mapbox-token', aiAssistantConfig.mapboxToken || ''),
_useLocalStorage14 = (0, _slicedToArray2["default"])(_useLocalStorage13, 2),
mapboxToken = _useLocalStorage14[0],
setMapboxToken = _useLocalStorage14[1];
var _useState = (0, _react.useState)(false),
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
ollamaModelInputChecked = _useState2[0],
setOllamaModelInputChecked = _useState2[1];
var _useState3 = (0, _react.useState)(''),
_useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
ollamaModelInputValue = _useState4[0],
setOllamaModelInputValue = _useState4[1];
var _useState5 = (0, _react.useState)(false),
_useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
connectionError = _useState6[0],
setConnectionError = _useState6[1];
var _useState7 = (0, _react.useState)(''),
_useState8 = (0, _slicedToArray2["default"])(_useState7, 2),
errorMessage = _useState8[0],
setErrorMessage = _useState8[1];
var _useState9 = (0, _react.useState)(false),
_useState10 = (0, _slicedToArray2["default"])(_useState9, 2),
isRunning = _useState10[0],
setIsRunning = _useState10[1];
var onAiProviderSelect = function onAiProviderSelect(value) {
if (typeof value === 'string') {
setProvider(value);
setModel(_models.PROVIDER_MODELS[value][0]);
setBaseUrl(_models.PROVIDER_DEFAULT_BASE_URLS[value]);
setConnectionError(false);
setErrorMessage('');
}
};
var onLLMModelSelect = function onLLMModelSelect(value) {
if (typeof value === 'string') {
setModel(value);
}
};
var onApiKeyChange = function onApiKeyChange(e) {
setApiKey(e.target.value);
// reset previous key error if any
setConnectionError(false);
setErrorMessage('');
};
var onTemperatureChange = function onTemperatureChange(value) {
setTemperature(value[1]);
};
var onTopPChange = function onTopPChange(value) {
setTopP(value[1]);
};
var onBaseUrlChange = function onBaseUrlChange(e) {
setBaseUrl(e.target.value);
setConnectionError(false);
setErrorMessage('');
};
var onMapboxTokenChange = function onMapboxTokenChange(e) {
setMapboxToken(e.target.value);
};
var onOllamaModelInputChecked = function onOllamaModelInputChecked(e) {
setOllamaModelInputChecked(e.target.checked);
if (!e.target.checked) {
// use model from selector
setModel('');
}
};
var onOllamaModelInputValueChange = function onOllamaModelInputValueChange(e) {
setOllamaModelInputValue(e.target.value);
setModel(e.target.value);
};
var onStartChat = /*#__PURE__*/function () {
var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
var timeoutPromise, AssistantModel, success, _errorMessage;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
setIsRunning(true);
_context.prev = 1;
timeoutPromise = new Promise(function (_, reject) {
setTimeout(function () {
return reject(new Error('Connection timeout after 15 seconds'));
}, 15000);
});
_context.next = 5;
return (0, _core.GetAssistantModelByProvider)({
provider: provider
});
case 5:
AssistantModel = _context.sent;
if (!(!AssistantModel || !AssistantModel.configure || !AssistantModel.testConnection)) {
_context.next = 8;
break;
}
throw new Error('Failed to initialize AI model');
case 8:
// configure model
AssistantModel.configure({
model: model,
baseURL: baseUrl || _models.PROVIDER_DEFAULT_BASE_URLS[provider],
apiKey: apiKey,
temperature: Number(temperature),
topP: Number(topP)
});
_context.next = 11;
return Promise.race([AssistantModel.testConnection(apiKey, model), timeoutPromise]);
case 11:
success = _context.sent;
_errorMessage = !success ? provider === 'ollama' ? 'Connection failed: maybe invalid Base URL' : 'Connection failed: maybe invalid API Key or Base URL' : '';
setConnectionError(!success);
setErrorMessage(_errorMessage);
dispatch((0, _actions.updateAiAssistantConfig)({
provider: provider,
model: model,
apiKey: apiKey,
baseUrl: baseUrl || _models.PROVIDER_DEFAULT_BASE_URLS[provider],
isReady: success,
temperature: temperature,
topP: topP,
mapboxToken: mapboxToken
}));
_context.next = 22;
break;
case 18:
_context.prev = 18;
_context.t0 = _context["catch"](1);
setConnectionError(true);
setErrorMessage(_context.t0 instanceof Error ? _context.t0.message : 'Connection failed');
case 22:
_context.prev = 22;
setIsRunning(false);
return _context.finish(22);
case 25:
case "end":
return _context.stop();
}
}, _callee, null, [[1, 18, 22, 25]]);
}));
return function onStartChat() {
return _ref.apply(this, arguments);
};
}();
return /*#__PURE__*/_react["default"].createElement(StyledAiAssistantConfig, {
className: "ai-assistant-config__type"
}, /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, {
id: "aiAssistantManager.aiProvider"
}))), /*#__PURE__*/_react["default"].createElement(StyledWrapper, null, /*#__PURE__*/_react["default"].createElement(StyledItemSelector, {
selectedItems: provider,
options: Object.keys(_models.PROVIDER_MODELS),
multiSelect: false,
disabled: false,
onChange: onAiProviderSelect,
filterOption: "name",
getOptionValue: function getOptionValue(op) {
return op;
},
displayOption: function displayOption(op) {
return op;
},
searchable: false,
showArrow: true
})), /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, {
id: "aiAssistantManager.llmModel.title"
}))), (provider === 'ollama' && !ollamaModelInputChecked || provider !== 'ollama') && /*#__PURE__*/_react["default"].createElement(StyledWrapper, null, /*#__PURE__*/_react["default"].createElement(StyledItemSelector, {
selectedItems: model,
options: _models.PROVIDER_MODELS[provider],
multiSelect: false,
disabled: provider === 'ollama' ? ollamaModelInputChecked : false,
placeholder: "Select LLM Model",
onChange: onLLMModelSelect,
filterOption: "name",
getOptionValue: function getOptionValue(op) {
return op;
},
displayOption: function displayOption(op) {
return op;
},
searchable: false,
showArrow: true
})), provider === 'ollama' && /*#__PURE__*/_react["default"].createElement(OllamaModelInputWrapper, null, /*#__PURE__*/_react["default"].createElement("div", {
style: {
width: '250px'
}
}, /*#__PURE__*/_react["default"].createElement(_components.Checkbox, {
id: "ollama-model-input",
label: "Input Model Name",
onChange: onOllamaModelInputChecked,
checked: ollamaModelInputChecked
})), /*#__PURE__*/_react["default"].createElement(_components.Input, {
type: "text",
onChange: onOllamaModelInputValueChange,
placeholder: "Enter Model Name",
value: ollamaModelInputValue,
disabled: !ollamaModelInputChecked
})), provider !== 'ollama' && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, {
id: "aiAssistantManager.apiKey.title"
}))), /*#__PURE__*/_react["default"].createElement("div", {
className: "api-key-input"
}, /*#__PURE__*/_react["default"].createElement("div", {
className: "api-key-input__icon"
}, /*#__PURE__*/_react["default"].createElement(_apiKey["default"], {
height: "20px"
})), /*#__PURE__*/_react["default"].createElement(_components.Input, {
type: "text",
onChange: onApiKeyChange,
placeholder: intl.formatMessage({
id: 'aiAssistantManager.apiKey.placeholder'
}),
value: apiKey
}))), /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, {
id: "aiAssistantManager.baseUrl.title"
}))), /*#__PURE__*/_react["default"].createElement("div", {
className: "api-key-input"
}, /*#__PURE__*/_react["default"].createElement("div", {
className: "api-key-input__icon"
}, /*#__PURE__*/_react["default"].createElement(_apiKey["default"], {
height: "20px"
})), /*#__PURE__*/_react["default"].createElement(_components.Input, {
type: "text",
onChange: onBaseUrlChange,
placeholder: _models.PROVIDER_DEFAULT_BASE_URLS[provider],
value: baseUrl
})), connectionError && /*#__PURE__*/_react["default"].createElement(StyleErrorMessage, {
className: "error-message"
}, errorMessage), /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, {
id: "aiAssistantManager.temperature.title"
}))), /*#__PURE__*/_react["default"].createElement(StyleSliderWrapper, null, /*#__PURE__*/_react["default"].createElement(RangeSlider, {
showInput: true,
isRanged: false,
value0: 0,
value1: temperature,
onChange: onTemperatureChange,
range: [0, 2],
step: 0.1
})), /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, {
id: "aiAssistantManager.topP.title"
}))), /*#__PURE__*/_react["default"].createElement(StyleSliderWrapper, null, /*#__PURE__*/_react["default"].createElement(RangeSlider, {
showInput: true,
isRanged: false,
value0: 0,
value1: topP,
onChange: onTopPChange,
range: [0, 1],
step: 0.1
})), /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_components.PanelLabelWrapper, null, /*#__PURE__*/_react["default"].createElement(SectionTitle, null, "Mapbox Token (optional for route/isochrone)")), /*#__PURE__*/_react["default"].createElement("div", {
className: "api-key-input"
}, /*#__PURE__*/_react["default"].createElement("div", {
className: "api-key-input__icon"
}, /*#__PURE__*/_react["default"].createElement(_apiKey["default"], {
height: "20px"
})), /*#__PURE__*/_react["default"].createElement(_components.Input, {
type: "text",
onChange: onMapboxTokenChange,
placeholder: "Enter your Mapbox Token",
value: mapboxToken
}))), /*#__PURE__*/_react["default"].createElement(StyledButton, null, /*#__PURE__*/_react["default"].createElement(_components.Button, {
onClick: onStartChat,
width: '100%'
}, isRunning && /*#__PURE__*/_react["default"].createElement(_components.LoadingSpinner, {
size: 12
}), /*#__PURE__*/_react["default"].createElement(_reactIntl.FormattedMessage, {
id: "aiAssistantManager.startChat"
}))));
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfc3R5bGVkQ29tcG9uZW50cyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfcmVhY3RSZWR1eCIsIl9jb21wb25lbnRzIiwiX2FwaUtleSIsIl9tb2RlbHMiLCJfdXNlaG9va3NUcyIsIl9jb3JlIiwiX2FjdGlvbnMiLCJfcmVhY3RJbnRsIiwiX3RlbXBsYXRlT2JqZWN0IiwiX3RlbXBsYXRlT2JqZWN0MiIsIl90ZW1wbGF0ZU9iamVjdDMiLCJfdGVtcGxhdGVPYmplY3Q0IiwiX3RlbXBsYXRlT2JqZWN0NSIsIl90ZW1wbGF0ZU9iamVjdDYiLCJfdGVtcGxhdGVPYmplY3Q3IiwiX3RlbXBsYXRlT2JqZWN0OCIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiX3R5cGVvZiIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIlNlY3Rpb25UaXRsZSIsInN0eWxlZCIsImRpdiIsIl90YWdnZWRUZW1wbGF0ZUxpdGVyYWwyIiwicHJvcHMiLCJ0aGVtZSIsImlucHV0Rm9udFNpemUiLCJlZmZlY3RQYW5lbFRleHRTZWNvbmRhcnkxIiwiU3R5bGVkQWlBc3Npc3RhbnRDb25maWciLCJwcmltYXJ5QnRuRm9udFNpemVEZWZhdWx0IiwiYm94U2hhZG93IiwiZ2VvY29kZXJJbnB1dEhlaWdodCIsInN1YnRleHRDb2xvciIsIk9sbGFtYU1vZGVsSW5wdXRXcmFwcGVyIiwiU3R5bGVkV3JhcHBlciIsIlN0eWxlZEl0ZW1TZWxlY3RvciIsIkl0ZW1TZWxlY3RvciIsImFjdGl2ZUNvbG9yIiwiU3R5bGVTbGlkZXJXcmFwcGVyIiwiU3R5bGVkQnV0dG9uIiwiU3R5bGVFcnJvck1lc3NhZ2UiLCJlcnJvckNvbG9yIiwiZXJyb3JUZXh0Q29sb3IiLCJSYW5nZVNsaWRlciIsImFwcEluamVjdG9yIiwiUmFuZ2VTbGlkZXJGYWN0b3J5IiwiQWlBc3Npc3RhbnRDb25maWciLCJkaXNwYXRjaCIsInVzZURpc3BhdGNoIiwiYWlBc3Npc3RhbnRDb25maWciLCJ1c2VTZWxlY3RvciIsInN0YXRlIiwiZGVtbyIsImFpQXNzaXN0YW50IiwiY29uZmlnIiwiaW50bCIsInVzZUludGwiLCJfdXNlTG9jYWxTdG9yYWdlIiwidXNlTG9jYWxTdG9yYWdlIiwicHJvdmlkZXIiLCJfdXNlTG9jYWxTdG9yYWdlMiIsIl9zbGljZWRUb0FycmF5MiIsInNldFByb3ZpZGVyIiwiX3VzZUxvY2FsU3RvcmFnZTMiLCJtb2RlbCIsIlBST1ZJREVSX01PREVMUyIsIl91c2VMb2NhbFN0b3JhZ2U0Iiwic2V0TW9kZWwiLCJfdXNlTG9jYWxTdG9yYWdlNSIsImFwaUtleSIsIl91c2VMb2NhbFN0b3JhZ2U2Iiwic2V0QXBpS2V5IiwiX3VzZUxvY2FsU3RvcmFnZTciLCJ0ZW1wZXJhdHVyZSIsIl91c2VMb2NhbFN0b3JhZ2U4Iiwic2V0VGVtcGVyYXR1cmUiLCJfdXNlTG9jYWxTdG9yYWdlOSIsInRvcFAiLCJfdXNlTG9jYWxTdG9yYWdlMTAiLCJzZXRUb3BQIiwiX3VzZUxvY2FsU3RvcmFnZTExIiwiYmFzZVVybCIsIlBST1ZJREVSX0RFRkFVTFRfQkFTRV9VUkxTIiwiX3VzZUxvY2FsU3RvcmFnZTEyIiwic2V0QmFzZVVybCIsIl91c2VMb2NhbFN0b3JhZ2UxMyIsIm1hcGJveFRva2VuIiwiX3VzZUxvY2FsU3RvcmFnZTE0Iiwic2V0TWFwYm94VG9rZW4iLCJfdXNlU3RhdGUiLCJ1c2VTdGF0ZSIsIl91c2VTdGF0ZTIiLCJvbGxhbWFNb2RlbElucHV0Q2hlY2tlZCIsInNldE9sbGFtYU1vZGVsSW5wdXRDaGVja2VkIiwiX3VzZVN0YXRlMyIsIl91c2VTdGF0ZTQiLCJvbGxhbWFNb2RlbElucHV0VmFsdWUiLCJzZXRPbGxhbWFNb2RlbElucHV0VmFsdWUiLCJfdXNlU3RhdGU1IiwiX3VzZVN0YXRlNiIsImNvbm5lY3Rpb25FcnJvciIsInNldENvbm5lY3Rpb25FcnJvciIsIl91c2VTdGF0ZTciLCJfdXNlU3RhdGU4IiwiZXJyb3JNZXNzYWdlIiwic2V0RXJyb3JNZXNzYWdlIiwiX3VzZVN0YXRlOSIsIl91c2VTdGF0ZTEwIiwiaXNSdW5uaW5nIiwic2V0SXNSdW5uaW5nIiwib25BaVByb3ZpZGVyU2VsZWN0IiwidmFsdWUiLCJvbkxMTU1vZGVsU2VsZWN0Iiwib25BcGlLZXlDaGFuZ2UiLCJ0YXJnZXQiLCJvblRlbXBlcmF0dXJlQ2hhbmdlIiwib25Ub3BQQ2hhbmdlIiwib25CYXNlVXJsQ2hhbmdlIiwib25NYXBib3hUb2tlbkNoYW5nZSIsIm9uT2xsYW1hTW9kZWxJbnB1dENoZWNrZWQiLCJjaGVja2VkIiwib25PbGxhbWFNb2RlbElucHV0VmFsdWVDaGFuZ2UiLCJvblN0YXJ0Q2hhdCIsIl9yZWYiLCJfYXN5bmNUb0dlbmVyYXRvcjIiLCJfcmVnZW5lcmF0b3IiLCJtYXJrIiwiX2NhbGxlZSIsInRpbWVvdXRQcm9taXNlIiwiQXNzaXN0YW50TW9kZWwiLCJzdWNjZXNzIiwiX2Vycm9yTWVzc2FnZSIsIndyYXAiLCJfY2FsbGVlJCIsIl9jb250ZXh0IiwicHJldiIsIm5leHQiLCJQcm9taXNlIiwiXyIsInJlamVjdCIsInNldFRpbWVvdXQiLCJFcnJvciIsIkdldEFzc2lzdGFudE1vZGVsQnlQcm92aWRlciIsInNlbnQiLCJjb25maWd1cmUiLCJ0ZXN0Q29ubmVjdGlvbiIsImJhc2VVUkwiLCJOdW1iZXIiLCJyYWNlIiwidXBkYXRlQWlBc3Npc3RhbnRDb25maWciLCJpc1JlYWR5IiwidDAiLCJtZXNzYWdlIiwiZmluaXNoIiwic3RvcCIsImFwcGx5IiwiYXJndW1lbnRzIiwiY3JlYXRlRWxlbWVudCIsImNsYXNzTmFtZSIsIlBhbmVsTGFiZWxXcmFwcGVyIiwiRm9ybWF0dGVkTWVzc2FnZSIsImlkIiwic2VsZWN0ZWRJdGVtcyIsIm9wdGlvbnMiLCJrZXlzIiwibXVsdGlTZWxlY3QiLCJkaXNhYmxlZCIsIm9uQ2hhbmdlIiwiZmlsdGVyT3B0aW9uIiwiZ2V0T3B0aW9uVmFsdWUiLCJvcCIsImRpc3BsYXlPcHRpb24iLCJzZWFyY2hhYmxlIiwic2hvd0Fycm93IiwicGxhY2Vob2xkZXIiLCJzdHlsZSIsIndpZHRoIiwiQ2hlY2tib3giLCJsYWJlbCIsIklucHV0IiwidHlwZSIsIkZyYWdtZW50IiwiaGVpZ2h0IiwiZm9ybWF0TWVzc2FnZSIsInNob3dJbnB1dCIsImlzUmFuZ2VkIiwidmFsdWUwIiwidmFsdWUxIiwicmFuZ2UiLCJzdGVwIiwiQnV0dG9uIiwib25DbGljayIsIkxvYWRpbmdTcGlubmVyIiwic2l6ZSJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL2FpLWFzc2lzdGFudC1jb25maWcudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCBSZWFjdCwge3VzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ3N0eWxlZC1jb21wb25lbnRzJztcbmltcG9ydCB7dXNlU2VsZWN0b3IsIHVzZURpc3BhdGNofSBmcm9tICdyZWFjdC1yZWR1eCc7XG5pbXBvcnQge1xuICBJbnB1dCxcbiAgUGFuZWxMYWJlbFdyYXBwZXIsXG4gIEl0ZW1TZWxlY3RvcixcbiAgUmFuZ2VTbGlkZXJGYWN0b3J5LFxuICBCdXR0b24sXG4gIExvYWRpbmdTcGlubmVyLFxuICBhcHBJbmplY3RvcixcbiAgQ2hlY2tib3hcbn0gZnJvbSAnQGtlcGxlci5nbC9jb21wb25lbnRzJztcbmltcG9ydCB7U3RhdGV9IGZyb20gJy4uL2luZGV4JztcbmltcG9ydCBBcGlLZXkgZnJvbSAnLi4vaWNvbnMvYXBpLWtleSc7XG5pbXBvcnQge1BST1ZJREVSX01PREVMUywgUFJPVklERVJfREVGQVVMVF9CQVNFX1VSTFN9IGZyb20gJy4uL2NvbmZpZy9tb2RlbHMnO1xuaW1wb3J0IHt1c2VMb2NhbFN0b3JhZ2V9IGZyb20gJ3VzZWhvb2tzLXRzJztcbmltcG9ydCB7R2V0QXNzaXN0YW50TW9kZWxCeVByb3ZpZGVyfSBmcm9tICdAb3BlbmFzc2lzdGFudC9jb3JlJztcbmltcG9ydCB7dXBkYXRlQWlBc3Npc3RhbnRDb25maWd9IGZyb20gJy4uL2FjdGlvbnMnO1xuaW1wb3J0IHtGb3JtYXR0ZWRNZXNzYWdlLCB1c2VJbnRsfSBmcm9tICdyZWFjdC1pbnRsJztcblxuY29uc3QgU2VjdGlvblRpdGxlID0gc3R5bGVkLmRpdmBcbiAgZm9udC1zaXplOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmlucHV0Rm9udFNpemV9O1xuICBjb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5lZmZlY3RQYW5lbFRleHRTZWNvbmRhcnkxfTtcbiAgdGV4dC10cmFuc2Zvcm06IGNhcGl0YWxpemU7XG5gO1xuXG5jb25zdCBTdHlsZWRBaUFzc2lzdGFudENvbmZpZyA9IHN0eWxlZC5kaXZgXG4gIHBhZGRpbmc6IDEycHg7XG4gIGZvbnQtc2l6ZTogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5wcmltYXJ5QnRuRm9udFNpemVEZWZhdWx0fTtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgZ2FwOiAxMnB4O1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xuXG4gIC5hcGkta2V5LWlucHV0IHtcbiAgICBib3gtc2hhZG93OiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmJveFNoYWRvd307XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgLmFwaS1rZXktaW5wdXRfX2ljb24ge1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgaGVpZ2h0OiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmdlb2NvZGVySW5wdXRIZWlnaHR9cHg7XG4gICAgICB3aWR0aDogMzBweDtcbiAgICAgIHBhZGRpbmctbGVmdDogNnB4O1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnN1YnRleHRDb2xvcn07XG4gICAgfVxuXG4gICAgaW5wdXQge1xuICAgICAgcGFkZGluZzogNHB4IDM2cHg7XG4gICAgICBoZWlnaHQ6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuZ2VvY29kZXJJbnB1dEhlaWdodH1weDtcbiAgICAgIGNhcmV0LWNvbG9yOiB1bnNldDtcbiAgICB9XG4gIH1cbmA7XG5cbi8vIE9sbGFtYSBtb2RlbCBpbnB1dCB3cmFwcGVyOiBjaGVja2JveCArICdJbnB1dCBNb2RlbCBOYW1lOicgKyBpbnB1dFxuLy8gYWxsIGNoaWxkcmVuIGVsZW1lbnQgaGF2ZSB3aWR0aCBiYXNlZCBvbiB0aGUgY29udGVudFxuY29uc3QgT2xsYW1hTW9kZWxJbnB1dFdyYXBwZXIgPSBzdHlsZWQuZGl2YFxuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBnYXA6IDRweDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbmA7XG5cbmNvbnN0IFN0eWxlZFdyYXBwZXIgPSBzdHlsZWQuZGl2YFxuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG5gO1xuXG5jb25zdCBTdHlsZWRJdGVtU2VsZWN0b3IgPSBzdHlsZWQoSXRlbVNlbGVjdG9yKWBcbiAgLml0ZW0tc2VsZWN0b3JfX2Ryb3Bkb3duIHtcbiAgICBwYWRkaW5nLWxlZnQ6IDEwcHg7XG4gICAgYm9yZGVyLXJhZGl1czogNHB4O1xuICB9XG4gIC5hY3RpdmUge1xuICAgIGJvcmRlci1jb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5hY3RpdmVDb2xvcn07XG4gICAgYm9yZGVyLXJhZGl1czogNHB4IDRweCAwcHggMHB4ICFpbXBvcnRhbnQ7XG4gIH1cbiAgd2lkdGg6IDEwMCU7XG5gO1xuXG5jb25zdCBTdHlsZVNsaWRlcldyYXBwZXIgPSBzdHlsZWQuZGl2YFxuICB3aWR0aDogMTAwJTtcbiAgYWxpZ24tc2VsZjogZmxleC1zdGFydDtcbiAgaGVpZ2h0OiAzMnB4O1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAua2ctcmFuZ2Utc2xpZGVyX19pbnB1dCB7XG4gICAgaGVpZ2h0OiAzMnB4O1xuICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICBwYWRkaW5nOiAzcHggNnB4O1xuICB9XG4gIC5rZy1zbGlkZXIge1xuICAgIHBhZGRpbmctbGVmdDogNnB4O1xuICB9XG4gIC5rZy1yYW5nZS1zbGlkZXIge1xuICAgIHBhZGRpbmc6IDBweCAhaW1wb3J0YW50O1xuICB9XG5gO1xuXG5jb25zdCBTdHlsZWRCdXR0b24gPSBzdHlsZWQuZGl2YFxuICB3aWR0aDogMTAwJTtcbiAgYWxpZ24tc2VsZjogZmxleC1zdGFydDtcbiAgbWFyZ2luLXRvcDogMTJweDtcblxuICBidXR0b24gZGl2IHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgZ2FwOiA0cHg7XG4gICAgbWFyZ2luLXJpZ2h0OiA0cHg7XG4gIH1cbmA7XG5cbmNvbnN0IFN0eWxlRXJyb3JNZXNzYWdlID0gc3R5bGVkLmRpdmBcbiAgZm9udC1zaXplOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnByaW1hcnlCdG5Gb250U2l6ZURlZmF1bHR9O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmVycm9yQ29sb3J9O1xuICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIHBhZGRpbmc6IDRweCA4cHg7XG4gIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLmVycm9yVGV4dENvbG9yfTtcbmA7XG5cbmNvbnN0IFJhbmdlU2xpZGVyID0gYXBwSW5qZWN0b3IuZ2V0KFJhbmdlU2xpZGVyRmFjdG9yeSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBBaUFzc2lzdGFudENvbmZpZygpIHtcbiAgY29uc3QgZGlzcGF0Y2ggPSB1c2VEaXNwYXRjaCgpO1xuICBjb25zdCBhaUFzc2lzdGFudENvbmZpZyA9IHVzZVNlbGVjdG9yKChzdGF0ZTogU3RhdGUpID0+IHN0YXRlLmRlbW8uYWlBc3Npc3RhbnQuY29uZmlnKTtcbiAgY29uc3QgaW50bCA9IHVzZUludGwoKTtcblxuICBjb25zdCBbcHJvdmlkZXIsIHNldFByb3ZpZGVyXSA9IHVzZUxvY2FsU3RvcmFnZShcbiAgICAnYWktYXNzaXN0YW50LXByb3ZpZGVyJyxcbiAgICBhaUFzc2lzdGFudENvbmZpZy5wcm92aWRlciB8fCAnb3BlbmFpJ1xuICApO1xuICBjb25zdCBbbW9kZWwsIHNldE1vZGVsXSA9IHVzZUxvY2FsU3RvcmFnZShcbiAgICAnYWktYXNzaXN0YW50LW1vZGVsJyxcbiAgICBhaUFzc2lzdGFudENvbmZpZy5tb2RlbCB8fCBQUk9WSURFUl9NT0RFTFNbcHJvdmlkZXJdWzBdXG4gICk7XG4gIGNvbnN0IFthcGlLZXksIHNldEFwaUtleV0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC1hcGkta2V5JyxcbiAgICBhaUFzc2lzdGFudENvbmZpZy5hcGlLZXkgfHwgJydcbiAgKTtcbiAgY29uc3QgW3RlbXBlcmF0dXJlLCBzZXRUZW1wZXJhdHVyZV0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC10ZW1wZXJhdHVyZScsXG4gICAgYWlBc3Npc3RhbnRDb25maWcudGVtcGVyYXR1cmUgfHwgMC4wXG4gICk7XG4gIGNvbnN0IFt0b3BQLCBzZXRUb3BQXSA9IHVzZUxvY2FsU3RvcmFnZSgnYWktYXNzaXN0YW50LXRvcC1wJywgYWlBc3Npc3RhbnRDb25maWcudG9wUCB8fCAxLjApO1xuICBjb25zdCBbYmFzZVVybCwgc2V0QmFzZVVybF0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC1iYXNlLXVybCcsXG4gICAgYWlBc3Npc3RhbnRDb25maWcuYmFzZVVybCB8fCBQUk9WSURFUl9ERUZBVUxUX0JBU0VfVVJMU1twcm92aWRlcl1cbiAgKTtcbiAgY29uc3QgW21hcGJveFRva2VuLCBzZXRNYXBib3hUb2tlbl0gPSB1c2VMb2NhbFN0b3JhZ2UoXG4gICAgJ2FpLWFzc2lzdGFudC1tYXBib3gtdG9rZW4nLFxuICAgIGFpQXNzaXN0YW50Q29uZmlnLm1hcGJveFRva2VuIHx8ICcnXG4gICk7XG4gIGNvbnN0IFtvbGxhbWFNb2RlbElucHV0Q2hlY2tlZCwgc2V0T2xsYW1hTW9kZWxJbnB1dENoZWNrZWRdID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbb2xsYW1hTW9kZWxJbnB1dFZhbHVlLCBzZXRPbGxhbWFNb2RlbElucHV0VmFsdWVdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbY29ubmVjdGlvbkVycm9yLCBzZXRDb25uZWN0aW9uRXJyb3JdID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbZXJyb3JNZXNzYWdlLCBzZXRFcnJvck1lc3NhZ2VdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXNSdW5uaW5nLCBzZXRJc1J1bm5pbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuXG4gIGNvbnN0IG9uQWlQcm92aWRlclNlbGVjdCA9ICh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG9iamVjdCB8IG51bGwpID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgc2V0UHJvdmlkZXIodmFsdWUpO1xuICAgICAgc2V0TW9kZWwoUFJPVklERVJfTU9ERUxTW3ZhbHVlXVswXSk7XG4gICAgICBzZXRCYXNlVXJsKFBST1ZJREVSX0RFRkFVTFRfQkFTRV9VUkxTW3ZhbHVlXSk7XG4gICAgICBzZXRDb25uZWN0aW9uRXJyb3IoZmFsc2UpO1xuICAgICAgc2V0RXJyb3JNZXNzYWdlKCcnKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3Qgb25MTE1Nb2RlbFNlbGVjdCA9ICh2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG9iamVjdCB8IG51bGwpID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgc2V0TW9kZWwodmFsdWUpO1xuICAgIH1cbiAgfTtcblxuICBjb25zdCBvbkFwaUtleUNoYW5nZSA9IChlOiBSZWFjdC5DaGFuZ2VFdmVudDxIVE1MSW5wdXRFbGVtZW50PikgPT4ge1xuICAgIHNldEFwaUtleShlLnRhcmdldC52YWx1ZSk7XG4gICAgLy8gcmVzZXQgcHJldmlvdXMga2V5IGVycm9yIGlmIGFueVxuICAgIHNldENvbm5lY3Rpb25FcnJvcihmYWxzZSk7XG4gICAgc2V0RXJyb3JNZXNzYWdlKCcnKTtcbiAgfTtcblxuICBjb25zdCBvblRlbXBlcmF0dXJlQ2hhbmdlID0gKHZhbHVlOiBudW1iZXJbXSkgPT4ge1xuICAgIHNldFRlbXBlcmF0dXJlKHZhbHVlWzFdKTtcbiAgfTtcblxuICBjb25zdCBvblRvcFBDaGFuZ2UgPSAodmFsdWU6IG51bWJlcltdKSA9PiB7XG4gICAgc2V0VG9wUCh2YWx1ZVsxXSk7XG4gIH07XG5cbiAgY29uc3Qgb25CYXNlVXJsQ2hhbmdlID0gKGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgc2V0QmFzZVVybChlLnRhcmdldC52YWx1ZSk7XG4gICAgc2V0Q29ubmVjdGlvbkVycm9yKGZhbHNlKTtcbiAgICBzZXRFcnJvck1lc3NhZ2UoJycpO1xuICB9O1xuXG4gIGNvbnN0IG9uTWFwYm94VG9rZW5DaGFuZ2UgPSAoZTogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICBzZXRNYXBib3hUb2tlbihlLnRhcmdldC52YWx1ZSk7XG4gIH07XG5cbiAgY29uc3Qgb25PbGxhbWFNb2RlbElucHV0Q2hlY2tlZCA9IChlOiBSZWFjdC5DaGFuZ2VFdmVudDxIVE1MSW5wdXRFbGVtZW50PikgPT4ge1xuICAgIHNldE9sbGFtYU1vZGVsSW5wdXRDaGVja2VkKGUudGFyZ2V0LmNoZWNrZWQpO1xuICAgIGlmICghZS50YXJnZXQuY2hlY2tlZCkge1xuICAgICAgLy8gdXNlIG1vZGVsIGZyb20gc2VsZWN0b3JcbiAgICAgIHNldE1vZGVsKCcnKTtcbiAgICB9XG4gIH07XG5cbiAgY29uc3Qgb25PbGxhbWFNb2RlbElucHV0VmFsdWVDaGFuZ2UgPSAoZTogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICBzZXRPbGxhbWFNb2RlbElucHV0VmFsdWUoZS50YXJnZXQudmFsdWUpO1xuICAgIHNldE1vZGVsKGUudGFyZ2V0LnZhbHVlKTtcbiAgfTtcblxuICBjb25zdCBvblN0YXJ0Q2hhdCA9IGFzeW5jICgpID0+IHtcbiAgICBzZXRJc1J1bm5pbmcodHJ1ZSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRpbWVvdXRQcm9taXNlID0gbmV3IFByb21pc2UoKF8sIHJlamVjdCkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHJlamVjdChuZXcgRXJyb3IoJ0Nvbm5lY3Rpb24gdGltZW91dCBhZnRlciAxNSBzZWNvbmRzJykpLCAxNTAwMCk7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgQXNzaXN0YW50TW9kZWwgPSBhd2FpdCBHZXRBc3Npc3RhbnRNb2RlbEJ5UHJvdmlkZXIoe1xuICAgICAgICBwcm92aWRlcjogcHJvdmlkZXJcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIUFzc2lzdGFudE1vZGVsIHx8ICFBc3Npc3RhbnRNb2RlbC5jb25maWd1cmUgfHwgIUFzc2lzdGFudE1vZGVsLnRlc3RDb25uZWN0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgQUkgbW9kZWwnKTtcbiAgICAgIH1cblxuICAgICAgLy8gY29uZmlndXJlIG1vZGVsXG4gICAgICBBc3Npc3RhbnRNb2RlbC5jb25maWd1cmUoe1xuICAgICAgICBtb2RlbDogbW9kZWwsXG4gICAgICAgIGJhc2VVUkw6IGJhc2VVcmwgfHwgUFJPVklERVJfREVGQVVMVF9CQVNFX1VSTFNbcHJvdmlkZXJdLFxuICAgICAgICBhcGlLZXk6IGFwaUtleSxcbiAgICAgICAgdGVtcGVyYXR1cmU6IE51bWJlcih0ZW1wZXJhdHVyZSksXG4gICAgICAgIHRvcFA6IE51bWJlcih0b3BQKVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHN1Y2Nlc3MgPSAoYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgQXNzaXN0YW50TW9kZWwudGVzdENvbm5lY3Rpb24oYXBpS2V5LCBtb2RlbCksXG4gICAgICAgIHRpbWVvdXRQcm9taXNlXG4gICAgICBdKSkgYXMgYm9vbGVhbjtcblxuICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gIXN1Y2Nlc3NcbiAgICAgICAgPyBwcm92aWRlciA9PT0gJ29sbGFtYSdcbiAgICAgICAgICA/ICdDb25uZWN0aW9uIGZhaWxlZDogbWF5YmUgaW52YWxpZCBCYXNlIFVSTCdcbiAgICAgICAgICA6ICdDb25uZWN0aW9uIGZhaWxlZDogbWF5YmUgaW52YWxpZCBBUEkgS2V5IG9yIEJhc2UgVVJMJ1xuICAgICAgICA6ICcnO1xuICAgICAgc2V0Q29ubmVjdGlvbkVycm9yKCFzdWNjZXNzKTtcbiAgICAgIHNldEVycm9yTWVzc2FnZShlcnJvck1lc3NhZ2UpO1xuICAgICAgZGlzcGF0Y2goXG4gICAgICAgIHVwZGF0ZUFpQXNzaXN0YW50Q29uZmlnKHtcbiAgICAgICAgICBwcm92aWRlcjogcHJvdmlkZXIsXG4gICAgICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgICAgIGFwaUtleTogYXBpS2V5LFxuICAgICAgICAgIGJhc2VVcmw6IGJhc2VVcmwgfHwgUFJPVklERVJfREVGQVVMVF9CQVNFX1VSTFNbcHJvdmlkZXJdLFxuICAgICAgICAgIGlzUmVhZHk6IHN1Y2Nlc3MsXG4gICAgICAgICAgdGVtcGVyYXR1cmU6IHRlbXBlcmF0dXJlLFxuICAgICAgICAgIHRvcFA6IHRvcFAsXG4gICAgICAgICAgbWFwYm94VG9rZW46IG1hcGJveFRva2VuXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBzZXRDb25uZWN0aW9uRXJyb3IodHJ1ZSk7XG4gICAgICBzZXRFcnJvck1lc3NhZ2UoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiAnQ29ubmVjdGlvbiBmYWlsZWQnKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgc2V0SXNSdW5uaW5nKGZhbHNlKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIChcbiAgICA8U3R5bGVkQWlBc3Npc3RhbnRDb25maWcgY2xhc3NOYW1lPVwiYWktYXNzaXN0YW50LWNvbmZpZ19fdHlwZVwiPlxuICAgICAgPFBhbmVsTGFiZWxXcmFwcGVyPlxuICAgICAgICA8U2VjdGlvblRpdGxlPlxuICAgICAgICAgIDxGb3JtYXR0ZWRNZXNzYWdlIGlkPVwiYWlBc3Npc3RhbnRNYW5hZ2VyLmFpUHJvdmlkZXJcIiAvPlxuICAgICAgICA8L1NlY3Rpb25UaXRsZT5cbiAgICAgIDwvUGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICA8U3R5bGVkV3JhcHBlcj5cbiAgICAgICAgPFN0eWxlZEl0ZW1TZWxlY3RvclxuICAgICAgICAgIHNlbGVjdGVkSXRlbXM9e3Byb3ZpZGVyfVxuICAgICAgICAgIG9wdGlvbnM9e09iamVjdC5rZXlzKFBST1ZJREVSX01PREVMUyl9XG4gICAgICAgICAgbXVsdGlTZWxlY3Q9e2ZhbHNlfVxuICAgICAgICAgIGRpc2FibGVkPXtmYWxzZX1cbiAgICAgICAgICBvbkNoYW5nZT17b25BaVByb3ZpZGVyU2VsZWN0fVxuICAgICAgICAgIGZpbHRlck9wdGlvbj1cIm5hbWVcIlxuICAgICAgICAgIGdldE9wdGlvblZhbHVlPXtvcCA9PiBvcH1cbiAgICAgICAgICBkaXNwbGF5T3B0aW9uPXtvcCA9PiBvcH1cbiAgICAgICAgICBzZWFyY2hhYmxlPXtmYWxzZX1cbiAgICAgICAgICBzaG93QXJyb3c9e3RydWV9XG4gICAgICAgIC8+XG4gICAgICA8L1N0eWxlZFdyYXBwZXI+XG4gICAgICA8UGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIubGxtTW9kZWwudGl0bGVcIiAvPlxuICAgICAgICA8L1NlY3Rpb25UaXRsZT5cbiAgICAgIDwvUGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICB7KChwcm92aWRlciA9PT0gJ29sbGFtYScgJiYgIW9sbGFtYU1vZGVsSW5wdXRDaGVja2VkKSB8fCBwcm92aWRlciAhPT0gJ29sbGFtYScpICYmIChcbiAgICAgICAgPFN0eWxlZFdyYXBwZXI+XG4gICAgICAgICAgPFN0eWxlZEl0ZW1TZWxlY3RvclxuICAgICAgICAgICAgc2VsZWN0ZWRJdGVtcz17bW9kZWx9XG4gICAgICAgICAgICBvcHRpb25zPXtQUk9WSURFUl9NT0RFTFNbcHJvdmlkZXJdfVxuICAgICAgICAgICAgbXVsdGlTZWxlY3Q9e2ZhbHNlfVxuICAgICAgICAgICAgZGlzYWJsZWQ9e3Byb3ZpZGVyID09PSAnb2xsYW1hJyA/IG9sbGFtYU1vZGVsSW5wdXRDaGVja2VkIDogZmFsc2V9XG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNlbGVjdCBMTE0gTW9kZWxcIlxuICAgICAgICAgICAgb25DaGFuZ2U9e29uTExNTW9kZWxTZWxlY3R9XG4gICAgICAgICAgICBmaWx0ZXJPcHRpb249XCJuYW1lXCJcbiAgICAgICAgICAgIGdldE9wdGlvblZhbHVlPXtvcCA9PiBvcH1cbiAgICAgICAgICAgIGRpc3BsYXlPcHRpb249e29wID0+IG9wfVxuICAgICAgICAgICAgc2VhcmNoYWJsZT17ZmFsc2V9XG4gICAgICAgICAgICBzaG93QXJyb3c9e3RydWV9XG4gICAgICAgICAgLz5cbiAgICAgICAgPC9TdHlsZWRXcmFwcGVyPlxuICAgICAgKX1cbiAgICAgIHtwcm92aWRlciA9PT0gJ29sbGFtYScgJiYgKFxuICAgICAgICA8T2xsYW1hTW9kZWxJbnB1dFdyYXBwZXI+XG4gICAgICAgICAgPGRpdiBzdHlsZT17e3dpZHRoOiAnMjUwcHgnfX0+XG4gICAgICAgICAgICA8Q2hlY2tib3hcbiAgICAgICAgICAgICAgaWQ9XCJvbGxhbWEtbW9kZWwtaW5wdXRcIlxuICAgICAgICAgICAgICBsYWJlbD1cIklucHV0IE1vZGVsIE5hbWVcIlxuICAgICAgICAgICAgICBvbkNoYW5nZT17b25PbGxhbWFNb2RlbElucHV0Q2hlY2tlZH1cbiAgICAgICAgICAgICAgY2hlY2tlZD17b2xsYW1hTW9kZWxJbnB1dENoZWNrZWR9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxJbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgb25DaGFuZ2U9e29uT2xsYW1hTW9kZWxJbnB1dFZhbHVlQ2hhbmdlfVxuICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJFbnRlciBNb2RlbCBOYW1lXCJcbiAgICAgICAgICAgIHZhbHVlPXtvbGxhbWFNb2RlbElucHV0VmFsdWV9XG4gICAgICAgICAgICBkaXNhYmxlZD17IW9sbGFtYU1vZGVsSW5wdXRDaGVja2VkfVxuICAgICAgICAgIC8+XG4gICAgICAgIDwvT2xsYW1hTW9kZWxJbnB1dFdyYXBwZXI+XG4gICAgICApfVxuICAgICAge3Byb3ZpZGVyICE9PSAnb2xsYW1hJyAmJiAoXG4gICAgICAgIDw+XG4gICAgICAgICAgPFBhbmVsTGFiZWxXcmFwcGVyPlxuICAgICAgICAgICAgPFNlY3Rpb25UaXRsZT5cbiAgICAgICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIuYXBpS2V5LnRpdGxlXCIgLz5cbiAgICAgICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgICAgIDwvUGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJhcGkta2V5LWlucHV0XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImFwaS1rZXktaW5wdXRfX2ljb25cIj5cbiAgICAgICAgICAgICAgPEFwaUtleSBoZWlnaHQ9XCIyMHB4XCIgLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPElucHV0XG4gICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgb25DaGFuZ2U9e29uQXBpS2V5Q2hhbmdlfVxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj17aW50bC5mb3JtYXRNZXNzYWdlKHtpZDogJ2FpQXNzaXN0YW50TWFuYWdlci5hcGlLZXkucGxhY2Vob2xkZXInfSl9XG4gICAgICAgICAgICAgIHZhbHVlPXthcGlLZXl9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8Lz5cbiAgICAgICl9XG4gICAgICA8UGFuZWxMYWJlbFdyYXBwZXI+XG4gICAgICAgIDxTZWN0aW9uVGl0bGU+XG4gICAgICAgICAgPEZvcm1hdHRlZE1lc3NhZ2UgaWQ9XCJhaUFzc2lzdGFudE1hbmFnZXIuYmFzZVVybC50aXRsZVwiIC8+XG4gICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYXBpLWtleS1pbnB1dFwiPlxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImFwaS1rZXktaW5wdXRfX2ljb25cIj5cbiAgICAgICAgICA8QXBpS2V5IGhlaWdodD1cIjIwcHhcIiAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPElucHV0XG4gICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgIG9uQ2hhbmdlPXtvbkJhc2VVcmxDaGFuZ2V9XG4gICAgICAgICAgcGxhY2Vob2xkZXI9e1BST1ZJREVSX0RFRkFVTFRfQkFTRV9VUkxTW3Byb3ZpZGVyXX1cbiAgICAgICAgICB2YWx1ZT17YmFzZVVybH1cbiAgICAgICAgLz5cbiAgICAgIDwvZGl2PlxuICAgICAge2Nvbm5lY3Rpb25FcnJvciAmJiAoXG4gICAgICAgIDxTdHlsZUVycm9yTWVzc2FnZSBjbGFzc05hbWU9XCJlcnJvci1tZXNzYWdlXCI+e2Vycm9yTWVzc2FnZX08L1N0eWxlRXJyb3JNZXNzYWdlPlxuICAgICAgKX1cbiAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgPFNlY3Rpb25UaXRsZT5cbiAgICAgICAgICA8Rm9ybWF0dGVkTWVzc2FnZSBpZD1cImFpQXNzaXN0YW50TWFuYWdlci50ZW1wZXJhdHVyZS50aXRsZVwiIC8+XG4gICAgICAgIDwvU2VjdGlvblRpdGxlPlxuICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgIDxTdHlsZVNsaWRlcldyYXBwZXI+XG4gICAgICAgIDxSYW5nZVNsaWRlclxuICAgICAgICAgIHNob3dJbnB1dD17dHJ1ZX1cbiAgICAgICAgICBpc1JhbmdlZD17ZmFsc2V9XG4gICAgICAgICAgdmFsdWUwPXswfVxuICAgICAgICAgIHZhbHVlMT17dGVtcGVyYXR1cmV9XG4gICAgICAgICAgb25DaGFuZ2U9e29uVGVtcGVyYXR1cmVDaGFuZ2V9XG4gICAgICAgICAgcmFuZ2U9e1swLCAyXX1cbiAgICAgICAgICBzdGVwPXswLjF9XG4gICAgICAgIC8+XG4gICAgICA8L1N0eWxlU2xpZGVyV3JhcHBlcj5cbiAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgPFNlY3Rpb25UaXRsZT5cbiAgICAgICAgICA8Rm9ybWF0dGVkTWVzc2FnZSBpZD1cImFpQXNzaXN0YW50TWFuYWdlci50b3BQLnRpdGxlXCIgLz5cbiAgICAgICAgPC9TZWN0aW9uVGl0bGU+XG4gICAgICA8L1BhbmVsTGFiZWxXcmFwcGVyPlxuICAgICAgPFN0eWxlU2xpZGVyV3JhcHBlcj5cbiAgICAgICAgPFJhbmdlU2xpZGVyXG4gICAgICAgICAgc2hvd0lucHV0PXt0cnVlfVxuICAgICAgICAgIGlzUmFuZ2VkPXtmYWxzZX1cbiAgICAgICAgICB2YWx1ZTA9ezB9XG4gICAgICAgICAgdmFsdWUxPXt0b3BQfVxuICAgICAgICAgIG9uQ2hhbmdlPXtvblRvcFBDaGFuZ2V9XG4gICAgICAgICAgcmFuZ2U9e1swLCAxXX1cbiAgICAgICAgICBzdGVwPXswLjF9XG4gICAgICAgIC8+XG4gICAgICA8L1N0eWxlU2xpZGVyV3JhcHBlcj5cbiAgICAgIDw+XG4gICAgICAgIDxQYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgICA8U2VjdGlvblRpdGxlPk1hcGJveCBUb2tlbiAob3B0aW9uYWwgZm9yIHJvdXRlL2lzb2Nocm9uZSk8L1NlY3Rpb25UaXRsZT5cbiAgICAgICAgPC9QYW5lbExhYmVsV3JhcHBlcj5cbiAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJhcGkta2V5LWlucHV0XCI+XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJhcGkta2V5LWlucHV0X19pY29uXCI+XG4gICAgICAgICAgICA8QXBpS2V5IGhlaWdodD1cIjIwcHhcIiAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxJbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgb25DaGFuZ2U9e29uTWFwYm94VG9rZW5DaGFuZ2V9XG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkVudGVyIHlvdXIgTWFwYm94IFRva2VuXCJcbiAgICAgICAgICAgIHZhbHVlPXttYXBib3hUb2tlbn1cbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvPlxuICAgICAgPFN0eWxlZEJ1dHRvbj5cbiAgICAgICAgPEJ1dHRvbiBvbkNsaWNrPXtvblN0YXJ0Q2hhdH0gd2lkdGg9eycxMDAlJ30+XG4gICAgICAgICAge2lzUnVubmluZyAmJiA8TG9hZGluZ1NwaW5uZXIgc2l6ZT17MTJ9IC8+fVxuICAgICAgICAgIDxGb3JtYXR0ZWRNZXNzYWdlIGlkPVwiYWlBc3Npc3RhbnRNYW5hZ2VyLnN0YXJ0Q2hhdFwiIC8+XG4gICAgICAgIDwvQnV0dG9uPlxuICAgICAgPC9TdHlsZWRCdXR0b24+XG4gICAgPC9TdHlsZWRBaUFzc2lzdGFudENvbmZpZz5cbiAgKTtcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEsTUFBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsaUJBQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLFdBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLFdBQUEsR0FBQUosT0FBQTtBQVdBLElBQUFLLE9BQUEsR0FBQUgsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFNLE9BQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLFdBQUEsR0FBQVAsT0FBQTtBQUNBLElBQUFRLEtBQUEsR0FBQVIsT0FBQTtBQUNBLElBQUFTLFFBQUEsR0FBQVQsT0FBQTtBQUNBLElBQUFVLFVBQUEsR0FBQVYsT0FBQTtBQUFxRCxJQUFBVyxlQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBQUFDLGdCQUFBLEVBdEJyRDtBQUNBO0FBQUEsU0FBQUMseUJBQUFDLENBQUEsNkJBQUFDLE9BQUEsbUJBQUFDLENBQUEsT0FBQUQsT0FBQSxJQUFBRSxDQUFBLE9BQUFGLE9BQUEsWUFBQUYsd0JBQUEsWUFBQUEseUJBQUFDLENBQUEsV0FBQUEsQ0FBQSxHQUFBRyxDQUFBLEdBQUFELENBQUEsS0FBQUYsQ0FBQTtBQUFBLFNBQUFyQix3QkFBQXFCLENBQUEsRUFBQUUsQ0FBQSxTQUFBQSxDQUFBLElBQUFGLENBQUEsSUFBQUEsQ0FBQSxDQUFBSSxVQUFBLFNBQUFKLENBQUEsZUFBQUEsQ0FBQSxnQkFBQUssT0FBQSxD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