biodsbench-adapter / src /components /permissions /PowerShellPermissionRequest /PowerShellPermissionRequest.tsx
| import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; | |
| import { Box, Text, useTheme } from '../../../ink.js'; | |
| import { useKeybinding } from '../../../keybindings/useKeybinding.js'; | |
| import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../../services/analytics/growthbook.js'; | |
| import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from '../../../services/analytics/index.js'; | |
| import { sanitizeToolNameForAnalytics } from '../../../services/analytics/metadata.js'; | |
| import { getDestructiveCommandWarning } from '../../../tools/PowerShellTool/destructiveCommandWarning.js'; | |
| import { PowerShellTool } from '../../../tools/PowerShellTool/PowerShellTool.js'; | |
| import { isAllowlistedCommand } from '../../../tools/PowerShellTool/readOnlyValidation.js'; | |
| import type { PermissionUpdate } from '../../../utils/permissions/PermissionUpdateSchema.js'; | |
| import { getCompoundCommandPrefixesStatic } from '../../../utils/powershell/staticPrefix.js'; | |
| import { Select } from '../../CustomSelect/select.js'; | |
| import { type UnaryEvent, usePermissionRequestLogging } from '../hooks.js'; | |
| import { PermissionDecisionDebugInfo } from '../PermissionDecisionDebugInfo.js'; | |
| import { PermissionDialog } from '../PermissionDialog.js'; | |
| import { PermissionExplainerContent, usePermissionExplainerUI } from '../PermissionExplanation.js'; | |
| import type { PermissionRequestProps } from '../PermissionRequest.js'; | |
| import { PermissionRuleExplanation } from '../PermissionRuleExplanation.js'; | |
| import { useShellPermissionFeedback } from '../useShellPermissionFeedback.js'; | |
| import { logUnaryPermissionEvent } from '../utils.js'; | |
| import { powershellToolUseOptions } from './powershellToolUseOptions.js'; | |
| export function PowerShellPermissionRequest(props: PermissionRequestProps): React.ReactNode { | |
| const { | |
| toolUseConfirm, | |
| toolUseContext, | |
| onDone, | |
| onReject, | |
| workerBadge | |
| } = props; | |
| const { | |
| command, | |
| description | |
| } = PowerShellTool.inputSchema.parse(toolUseConfirm.input); | |
| const [theme] = useTheme(); | |
| const explainerState = usePermissionExplainerUI({ | |
| toolName: toolUseConfirm.tool.name, | |
| toolInput: toolUseConfirm.input, | |
| toolDescription: toolUseConfirm.description, | |
| messages: toolUseContext.messages | |
| }); | |
| const { | |
| yesInputMode, | |
| noInputMode, | |
| yesFeedbackModeEntered, | |
| noFeedbackModeEntered, | |
| acceptFeedback, | |
| rejectFeedback, | |
| setAcceptFeedback, | |
| setRejectFeedback, | |
| focusedOption, | |
| handleInputModeToggle, | |
| handleReject, | |
| handleFocus | |
| } = useShellPermissionFeedback({ | |
| toolUseConfirm, | |
| onDone, | |
| onReject, | |
| explainerVisible: explainerState.visible | |
| }); | |
| const destructiveWarning = getFeatureValue_CACHED_MAY_BE_STALE('tengu_destructive_command_warning', false) ? getDestructiveCommandWarning(command) : null; | |
| const [showPermissionDebug, setShowPermissionDebug] = useState(false); | |
| // Editable prefix — compute static prefix locally (no LLM call). | |
| // Initialize synchronously to the raw command for single-line commands so | |
| // the editable input renders immediately, then refine to the extracted prefix | |
| // once the AST parser resolves. Multiline commands (`# comment\n...`, | |
| // foreach loops) get undefined → powershellToolUseOptions:64 hides the | |
| // "don't ask again" option — those literals are one-time-use (settings | |
| // corpus shows 14 multiline rules, zero match twice). For compound commands, | |
| // computes a prefix per subcommand, excluding subcommands that are already | |
| // auto-allowed (read-only). | |
| const [editablePrefix, setEditablePrefix] = useState<string | undefined>(command.includes('\n') ? undefined : command); | |
| const hasUserEditedPrefix = useRef(false); | |
| useEffect(() => { | |
| let cancelled = false; | |
| // Filter receives ParsedCommandElement — isAllowlistedCommand works from | |
| // element.name/nameType/args directly. isReadOnlyCommand(text) would need | |
| // to reparse (pwsh.exe spawn per subcommand) and returns false without the | |
| // full parsed AST, making the filter a no-op. | |
| getCompoundCommandPrefixesStatic(command, element => isAllowlistedCommand(element, element.text)).then(prefixes => { | |
| if (cancelled || hasUserEditedPrefix.current) return; | |
| if (prefixes.length > 0) { | |
| setEditablePrefix(`${prefixes[0]}:*`); | |
| } | |
| }).catch(() => {}); | |
| return () => { | |
| cancelled = true; | |
| }; | |
| // eslint-disable-next-line react-hooks/exhaustive-deps | |
| }, [command]); | |
| const onEditablePrefixChange = useCallback((value: string) => { | |
| hasUserEditedPrefix.current = true; | |
| setEditablePrefix(value); | |
| }, []); | |
| const unaryEvent = useMemo<UnaryEvent>(() => ({ | |
| completion_type: 'tool_use_single', | |
| language_name: 'none' | |
| }), []); | |
| usePermissionRequestLogging(toolUseConfirm, unaryEvent); | |
| const options = useMemo(() => powershellToolUseOptions({ | |
| suggestions: toolUseConfirm.permissionResult.behavior === 'ask' ? toolUseConfirm.permissionResult.suggestions : undefined, | |
| onRejectFeedbackChange: setRejectFeedback, | |
| onAcceptFeedbackChange: setAcceptFeedback, | |
| yesInputMode, | |
| noInputMode, | |
| editablePrefix, | |
| onEditablePrefixChange | |
| }), [toolUseConfirm, yesInputMode, noInputMode, editablePrefix, onEditablePrefixChange]); | |
| // Toggle permission debug info with keybinding | |
| const handleToggleDebug = useCallback(() => { | |
| setShowPermissionDebug(prev => !prev); | |
| }, []); | |
| useKeybinding('permission:toggleDebug', handleToggleDebug, { | |
| context: 'Confirmation' | |
| }); | |
| function onSelect(value: string) { | |
| // Map options to numeric values for analytics (strings not allowed in logEvent) | |
| const optionIndex: Record<string, number> = { | |
| yes: 1, | |
| 'yes-apply-suggestions': 2, | |
| 'yes-prefix-edited': 2, | |
| no: 3 | |
| }; | |
| logEvent('tengu_permission_request_option_selected', { | |
| option_index: optionIndex[value], | |
| explainer_visible: explainerState.visible | |
| }); | |
| const toolNameForAnalytics = sanitizeToolNameForAnalytics(toolUseConfirm.tool.name) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS; | |
| if (value === 'yes-prefix-edited') { | |
| const trimmedPrefix = (editablePrefix ?? '').trim(); | |
| logUnaryPermissionEvent('tool_use_single', toolUseConfirm, 'accept'); | |
| if (!trimmedPrefix) { | |
| toolUseConfirm.onAllow(toolUseConfirm.input, []); | |
| } else { | |
| const prefixUpdates: PermissionUpdate[] = [{ | |
| type: 'addRules', | |
| rules: [{ | |
| toolName: PowerShellTool.name, | |
| ruleContent: trimmedPrefix | |
| }], | |
| behavior: 'allow', | |
| destination: 'localSettings' | |
| }]; | |
| toolUseConfirm.onAllow(toolUseConfirm.input, prefixUpdates); | |
| } | |
| onDone(); | |
| return; | |
| } | |
| switch (value) { | |
| case 'yes': | |
| { | |
| const trimmedFeedback = acceptFeedback.trim(); | |
| logUnaryPermissionEvent('tool_use_single', toolUseConfirm, 'accept'); | |
| // Log accept submission with feedback context | |
| logEvent('tengu_accept_submitted', { | |
| toolName: toolNameForAnalytics, | |
| isMcp: toolUseConfirm.tool.isMcp ?? false, | |
| has_instructions: !!trimmedFeedback, | |
| instructions_length: trimmedFeedback.length, | |
| entered_feedback_mode: yesFeedbackModeEntered | |
| }); | |
| toolUseConfirm.onAllow(toolUseConfirm.input, [], trimmedFeedback || undefined); | |
| onDone(); | |
| break; | |
| } | |
| case 'yes-apply-suggestions': | |
| { | |
| logUnaryPermissionEvent('tool_use_single', toolUseConfirm, 'accept'); | |
| // Extract suggestions if present (works for both 'ask' and 'passthrough' behaviors) | |
| const permissionUpdates = 'suggestions' in toolUseConfirm.permissionResult ? toolUseConfirm.permissionResult.suggestions || [] : []; | |
| toolUseConfirm.onAllow(toolUseConfirm.input, permissionUpdates); | |
| onDone(); | |
| break; | |
| } | |
| case 'no': | |
| { | |
| const trimmedFeedback = rejectFeedback.trim(); | |
| // Log reject submission with feedback context | |
| logEvent('tengu_reject_submitted', { | |
| toolName: toolNameForAnalytics, | |
| isMcp: toolUseConfirm.tool.isMcp ?? false, | |
| has_instructions: !!trimmedFeedback, | |
| instructions_length: trimmedFeedback.length, | |
| entered_feedback_mode: noFeedbackModeEntered | |
| }); | |
| // Process rejection (with or without feedback) | |
| handleReject(trimmedFeedback || undefined); | |
| break; | |
| } | |
| } | |
| } | |
| return <PermissionDialog workerBadge={workerBadge} title="PowerShell command"> | |
| <Box flexDirection="column" paddingX={2} paddingY={1}> | |
| <Text dimColor={explainerState.visible}> | |
| {PowerShellTool.renderToolUseMessage({ | |
| command, | |
| description | |
| }, { | |
| theme, | |
| verbose: true | |
| } // always show the full command | |
| )} | |
| </Text> | |
| {!explainerState.visible && <Text dimColor>{toolUseConfirm.description}</Text>} | |
| <PermissionExplainerContent visible={explainerState.visible} promise={explainerState.promise} /> | |
| </Box> | |
| {showPermissionDebug ? <> | |
| <PermissionDecisionDebugInfo permissionResult={toolUseConfirm.permissionResult} toolName="PowerShell" /> | |
| {toolUseContext.options.debug && <Box justifyContent="flex-end" marginTop={1}> | |
| <Text dimColor>Ctrl-D to hide debug info</Text> | |
| </Box>} | |
| </> : <> | |
| <Box flexDirection="column"> | |
| <PermissionRuleExplanation permissionResult={toolUseConfirm.permissionResult} toolType="command" /> | |
| {destructiveWarning && <Box marginBottom={1}> | |
| <Text color="warning">{destructiveWarning}</Text> | |
| </Box>} | |
| <Text>Do you want to proceed?</Text> | |
| <Select options={options} inlineDescriptions onChange={onSelect} onCancel={() => handleReject()} onFocus={handleFocus} onInputModeToggle={handleInputModeToggle} /> | |
| </Box> | |
| <Box justifyContent="space-between" marginTop={1}> | |
| <Text dimColor> | |
| Esc to cancel | |
| {(focusedOption === 'yes' && !yesInputMode || focusedOption === 'no' && !noInputMode) && ' · Tab to amend'} | |
| {explainerState.enabled && ` · ctrl+e to ${explainerState.visible ? 'hide' : 'explain'}`} | |
| </Text> | |
| {toolUseContext.options.debug && <Text dimColor>Ctrl+d to show debug info</Text>} | |
| </Box> | |
| </>} | |
| </PermissionDialog>; | |
| } | |
| //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsInVzZUNhbGxiYWNrIiwidXNlRWZmZWN0IiwidXNlTWVtbyIsInVzZVJlZiIsInVzZVN0YXRlIiwiQm94IiwiVGV4dCIsInVzZVRoZW1lIiwidXNlS2V5YmluZGluZyIsImdldEZlYXR1cmVWYWx1ZV9DQUNIRURfTUFZX0JFX1NUQUxFIiwiQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIUyIsImxvZ0V2ZW50Iiwic2FuaXRpemVUb29sTmFtZUZvckFuYWx5dGljcyIsImdldERlc3RydWN0aXZlQ29tbWFuZFdhcm5pbmciLCJQb3dlclNoZWxsVG9vbCIsImlzQWxsb3dsaXN0ZWRDb21tYW5kIiwiUGVybWlzc2lvblVwZGF0ZSIsImdldENvbXBvdW5kQ29tbWFuZFByZWZpeGVzU3RhdGljIiwiU2VsZWN0IiwiVW5hcnlFdmVudCIsInVzZVBlcm1pc3Npb25SZXF1ZXN0TG9nZ2luZyIsIlBlcm1pc3Npb25EZWNpc2lvbkRlYnVnSW5mbyIsIlBlcm1pc3Npb25EaWFsb2ciLCJQZXJtaXNzaW9uRXhwbGFpbmVyQ29udGVudCIsInVzZVBlcm1pc3Npb25FeHBsYWluZXJVSSIsIlBlcm1pc3Npb25SZXF1ZXN0UHJvcHMiLCJQZXJtaXNzaW9uUnVsZUV4cGxhbmF0aW9uIiwidXNlU2hlbGxQZXJtaXNzaW9uRmVlZGJhY2siLCJsb2dVbmFyeVBlcm1pc3Npb25FdmVudCIsInBvd2Vyc2hlbGxUb29sVXNlT3B0aW9ucyIsIlBvd2VyU2hlbGxQZXJtaXNzaW9uUmVxdWVzdCIsInByb3BzIiwiUmVhY3ROb2RlIiwidG9vbFVzZUNvbmZpcm0iLCJ0b29sVXNlQ29udGV4dCIsIm9uRG9uZSIsIm9uUmVqZWN0Iiwid29ya2VyQmFkZ2UiLCJjb21tYW5kIiwiZGVzY3JpcHRpb24iLCJpbnB1dFNjaGVtYSIsInBhcnNlIiwiaW5wdXQiLCJ0aGVtZSIsImV4cGxhaW5lclN0YXRlIiwidG9vbE5hbWUiLCJ0b29sIiwibmFtZSIsInRvb2xJbnB1dCIsInRvb2xEZXNjcmlwdGlvbiIsIm1lc3NhZ2VzIiwieWVzSW5wdXRNb2RlIiwibm9JbnB1dE1vZGUiLCJ5ZXNGZWVkYmFja01vZGVFbnRlcmVkIiwibm9GZWVkYmFja01vZGVFbnRlcmVkIiwiYWNjZXB0RmVlZGJhY2siLCJyZWplY3RGZWVkYmFjayIsInNldEFjY2VwdEZlZWRiYWNrIiwic2V0UmVqZWN0RmVlZGJhY2siLCJmb2N1c2VkT3B0aW9uIiwiaGFuZGxlSW5wdXRNb2RlVG9nZ2xlIiwiaGFuZGxlUmVqZWN0IiwiaGFuZGxlRm9jdXMiLCJleHBsYWluZXJWaXNpYmxlIiwidmlzaWJsZSIsImRlc3RydWN0aXZlV2FybmluZyIsInNob3dQZXJtaXNzaW9uRGVidWciLCJzZXRTaG93UGVybWlzc2lvbkRlYnVnIiwiZWRpdGFibGVQcmVmaXgiLCJzZXRFZGl0YWJsZVByZWZpeCIsImluY2x1ZGVzIiwidW5kZWZpbmVkIiwiaGFzVXNlckVkaXRlZFByZWZpeCIsImNhbmNlbGxlZCIsImVsZW1lbnQiLCJ0ZXh0IiwidGhlbiIsInByZWZpeGVzIiwiY3VycmVudCIsImxlbmd0aCIsImNhdGNoIiwib25FZGl0YWJsZVByZWZpeENoYW5nZSIsInZhbHVlIiwidW5hcnlFdmVudCIsImNvbXBsZXRpb25fdHlwZSIsImxhbmd1YWdlX25hbWUiLCJvcHRpb25zIiwic3VnZ2VzdGlvbnMiLCJwZXJtaXNzaW9uUmVzdWx0IiwiYmVoYXZpb3IiLCJvblJlamVjdEZlZWRiYWNrQ2hhbmdlIiwib25BY2NlcHRGZWVkYmFja0NoYW5nZSIsImhhbmRsZVRvZ2dsZURlYnVnIiwicHJldiIsImNvbnRleHQiLCJvblNlbGVjdCIsIm9wdGlvbkluZGV4IiwiUmVjb3JkIiwieWVzIiwibm8iLCJvcHRpb25faW5kZXgiLCJleHBsYWluZXJfdmlzaWJsZSIsInRvb2xOYW1lRm9yQW5hbHl0aWNzIiwidHJpbW1lZFByZWZpeCIsInRyaW0iLCJvbkFsbG93IiwicHJlZml4VXBkYXRlcyIsInR5cGUiLCJydWxlcyIsInJ1bGVDb250ZW50IiwiZGVzdGluYXRpb24iLCJ0cmltbWVkRmVlZGJhY2siLCJpc01jcCIsImhhc19pbnN0cnVjdGlvbnMiLCJpbnN0cnVjdGlvbnNfbGVuZ3RoIiwiZW50ZXJlZF9mZWVkYmFja19tb2RlIiwicGVybWlzc2lvblVwZGF0ZXMiLCJyZW5kZXJUb29sVXNlTWVzc2FnZSIsInZlcmJvc2UiLCJwcm9taXNlIiwiZGVidWciLCJlbmFibGVkIl0sInNvdXJjZXMiOlsiUG93ZXJTaGVsbFBlcm1pc3Npb25SZXF1ZXN0LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QsIHsgdXNlQ2FsbGJhY2ssIHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgQm94LCBUZXh0LCB1c2VUaGVtZSB9IGZyb20gJy4uLy4uLy4uL2luay5qcydcbmltcG9ydCB7IHVzZUtleWJpbmRpbmcgfSBmcm9tICcuLi8uLi8uLi9rZXliaW5kaW5ncy91c2VLZXliaW5kaW5nLmpzJ1xuaW1wb3J0IHsgZ2V0RmVhdHVyZVZhbHVlX0NBQ0hFRF9NQVlfQkVfU1RBTEUgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9hbmFseXRpY3MvZ3Jvd3RoYm9vay5qcydcbmltcG9ydCB7XG4gIHR5cGUgQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIUyxcbiAgbG9nRXZlbnQsXG59IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2FuYWx5dGljcy9pbmRleC5qcydcbmltcG9ydCB7IHNhbml0aXplVG9vbE5hbWVGb3JBbmFseXRpY3MgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9hbmFseXRpY3MvbWV0YWRhdGEuanMnXG5pbXBvcnQgeyBnZXREZXN0cnVjdGl2ZUNvbW1hbmRXYXJuaW5nIH0gZnJvbSAnLi4vLi4vLi4vdG9vbHMvUG93ZXJTaGVsbFRvb2wvZGVzdHJ1Y3RpdmVDb21tYW5kV2FybmluZy5qcydcbmltcG9ydCB7IFBvd2VyU2hlbGxUb29sIH0gZnJvbSAnLi4vLi4vLi4vdG9vbHMvUG93ZXJTaGVsbFRvb2wvUG93ZXJTaGVsbFRvb2wuanMnXG5pbXBvcnQgeyBpc0FsbG93bGlzdGVkQ29tbWFuZCB9IGZyb20gJy4uLy4uLy4uL3Rvb2xzL1Bvd2VyU2hlbGxUb29sL3JlYWRPbmx5VmFsaWRhdGlvbi5qcydcbmltcG9ydCB0eXBlIHsgUGVybWlzc2lvblVwZGF0ZSB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL3Blcm1pc3Npb25zL1Blcm1pc3Npb25VcGRhdGVTY2hlbWEuanMnXG5pbXBvcnQgeyBnZXRDb21wb3VuZENvbW1hbmRQcmVmaXhlc1N0YXRpYyB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL3Bvd2Vyc2hlbGwvc3RhdGljUHJlZml4LmpzJ1xuaW1wb3J0IHsgU2VsZWN0IH0gZnJvbSAnLi4vLi4vQ3VzdG9tU2VsZWN0L3NlbGVjdC5qcydcbmltcG9ydCB7IHR5cGUgVW5hcnlFdmVudCwgdXNlUGVybWlzc2lvblJlcXVlc3RMb2dnaW5nIH0gZnJvbSAnLi4vaG9va3MuanMnXG5pbXBvcnQgeyBQZXJtaXNzaW9uRGVjaXNpb25EZWJ1Z0luZm8gfSBmcm9tICcuLi9QZXJtaXNzaW9uRGVjaXNpb25EZWJ1Z0luZm8uanMnXG5pbXBvcnQgeyBQZXJtaXNzaW9uRGlhbG9nIH0gZnJvbSAnLi4vUGVybWlzc2lvbkRpYWxvZy5qcydcbmltcG9ydCB7XG4gIFBlcm1pc3Npb25FeHBsYWluZXJDb250ZW50LFxuICB1c2VQZXJtaXNzaW9uRXhwbGFpbmVyVUksXG59IGZyb20gJy4uL1Blcm1pc3Npb25FeHBsYW5hdGlvbi5qcydcbmltcG9ydCB0eXBlIHsgUGVybWlzc2lvblJlcXVlc3RQcm9wcyB9IGZyb20gJy4uL1Blcm1pc3Npb25SZXF1ZXN0LmpzJ1xuaW1wb3J0IHsgUGVybWlzc2lvblJ1bGVFeHBsYW5hdGlvbiB9IGZyb20gJy4uL1Blcm1pc3Npb25SdWxlRXhwbGFuYXRpb24uanMnXG5pbXBvcnQgeyB1c2VTaGVsbFBlcm1pc3Npb25GZWVkYmFjayB9IGZyb20gJy4uL3VzZVNoZWxsUGVybWlzc2lvbkZlZWRiYWNrLmpzJ1xuaW1wb3J0IHsgbG9nVW5hcnlQZXJtaXNzaW9uRXZlbnQgfSBmcm9tICcuLi91dGlscy5qcydcbmltcG9ydCB7IHBvd2Vyc2hlbGxUb29sVXNlT3B0aW9ucyB9IGZyb20gJy4vcG93ZXJzaGVsbFRvb2xVc2VPcHRpb25zLmpzJ1xuXG5leHBvcnQgZnVuY3Rpb24gUG93ZXJTaGVsbFBlcm1pc3Npb25SZXF1ZXN0KFxuICBwcm9wczogUGVybWlzc2lvblJlcXVlc3RQcm9wcyxcbik6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IHsgdG9vbFVzZUNvbmZpcm0sIHRvb2xVc2VDb250ZXh0LCBvbkRvbmUsIG9uUmVqZWN0LCB3b3JrZXJCYWRnZSB9ID1cbiAgICBwcm9wc1xuXG4gIGNvbnN0IHsgY29tbWFuZCwgZGVzY3JpcHRpb24gfSA9IFBvd2VyU2hlbGxUb29sLmlucHV0U2NoZW1hLnBhcnNlKFxuICAgIHRvb2xVc2VDb25maXJtLmlucHV0LFxuICApXG5cbiAgY29uc3QgW3RoZW1lXSA9IHVzZVRoZW1lKClcbiAgY29uc3QgZXhwbGFpbmVyU3RhdGUgPSB1c2VQZXJtaXNzaW9uRXhwbGFpbmVyVUkoe1xuICAgIHRvb2xOYW1lOiB0b29sVXNlQ29uZmlybS50b29sLm5hbWUsXG4gICAgdG9vbElucHV0OiB0b29sVXNlQ29uZmlybS5pbnB1dCxcbiAgICB0b29sRGVzY3JpcHRpb246IHRvb2xVc2VDb25maXJtLmRlc2NyaXB0aW9uLFxuICAgIG1lc3NhZ2VzOiB0b29sVXNlQ29udGV4dC5tZXNzYWdlcyxcbiAgfSlcbiAgY29uc3Qge1xuICAgIHllc0lucHV0TW9kZSxcbiAgICBub0lucHV0TW9kZSxcbiAgICB5ZXNGZWVkYmFja01vZGVFbnRlcmVkLFxuICAgIG5vRmVlZGJhY2tNb2RlRW50ZXJlZCxcbiAgICBhY2NlcHRGZWVkYmFjayxcbiAgICByZWplY3RGZWVkYmFjayxcbiAgICBzZXRBY2NlcHRGZWVkYmFjayxcbiAgICBzZXRSZWplY3RGZWVkYmFjayxcbiAgICBmb2N1c2VkT3B0aW9uLFxuICAgIGhhbmRsZUlucHV0TW9kZVRvZ2dsZSxcbiAgICBoYW5kbGVSZWplY3QsXG4gICAgaGFuZGxlRm9jdXMsXG4gIH0gPSB1c2VTaGVsbFBlcm1pc3Npb25GZWVkYmFjayh7XG4gICAgdG9vbFVzZUNvbmZpcm0sXG4gICAgb25Eb25lLFxuICAgIG9uUmVqZWN0LFxuICAgIGV4cGxhaW5lclZpc2libGU6IGV4cGxhaW5lclN0YXRlLnZpc2libGUsXG4gIH0pXG4gIGNvbnN0IGRlc3RydWN0aXZlV2FybmluZyA9IGdldEZlYXR1cmVWYWx1ZV9DQUNIRURfTUFZX0JFX1NUQUxFKFxuICAgICd0ZW5ndV9kZXN0cnVjdGl2ZV9jb21tYW5kX3dhcm5pbmcnLFxuICAgIGZhbHNlLFxuICApXG4gICAgPyBnZXREZXN0cnVjdGl2ZUNvbW1hbmRXYXJuaW5nKGNvbW1hbmQpXG4gICAgOiBudWxsXG5cbiAgY29uc3QgW3Nob3dQZXJtaXNzaW9uRGVidWcsIHNldFNob3dQZXJtaXNzaW9uRGVidWddID0gdXNlU3RhdGUoZmFsc2UpXG5cbiAgLy8gRWRpdGFibGUgcHJlZml4IOKAlCBjb21wdXRlIHN0YXRpYyBwcmVmaXggbG9jYWxseSAobm8gTExNIGNhbGwpLlxuICAvLyBJbml0aWFsaXplIHN5bmNocm9ub3VzbHkgdG8gdGhlIHJhdyBjb21tYW5kIGZvciBzaW5nbGUtbGluZSBjb21tYW5kcyBzb1xuICAvLyB0aGUgZWRpdGFibGUgaW5wdXQgcmVuZGVycyBpbW1lZGlhdGVseSwgdGhlbiByZWZpbmUgdG8gdGhlIGV4dHJhY3RlZCBwcmVmaXhcbiAgLy8gb25jZSB0aGUgQVNUIHBhcnNlciByZXNvbHZlcy4gTXVsdGlsaW5lIGNvbW1hbmRzIChgIyBjb21tZW50XFxuLi4uYCxcbiAgLy8gZm9yZWFjaCBsb29wcykgZ2V0IHVuZGVmaW5lZCDihpIgcG93ZXJzaGVsbFRvb2xVc2VPcHRpb25zOjY0IGhpZGVzIHRoZVxuICAvLyBcImRvbid0IGFzayBhZ2FpblwiIG9wdGlvbiDigJQgdGhvc2UgbGl0ZXJhbHMgYXJlIG9uZS10aW1lLXVzZSAoc2V0dGluZ3NcbiAgLy8gY29ycHVzIHNob3dzIDE0IG11bHRpbGluZSBydWxlcywgemVybyBtYXRjaCB0d2ljZSkuIEZvciBjb21wb3VuZCBjb21tYW5kcyxcbiAgLy8gY29tcHV0ZXMgYSBwcmVmaXggcGVyIHN1YmNvbW1hbmQsIGV4Y2x1ZGluZyBzdWJjb21tYW5kcyB0aGF0IGFyZSBhbHJlYWR5XG4gIC8vIGF1dG8tYWxsb3dlZCAocmVhZC1vbmx5KS5cbiAgY29uc3QgW2VkaXRhYmxlUHJlZml4LCBzZXRFZGl0YWJsZVByZWZpeF0gPSB1c2VTdGF0ZTxzdHJpbmcgfCB1bmRlZmluZWQ+KFxuICAgIGNvbW1hbmQuaW5jbHVkZXMoJ1xcbicpID8gdW5kZWZpbmVkIDogY29tbWFuZCxcbiAgKVxuICBjb25zdCBoYXNVc2VyRWRpdGVkUHJlZml4ID0gdXNlUmVmKGZhbHNlKVxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGxldCBjYW5jZWxsZWQgPSBmYWxzZVxuICAgIC8vIEZpbHRlciByZWNlaXZlcyBQYXJzZWRDb21tYW5kRWxlbWVudCDigJQgaXNBbGxvd2xpc3RlZENvbW1hbmQgd29ya3MgZnJvbVxuICAgIC8vIGVsZW1lbnQubmFtZS9uYW1lVHlwZS9hcmdzIGRpcmVjdGx5LiBpc1JlYWRPbmx5Q29tbWFuZCh0ZXh0KSB3b3VsZCBuZWVkXG4gICAgLy8gdG8gcmVwYXJzZSAocHdzaC5leGUgc3Bhd24gcGVyIHN1YmNvbW1hbmQpIGFuZCByZXR1cm5zIGZhbHNlIHdpdGhvdXQgdGhlXG4gICAgLy8gZnVsbCBwYXJzZWQgQVNULCBtYWtpbmcgdGhlIGZpbHRlciBhIG5vLW9wLlxuICAgIGdldENvbXBvdW5kQ29tbWFuZFByZWZpeGVzU3RhdGljKGNvbW1hbmQsIGVsZW1lbnQgPT5cbiAgICAgIGlzQWxsb3dsaXN0ZWRDb21tYW5kKGVsZW1lbnQsIGVsZW1lbnQudGV4dCksXG4gICAgKVxuICAgICAgLnRoZW4ocHJlZml4ZXMgPT4ge1xuICAgICAgICBpZiAoY2FuY2VsbGVkIHx8IGhhc1VzZXJFZGl0ZWRQcmVmaXguY3VycmVudCkgcmV0dXJuXG4gICAgICAgIGlmIChwcmVmaXhlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgc2V0RWRpdGFibGVQcmVmaXgoYCR7cHJlZml4ZXNbMF19OipgKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICAgLmNhdGNoKCgpID0+IHt9KVxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjYW5jZWxsZWQgPSB0cnVlXG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcbiAgfSwgW2NvbW1hbmRdKVxuXG4gIGNvbnN0IG9uRWRpdGFibGVQcmVmaXhDaGFuZ2UgPSB1c2VDYWxsYmFjaygodmFsdWU6IHN0cmluZykgPT4ge1xuICAgIGhhc1VzZXJFZGl0ZWRQcmVmaXguY3VycmVudCA9IHRydWVcbiAgICBzZXRFZGl0YWJsZVByZWZpeCh2YWx1ZSlcbiAgfSwgW10pXG5cbiAgY29uc3QgdW5hcnlFdmVudCA9IHVzZU1lbW88VW5hcnlFdmVudD4oXG4gICAgKCkgPT4gKHsgY29tcGxldGlvbl90eXBlOiAndG9vbF91c2Vfc2luZ2xlJywgbGFuZ3VhZ2VfbmFtZTogJ25vbmUnIH0pLFxuICAgIFtdLFxuICApXG5cbiAgdXNlUGVybWlzc2lvblJlcXVlc3RMb2dnaW5nKHRvb2xVc2VDb25maXJtLCB1bmFyeUV2ZW50KVxuXG4gIGNvbnN0IG9wdGlvbnMgPSB1c2VNZW1vKFxuICAgICgpID0+XG4gICAgICBwb3dlcnNoZWxsVG9vbFVzZU9wdGlvbnMoe1xuICAgICAgICBzdWdnZXN0aW9uczpcbiAgICAgICAgICB0b29sVXNlQ29uZmlybS5wZXJtaXNzaW9uUmVzdWx0LmJlaGF2aW9yID09PSAnYXNrJ1xuICAgICAgICAgICAgPyB0b29sVXNlQ29uZmlybS5wZXJtaXNzaW9uUmVzdWx0LnN1Z2dlc3Rpb25zXG4gICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgb25SZWplY3RGZWVkYmFja0NoYW5nZTogc2V0UmVqZWN0RmVlZGJhY2ssXG4gICAgICAgIG9uQWNjZXB0RmVlZGJhY2tDaGFuZ2U6IHNldEFjY2VwdEZlZWRiYWNrLFxuICAgICAgICB5ZXNJbnB1dE1vZGUsXG4gICAgICAgIG5vSW5wdXRNb2RlLFxuICAgICAgICBlZGl0YWJsZVByZWZpeCxcbiAgICAgICAgb25FZGl0YWJsZVByZWZpeENoYW5nZSxcbiAgICAgIH0pLFxuICAgIFtcbiAgICAgIHRvb2xVc2VDb25maXJtLFxuICAgICAgeWVzSW5wdXRNb2RlLFxuICAgICAgbm9JbnB1dE1vZGUsXG4gICAgICBlZGl0YWJsZVByZWZpeCxcbiAgICAgIG9uRWRpdGFibGVQcmVmaXhDaGFuZ2UsXG4gICAgXSxcbiAgKVxuXG4gIC8vIFRvZ2dsZSBwZXJtaXNzaW9uIGRlYnVnIGluZm8gd2l0aCBrZXliaW5kaW5nXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZURlYnVnID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldFNob3dQZXJtaXNzaW9uRGVidWcocHJldiA9PiAhcHJldilcbiAgfSwgW10pXG4gIHVzZUtleWJpbmRpbmcoJ3Blcm1pc3Npb246dG9nZ2xlRGVidWcnLCBoYW5kbGVUb2dnbGVEZWJ1Zywge1xuICAgIGNvbnRleHQ6ICdDb25maXJtYXRpb24nLFxuICB9KVxuXG4gIGZ1bmN0aW9uIG9uU2VsZWN0KHZhbHVlOiBzdHJpbmcpIHtcbiAgICAvLyBNYXAgb3B0aW9ucyB0byBudW1lcmljIHZhbHVlcyBmb3IgYW5hbHl0aWNzIChzdHJpbmdzIG5vdCBhbGxvd2VkIGluIGxvZ0V2ZW50KVxuICAgIGNvbnN0IG9wdGlvbkluZGV4OiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge1xuICAgICAgeWVzOiAxLFxuICAgICAgJ3llcy1hcHBseS1zdWdnZXN0aW9ucyc6IDIsXG4gICAgICAneWVzLXByZWZpeC1lZGl0ZWQnOiAyLFxuICAgICAgbm86IDMsXG4gICAgfVxuICAgIGxvZ0V2ZW50KCd0ZW5ndV9wZXJtaXNzaW9uX3JlcXVlc3Rfb3B0aW9uX3NlbGVjdGVkJywge1xuICAgICAgb3B0aW9uX2luZGV4OiBvcHRpb25JbmRleFt2YWx1ZV0sXG4gICAgICBleHBsYWluZXJfdmlzaWJsZTogZXhwbGFpbmVyU3RhdGUudmlzaWJsZSxcbiAgICB9KVxuXG4gICAgY29uc3QgdG9vbE5hbWVGb3JBbmFseXRpY3MgPSBzYW5pdGl6ZVRvb2xOYW1lRm9yQW5hbHl0aWNzKFxuICAgICAgdG9vbFVzZUNvbmZpcm0udG9vbC5uYW1lLFxuICAgICkgYXMgQW5hbHl0aWNzTWV0YWRhdGFfSV9WRVJJRklFRF9USElTX0lTX05PVF9DT0RFX09SX0ZJTEVQQVRIU1xuXG4gICAgaWYgKHZhbHVlID09PSAneWVzLXByZWZpeC1lZGl0ZWQnKSB7XG4gICAgICBjb25zdCB0cmltbWVkUHJlZml4ID0gKGVkaXRhYmxlUHJlZml4ID8/ICcnKS50cmltKClcbiAgICAgIGxvZ1VuYXJ5UGVybWlzc2lvbkV2ZW50KCd0b29sX3VzZV9zaW5nbGUnLCB0b29sVXNlQ29uZmlybSwgJ2FjY2VwdCcpXG4gICAgICBpZiAoIXRyaW1tZWRQcmVmaXgpIHtcbiAgICAgICAgdG9vbFVzZUNvbmZpcm0ub25BbGxvdyh0b29sVXNlQ29uZmlybS5pbnB1dCwgW10pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBwcmVmaXhVcGRhdGVzOiBQZXJtaXNzaW9uVXBkYXRlW10gPSBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHlwZTogJ2FkZFJ1bGVzJyxcbiAgICAgICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0b29sTmFtZTogUG93ZXJTaGVsbFRvb2wubmFtZSxcbiAgICAgICAgICAgICAgICBydWxlQ29udGVudDogdHJpbW1lZFByZWZpeCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBiZWhhdmlvcjogJ2FsbG93JyxcbiAgICAgICAgICAgIGRlc3RpbmF0aW9uOiAnbG9jYWxTZXR0aW5ncycsXG4gICAgICAgICAgfSxcbiAgICAgICAgXVxuICAgICAgICB0b29sVXNlQ29uZmlybS5vbkFsbG93KHRvb2xVc2VDb25maXJtLmlucHV0LCBwcmVmaXhVcGRhdGVzKVxuICAgICAgfVxuICAgICAgb25Eb25lKClcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHN3aXRjaCAodmFsdWUpIHtcbiAgICAgIGNhc2UgJ3llcyc6IHtcbiAgICAgICAgY29uc3QgdHJpbW1lZEZlZWRiYWNrID0gYWNjZXB0RmVlZGJhY2sudHJpbSgpXG4gICAgICAgIGxvZ1VuYXJ5UGVybWlzc2lvbkV2ZW50KCd0b29sX3VzZV9zaW5nbGUnLCB0b29sVXNlQ29uZmlybSwgJ2FjY2VwdCcpXG4gICAgICAgIC8vIExvZyBhY2NlcHQgc3VibWlzc2lvbiB3aXRoIGZlZWRiYWNrIGNvbnRleHRcbiAgICAgICAgbG9nRXZlbnQoJ3Rlbmd1X2FjY2VwdF9zdWJtaXR0ZWQnLCB7XG4gICAgICAgICAgdG9vbE5hbWU6IHRvb2xOYW1lRm9yQW5hbHl0aWNzLFxuICAgICAgICAgIGlzTWNwOiB0b29sVXNlQ29uZmlybS50b29sLmlzTWNwID8/IGZhbHNlLFxuICAgICAgICAgIGhhc19pbnN0cnVjdGlvbnM6ICEhdHJpbW1lZEZlZWRiYWNrLFxuICAgICAgICAgIGluc3RydWN0aW9uc19sZW5ndGg6IHRyaW1tZWRGZWVkYmFjay5sZW5ndGgsXG4gICAgICAgICAgZW50ZXJlZF9mZWVkYmFja19tb2RlOiB5ZXNGZWVkYmFja01vZGVFbnRlcmVkLFxuICAgICAgICB9KVxuICAgICAgICB0b29sVXNlQ29uZmlybS5vbkFsbG93KFxuICAgICAgICAgIHRvb2xVc2VDb25maXJtLmlucHV0LFxuICAgICAgICAgIFtdLFxuICAgICAgICAgIHRyaW1tZWRGZWVkYmFjayB8fCB1bmRlZmluZWQsXG4gICAgICAgIClcbiAgICAgICAgb25Eb25lKClcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3llcy1hcHBseS1zdWdnZXN0aW9ucyc6IHtcbiAgICAgICAgbG9nVW5hcnlQZXJtaXNzaW9uRXZlbnQoJ3Rvb2xfdXNlX3NpbmdsZScsIHRvb2xVc2VDb25maXJtLCAnYWNjZXB0JylcbiAgICAgICAgLy8gRXh0cmFjdCBzdWdnZXN0aW9ucyBpZiBwcmVzZW50ICh3b3JrcyBmb3IgYm90aCAnYXNrJyBhbmQgJ3Bhc3N0aHJvdWdoJyBiZWhhdmlvcnMpXG4gICAgICAgIGNvbnN0IHBlcm1pc3Npb25VcGRhdGVzID1cbiAgICAgICAgICAnc3VnZ2VzdGlvbnMnIGluIHRvb2xVc2VDb25maXJtLnBlcm1pc3Npb25SZXN1bHRcbiAgICAgICAgICAgID8gdG9vbFVzZUNvbmZpcm0ucGVybWlzc2lvblJlc3VsdC5zdWdnZXN0aW9ucyB8fCBbXVxuICAgICAgICAgICAgOiBbXVxuICAgICAgICB0b29sVXNlQ29uZmlybS5vbkFsbG93KHRvb2xVc2VDb25maXJtLmlucHV0LCBwZXJtaXNzaW9uVXBkYXRlcylcbiAgICAgICAgb25Eb25lKClcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIGNhc2UgJ25vJzoge1xuICAgICAgICBjb25zdCB0cmltbWVkRmVlZGJhY2sgPSByZWplY3RGZWVkYmFjay50cmltKClcblxuICAgICAgICAvLyBMb2cgcmVqZWN0IHN1Ym1pc3Npb24gd2l0aCBmZWVkYmFjayBjb250ZXh0XG4gICAgICAgIGxvZ0V2ZW50KCd0ZW5ndV9yZWplY3Rfc3VibWl0dGVkJywge1xuICAgICAgICAgIHRvb2xOYW1lOiB0b29sTmFtZUZvckFuYWx5dGljcyxcbiAgICAgICAgICBpc01jcDogdG9vbFVzZUNvbmZpcm0udG9vbC5pc01jcCA/PyBmYWxzZSxcbiAgICAgICAgICBoYXNfaW5zdHJ1Y3Rpb25zOiAhIXRyaW1tZWRGZWVkYmFjayxcbiAgICAgICAgICBpbnN0cnVjdGlvbnNfbGVuZ3RoOiB0cmltbWVkRmVlZGJhY2subGVuZ3RoLFxuICAgICAgICAgIGVudGVyZWRfZmVlZGJhY2tfbW9kZTogbm9GZWVkYmFja01vZGVFbnRlcmVkLFxuICAgICAgICB9KVxuXG4gICAgICAgIC8vIFByb2Nlc3MgcmVqZWN0aW9uICh3aXRoIG9yIHdpdGhvdXQgZmVlZGJhY2spXG4gICAgICAgIGhhbmRsZVJlamVjdCh0cmltbWVkRmVlZGJhY2sgfHwgdW5kZWZpbmVkKVxuICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPFBlcm1pc3Npb25EaWFsb2cgd29ya2VyQmFkZ2U9e3dvcmtlckJhZGdlfSB0aXRsZT1cIlBvd2VyU2hlbGwgY29tbWFuZFwiPlxuICAgICAgPEJveCBmbGV4RGlyZWN0aW9uPVwiY29sdW1uXCIgcGFkZGluZ1g9ezJ9IHBhZGRpbmdZPXsxfT5cbiAgICAgICAgPFRleHQgZGltQ29sb3I9e2V4cGxhaW5lclN0YXRlLnZpc2libGV9PlxuICAgICAgICAgIHtQb3dlclNoZWxsVG9vbC5yZW5kZXJUb29sVXNlTWVzc2FnZShcbiAgICAgICAgICAgIHsgY29tbWFuZCwgZGVzY3JpcHRpb24gfSxcbiAgICAgICAgICAgIHsgdGhlbWUsIHZlcmJvc2U6IHRydWUgfSwgLy8gYWx3YXlzIHNob3cgdGhlIGZ1bGwgY29tbWFuZFxuICAgICAgICAgICl9XG4gICAgICAgIDwvVGV4dD5cbiAgICAgICAgeyFleHBsYWluZXJTdGF0ZS52aXNpYmxlICYmIChcbiAgICAgICAgICA8VGV4dCBkaW1Db2xvcj57dG9vbFVzZUNvbmZpcm0uZGVzY3JpcHRpb259PC9UZXh0PlxuICAgICAgICApfVxuICAgICAgICA8UGVybWlzc2lvbkV4cGxhaW5lckNvbnRlbnRcbiAgICAgICAgICB2aXNpYmxlPXtleHBsYWluZXJTdGF0ZS52aXNpYmxlfVxuICAgICAgICAgIHByb21pc2U9e2V4cGxhaW5lclN0YXRlLnByb21pc2V9XG4gICAgICAgIC8+XG4gICAgICA8L0JveD5cbiAgICAgIHtzaG93UGVybWlzc2lvbkRlYnVnID8gKFxuICAgICAgICA8PlxuICAgICAgICAgIDxQZXJtaXNzaW9uRGVjaXNpb25EZWJ1Z0luZm9cbiAgICAgICAgICAgIHBlcm1pc3Npb25SZXN1bHQ9e3Rvb2xVc2VDb25maXJtLnBlcm1pc3Npb25SZXN1bHR9XG4gICAgICAgICAgICB0b29sTmFtZT1cIlBvd2VyU2hlbGxcIlxuICAgICAgICAgIC8+XG4gICAgICAgICAge3Rvb2xVc2VDb250ZXh0Lm9wdGlvbnMuZGVidWcgJiYgKFxuICAgICAgICAgICAgPEJveCBqdXN0aWZ5Q29udGVudD1cImZsZXgtZW5kXCIgbWFyZ2luVG9wPXsxfT5cbiAgICAgICAgICAgICAgPFRleHQgZGltQ29sb3I+Q3RybC1EIHRvIGhpZGUgZGVidWcgaW5mbzwvVGV4dD5cbiAgICAgICAgICAgIDwvQm94PlxuICAgICAgICAgICl9XG4gICAgICAgIDwvPlxuICAgICAgKSA6IChcbiAgICAgICAgPD5cbiAgICAgICAgICA8Qm94IGZsZXhEaXJlY3Rpb249XCJjb2x1bW5cIj5cbiAgICAgICAgICAgIDxQZXJtaXNzaW9uUnVsZUV4cGxhbmF0aW9uXG4gICAgICAgICAgICAgIHBlcm1pc3Npb25SZXN1bHQ9e3Rvb2xVc2VDb25maXJtLnBlcm1pc3Npb25SZXN1bHR9XG4gICAgICAgICAgICAgIHRvb2xUeXBlPVwiY29tbWFuZFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAge2Rlc3RydWN0aXZlV2FybmluZyAmJiAoXG4gICAgICAgICAgICAgIDxCb3ggbWFyZ2luQm90dG9tPXsxfT5cbiAgICAgICAgICAgICAgICA8VGV4dCBjb2xvcj1cIndhcm5pbmdcIj57ZGVzdHJ1Y3RpdmVXYXJuaW5nfTwvVGV4dD5cbiAgICAgICAgICAgICAgPC9Cb3g+XG4gICAgICAgICAgICApfVxuICAgICAgICAgICAgPFRleHQ+RG8geW91IHdhbnQgdG8gcHJvY2VlZD88L1RleHQ+XG4gICAgICAgICAgICA8U2VsZWN0XG4gICAgICAgICAgICAgIG9wdGlvbnM9e29wdGlvbnN9XG4gICAgICAgICAgICAgIGlubGluZURlc2NyaXB0aW9uc1xuICAgICAgICAgICAgICBvbkNoYW5nZT17b25TZWxlY3R9XG4gICAgICAgICAgICAgIG9uQ2FuY2VsPXsoKSA9PiBoYW5kbGVSZWplY3QoKX1cbiAgICAgICAgICAgICAgb25Gb2N1cz17aGFuZGxlRm9jdXN9XG4gICAgICAgICAgICAgIG9uSW5wdXRNb2RlVG9nZ2xlPXtoYW5kbGVJbnB1dE1vZGVUb2dnbGV9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvQm94PlxuICAgICAgICAgIDxCb3gganVzdGlmeUNvbnRlbnQ9XCJzcGFjZS1iZXR3ZWVuXCIgbWFyZ2luVG9wPXsxfT5cbiAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPlxuICAgICAgICAgICAgICBFc2MgdG8gY2FuY2VsXG4gICAgICAgICAgICAgIHsoKGZvY3VzZWRPcHRpb24gPT09ICd5ZXMnICYmICF5ZXNJbnB1dE1vZGUpIHx8XG4gICAgICAgICAgICAgICAgKGZvY3VzZWRPcHRpb24gPT09ICdubycgJiYgIW5vSW5wdXRNb2RlKSkgJiZcbiAgICAgICAgICAgICAgICAnIMK3IFRhYiB0byBhbWVuZCd9XG4gICAgICAgICAgICAgIHtleHBsYWluZXJTdGF0ZS5lbmFibGVkICYmXG4gICAgICAgICAgICAgICAgYCDCtyBjdHJsK2UgdG8gJHtleHBsYWluZXJTdGF0ZS52aXNpYmxlID8gJ2hpZGUnIDogJ2V4cGxhaW4nfWB9XG4gICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICB7dG9vbFVzZUNvbnRleHQub3B0aW9ucy5kZWJ1ZyAmJiAoXG4gICAgICAgICAgICAgIDxUZXh0IGRpbUNvbG9yPkN0cmwrZCB0byBzaG93IGRlYnVnIGluZm88L1RleHQ+XG4gICAgICAgICAgICApfVxuICAgICAgICAgIDwvQm94PlxuICAgICAgICA8Lz5cbiAgICAg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 |