source dump of claude code
at main 147 lines 21 kB view raw
1import { BASH_TOOL_NAME } from '../../../tools/BashTool/toolName.js'; 2import { extractOutputRedirections } from '../../../utils/bash/commands.js'; 3import { isClassifierPermissionsEnabled } from '../../../utils/permissions/bashClassifier.js'; 4import type { PermissionDecisionReason } from '../../../utils/permissions/PermissionResult.js'; 5import type { PermissionUpdate } from '../../../utils/permissions/PermissionUpdateSchema.js'; 6import { shouldShowAlwaysAllowOptions } from '../../../utils/permissions/permissionsLoader.js'; 7import type { OptionWithDescription } from '../../CustomSelect/select.js'; 8import { generateShellSuggestionsLabel } from '../shellPermissionHelpers.js'; 9export type BashToolUseOption = 'yes' | 'yes-apply-suggestions' | 'yes-prefix-edited' | 'yes-classifier-reviewed' | 'no'; 10 11/** 12 * Check if a description already exists in the allow list. 13 * Compares lowercase and trailing-whitespace-trimmed versions. 14 */ 15function descriptionAlreadyExists(description: string, existingDescriptions: string[]): boolean { 16 const normalized = description.toLowerCase().trimEnd(); 17 return existingDescriptions.some(existing => existing.toLowerCase().trimEnd() === normalized); 18} 19 20/** 21 * Strip output redirections so filenames don't show as commands in the label. 22 */ 23function stripBashRedirections(command: string): string { 24 const { 25 commandWithoutRedirections, 26 redirections 27 } = extractOutputRedirections(command); 28 // Only use stripped version if there were actual redirections 29 return redirections.length > 0 ? commandWithoutRedirections : command; 30} 31export function bashToolUseOptions({ 32 suggestions = [], 33 decisionReason, 34 onRejectFeedbackChange, 35 onAcceptFeedbackChange, 36 onClassifierDescriptionChange, 37 classifierDescription, 38 initialClassifierDescriptionEmpty = false, 39 existingAllowDescriptions = [], 40 yesInputMode = false, 41 noInputMode = false, 42 editablePrefix, 43 onEditablePrefixChange 44}: { 45 suggestions?: PermissionUpdate[]; 46 decisionReason?: PermissionDecisionReason; 47 onRejectFeedbackChange: (value: string) => void; 48 onAcceptFeedbackChange: (value: string) => void; 49 onClassifierDescriptionChange?: (value: string) => void; 50 classifierDescription?: string; 51 /** Whether the initial classifier description was empty. When true, hides the option. */ 52 initialClassifierDescriptionEmpty?: boolean; 53 existingAllowDescriptions?: string[]; 54 yesInputMode?: boolean; 55 noInputMode?: boolean; 56 /** Editable prefix rule content (e.g., "npm run:*"). When set, replaces Haiku-based suggestions. */ 57 editablePrefix?: string; 58 /** Callback when the user edits the prefix value. */ 59 onEditablePrefixChange?: (value: string) => void; 60}): OptionWithDescription<BashToolUseOption>[] { 61 const options: OptionWithDescription<BashToolUseOption>[] = []; 62 if (yesInputMode) { 63 options.push({ 64 type: 'input', 65 label: 'Yes', 66 value: 'yes', 67 placeholder: 'and tell Claude what to do next', 68 onChange: onAcceptFeedbackChange, 69 allowEmptySubmitToCancel: true 70 }); 71 } else { 72 options.push({ 73 label: 'Yes', 74 value: 'yes' 75 }); 76 } 77 78 // Only show "always allow" options when not restricted by allowManagedPermissionRulesOnly 79 if (shouldShowAlwaysAllowOptions()) { 80 // Show an editable input for the prefix rule instead of the 81 // Haiku-generated suggestion label — but only when the suggestions 82 // don't contain non-Bash items (addDirectories, Read rules) that 83 // the editable prefix can't represent. 84 const hasNonBashSuggestions = suggestions.some(s => s.type === 'addDirectories' || s.type === 'addRules' && s.rules?.some(r => r.toolName !== BASH_TOOL_NAME)); 85 if (editablePrefix !== undefined && onEditablePrefixChange && !hasNonBashSuggestions && suggestions.length > 0) { 86 options.push({ 87 type: 'input', 88 label: 'Yes, and don\u2019t ask again for', 89 value: 'yes-prefix-edited', 90 placeholder: 'command prefix (e.g., npm run:*)', 91 initialValue: editablePrefix, 92 onChange: onEditablePrefixChange, 93 allowEmptySubmitToCancel: true, 94 showLabelWithValue: true, 95 labelValueSeparator: ': ', 96 resetCursorOnUpdate: true 97 }); 98 } else if (suggestions.length > 0) { 99 const label = generateShellSuggestionsLabel(suggestions, BASH_TOOL_NAME, stripBashRedirections); 100 if (label) { 101 options.push({ 102 label, 103 value: 'yes-apply-suggestions' 104 }); 105 } 106 } 107 108 // Add classifier-reviewed option if enabled, the initial description was 109 // non-empty, the description doesn't already exist in the allow list, 110 // and the decision reason is NOT a server-side classifier block 111 // (prompt-based rules don't help when the server-side classifier triggers first). 112 // Skip when the editable prefix option is already shown — they serve the 113 // same role and having two identical-looking "don't ask again" inputs is confusing. 114 const editablePrefixShown = options.some(o => o.value === 'yes-prefix-edited'); 115 if ("external" === 'ant' && !editablePrefixShown && isClassifierPermissionsEnabled() && onClassifierDescriptionChange && !initialClassifierDescriptionEmpty && !descriptionAlreadyExists(classifierDescription ?? '', existingAllowDescriptions) && decisionReason?.type !== 'classifier') { 116 options.push({ 117 type: 'input', 118 label: 'Yes, and don\u2019t ask again for', 119 value: 'yes-classifier-reviewed', 120 placeholder: 'describe what to allow...', 121 initialValue: classifierDescription ?? '', 122 onChange: onClassifierDescriptionChange, 123 allowEmptySubmitToCancel: true, 124 showLabelWithValue: true, 125 labelValueSeparator: ': ', 126 resetCursorOnUpdate: true 127 }); 128 } 129 } 130 if (noInputMode) { 131 options.push({ 132 type: 'input', 133 label: 'No', 134 value: 'no', 135 placeholder: 'and tell Claude what to do differently', 136 onChange: onRejectFeedbackChange, 137 allowEmptySubmitToCancel: true 138 }); 139 } else { 140 options.push({ 141 label: 'No', 142 value: 'no' 143 }); 144 } 145 return options; 146} 147//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJCQVNIX1RPT0xfTkFNRSIsImV4dHJhY3RPdXRwdXRSZWRpcmVjdGlvbnMiLCJpc0NsYXNzaWZpZXJQZXJtaXNzaW9uc0VuYWJsZWQiLCJQZXJtaXNzaW9uRGVjaXNpb25SZWFzb24iLCJQZXJtaXNzaW9uVXBkYXRlIiwic2hvdWxkU2hvd0Fsd2F5c0FsbG93T3B0aW9ucyIsIk9wdGlvbldpdGhEZXNjcmlwdGlvbiIsImdlbmVyYXRlU2hlbGxTdWdnZXN0aW9uc0xhYmVsIiwiQmFzaFRvb2xVc2VPcHRpb24iLCJkZXNjcmlwdGlvbkFscmVhZHlFeGlzdHMiLCJkZXNjcmlwdGlvbiIsImV4aXN0aW5nRGVzY3JpcHRpb25zIiwibm9ybWFsaXplZCIsInRvTG93ZXJDYXNlIiwidHJpbUVuZCIsInNvbWUiLCJleGlzdGluZyIsInN0cmlwQmFzaFJlZGlyZWN0aW9ucyIsImNvbW1hbmQiLCJjb21tYW5kV2l0aG91dFJlZGlyZWN0aW9ucyIsInJlZGlyZWN0aW9ucyIsImxlbmd0aCIsImJhc2hUb29sVXNlT3B0aW9ucyIsInN1Z2dlc3Rpb25zIiwiZGVjaXNpb25SZWFzb24iLCJvblJlamVjdEZlZWRiYWNrQ2hhbmdlIiwib25BY2NlcHRGZWVkYmFja0NoYW5nZSIsIm9uQ2xhc3NpZmllckRlc2NyaXB0aW9uQ2hhbmdlIiwiY2xhc3NpZmllckRlc2NyaXB0aW9uIiwiaW5pdGlhbENsYXNzaWZpZXJEZXNjcmlwdGlvbkVtcHR5IiwiZXhpc3RpbmdBbGxvd0Rlc2NyaXB0aW9ucyIsInllc0lucHV0TW9kZSIsIm5vSW5wdXRNb2RlIiwiZWRpdGFibGVQcmVmaXgiLCJvbkVkaXRhYmxlUHJlZml4Q2hhbmdlIiwidmFsdWUiLCJvcHRpb25zIiwicHVzaCIsInR5cGUiLCJsYWJlbCIsInBsYWNlaG9sZGVyIiwib25DaGFuZ2UiLCJhbGxvd0VtcHR5U3VibWl0VG9DYW5jZWwiLCJoYXNOb25CYXNoU3VnZ2VzdGlvbnMiLCJzIiwicnVsZXMiLCJyIiwidG9vbE5hbWUiLCJ1bmRlZmluZWQiLCJpbml0aWFsVmFsdWUiLCJzaG93TGFiZWxXaXRoVmFsdWUiLCJsYWJlbFZhbHVlU2VwYXJhdG9yIiwicmVzZXRDdXJzb3JPblVwZGF0ZSIsImVkaXRhYmxlUHJlZml4U2hvd24iLCJvIl0sInNvdXJjZXMiOlsiYmFzaFRvb2xVc2VPcHRpb25zLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCQVNIX1RPT0xfTkFNRSB9IGZyb20gJy4uLy4uLy4uL3Rvb2xzL0Jhc2hUb29sL3Rvb2xOYW1lLmpzJ1xuaW1wb3J0IHsgZXh0cmFjdE91dHB1dFJlZGlyZWN0aW9ucyB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL2Jhc2gvY29tbWFuZHMuanMnXG5pbXBvcnQgeyBpc0NsYXNzaWZpZXJQZXJtaXNzaW9uc0VuYWJsZWQgfSBmcm9tICcuLi8uLi8uLi91dGlscy9wZXJtaXNzaW9ucy9iYXNoQ2xhc3NpZmllci5qcydcbmltcG9ydCB0eXBlIHsgUGVybWlzc2lvbkRlY2lzaW9uUmVhc29uIH0gZnJvbSAnLi4vLi4vLi4vdXRpbHMvcGVybWlzc2lvbnMvUGVybWlzc2lvblJlc3VsdC5qcydcbmltcG9ydCB0eXBlIHsgUGVybWlzc2lvblVwZGF0ZSB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL3Blcm1pc3Npb25zL1Blcm1pc3Npb25VcGRhdGVTY2hlbWEuanMnXG5pbXBvcnQgeyBzaG91bGRTaG93QWx3YXlzQWxsb3dPcHRpb25zIH0gZnJvbSAnLi4vLi4vLi4vdXRpbHMvcGVybWlzc2lvbnMvcGVybWlzc2lvbnNMb2FkZXIuanMnXG5pbXBvcnQgdHlwZSB7IE9wdGlvbldpdGhEZXNjcmlwdGlvbiB9IGZyb20gJy4uLy4uL0N1c3RvbVNlbGVjdC9zZWxlY3QuanMnXG5pbXBvcnQgeyBnZW5lcmF0ZVNoZWxsU3VnZ2VzdGlvbnNMYWJlbCB9IGZyb20gJy4uL3NoZWxsUGVybWlzc2lvbkhlbHBlcnMuanMnXG5cbmV4cG9ydCB0eXBlIEJhc2hUb29sVXNlT3B0aW9uID1cbiAgfCAneWVzJ1xuICB8ICd5ZXMtYXBwbHktc3VnZ2VzdGlvbnMnXG4gIHwgJ3llcy1wcmVmaXgtZWRpdGVkJ1xuICB8ICd5ZXMtY2xhc3NpZmllci1yZXZpZXdlZCdcbiAgfCAnbm8nXG5cbi8qKlxuICogQ2hlY2sgaWYgYSBkZXNjcmlwdGlvbiBhbHJlYWR5IGV4aXN0cyBpbiB0aGUgYWxsb3cgbGlzdC5cbiAqIENvbXBhcmVzIGxvd2VyY2FzZSBhbmQgdHJhaWxpbmctd2hpdGVzcGFjZS10cmltbWVkIHZlcnNpb25zLlxuICovXG5mdW5jdGlvbiBkZXNjcmlwdGlvbkFscmVhZHlFeGlzdHMoXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmcsXG4gIGV4aXN0aW5nRGVzY3JpcHRpb25zOiBzdHJpbmdbXSxcbik6IGJvb2xlYW4ge1xuICBjb25zdCBub3JtYWxpemVkID0gZGVzY3JpcHRpb24udG9Mb3dlckNhc2UoKS50cmltRW5kKClcbiAgcmV0dXJuIGV4aXN0aW5nRGVzY3JpcHRpb25zLnNvbWUoXG4gICAgZXhpc3RpbmcgPT4gZXhpc3RpbmcudG9Mb3dlckNhc2UoKS50cmltRW5kKCkgPT09IG5vcm1hbGl6ZWQsXG4gIClcbn1cblxuLyoqXG4gKiBTdHJpcCBvdXRwdXQgcmVkaXJlY3Rpb25zIHNvIGZpbGVuYW1lcyBkb24ndCBzaG93IGFzIGNvbW1hbmRzIGluIHRoZSBsYWJlbC5cbiAqL1xuZnVuY3Rpb24gc3RyaXBCYXNoUmVkaXJlY3Rpb25zKGNvbW1hbmQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHsgY29tbWFuZFdpdGhvdXRSZWRpcmVjdGlvbnMsIHJlZGlyZWN0aW9ucyB9ID1cbiAgICBleHRyYWN0T3V0cHV0UmVkaXJlY3Rpb25zKGNvbW1hbmQpXG4gIC8vIE9ubHkgdXNlIHN0cmlwcGVkIHZlcnNpb24gaWYgdGhlcmUgd2VyZSBhY3R1YWwgcmVkaXJlY3Rpb25zXG4gIHJldHVybiByZWRpcmVjdGlvbnMubGVuZ3RoID4gMCA/IGNvbW1hbmRXaXRob3V0UmVkaXJlY3Rpb25zIDogY29tbWFuZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gYmFzaFRvb2xVc2VPcHRpb25zKHtcbiAgc3VnZ2VzdGlvbnMgPSBbXSxcbiAgZGVjaXNpb25SZWFzb24sXG4gIG9uUmVqZWN0RmVlZGJhY2tDaGFuZ2UsXG4gIG9uQWNjZXB0RmVlZGJhY2tDaGFuZ2UsXG4gIG9uQ2xhc3NpZmllckRlc2NyaXB0aW9uQ2hhbmdlLFxuICBjbGFzc2lmaWVyRGVzY3JpcHRpb24sXG4gIGluaXRpYWxDbGFzc2lmaWVyRGVzY3JpcHRpb25FbXB0eSA9IGZhbHNlLFxuICBleGlzdGluZ0FsbG93RGVzY3JpcHRpb25zID0gW10sXG4gIHllc0lucHV0TW9kZSA9IGZhbHNlLFxuICBub0lucHV0TW9kZSA9IGZhbHNlLFxuICBlZGl0YWJsZVByZWZpeCxcbiAgb25FZGl0YWJsZVByZWZpeENoYW5nZSxcbn06IHtcbiAgc3VnZ2VzdGlvbnM/OiBQZXJtaXNzaW9uVXBkYXRlW11cbiAgZGVjaXNpb25SZWFzb24/OiBQZXJtaXNzaW9uRGVjaXNpb25SZWFzb25cbiAgb25SZWplY3RGZWVkYmFja0NoYW5nZTogKHZhbHVlOiBzdHJpbmcpID0+IHZvaWRcbiAgb25BY2NlcHRGZWVkYmFja0NoYW5nZTogKHZhbHVlOiBzdHJpbmcpID0+IHZvaWRcbiAgb25DbGFzc2lmaWVyRGVzY3JpcHRpb25DaGFuZ2U/OiAodmFsdWU6IHN0cmluZykgPT4gdm9pZFxuICBjbGFzc2lmaWVyRGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgLyoqIFdoZXRoZXIgdGhlIGluaXRpYWwgY2xhc3NpZmllciBkZXNjcmlwdGlvbiB3YXMgZW1wdHkuIFdoZW4gdHJ1ZSwgaGlkZXMgdGhlIG9wdGlvbi4gKi9cbiAgaW5pdGlhbENsYXNzaWZpZXJEZXNjcmlwdGlvbkVtcHR5PzogYm9vbGVhblxuICBleGlzdGluZ0FsbG93RGVzY3JpcHRpb25zPzogc3RyaW5nW11cbiAgeWVzSW5wdXRNb2RlPzogYm9vbGVhblxuICBub0lucHV0TW9kZT86IGJvb2xlYW5cbiAgLyoqIEVkaXRhYmxlIHByZWZpeCBydWxlIGNvbnRlbnQgKGUuZy4sIFwibnBtIHJ1bjoqXCIpLiBXaGVuIHNldCwgcmVwbGFjZXMgSGFpa3UtYmFzZWQgc3VnZ2VzdGlvbnMuICovXG4gIGVkaXRhYmxlUHJlZml4Pzogc3RyaW5nXG4gIC8qKiBDYWxsYmFjayB3aGVuIHRoZSB1c2VyIGVkaXRzIHRoZSBwcmVmaXggdmFsdWUuICovXG4gIG9uRWRpdGFibGVQcmVmaXhDaGFuZ2U/OiAodmFsdWU6IHN0cmluZykgPT4gdm9pZFxufSk6IE9wdGlvbldpdGhEZXNjcmlwdGlvbjxCYXNoVG9vbFVzZU9wdGlvbj5bXSB7XG4gIGNvbnN0IG9wdGlvbnM6IE9wdGlvbldpdGhEZXNjcmlwdGlvbjxCYXNoVG9vbFVzZU9wdGlvbj5bXSA9IFtdXG5cbiAgaWYgKHllc0lucHV0TW9kZSkge1xuICAgIG9wdGlvbnMucHVzaCh7XG4gICAgICB0eXBlOiAnaW5wdXQnLFxuICAgICAgbGFiZWw6ICdZZXMnLFxuICAgICAgdmFsdWU6ICd5ZXMnLFxuICAgICAgcGxhY2Vob2xkZXI6ICdhbmQgdGVsbCBDbGF1ZGUgd2hhdCB0byBkbyBuZXh0JyxcbiAgICAgIG9uQ2hhbmdlOiBvbkFjY2VwdEZlZWRiYWNrQ2hhbmdlLFxuICAgICAgYWxsb3dFbXB0eVN1Ym1pdFRvQ2FuY2VsOiB0cnVlLFxuICAgIH0pXG4gIH0gZWxzZSB7XG4gICAgb3B0aW9ucy5wdXNoKHtcbiAgICAgIGxhYmVsOiAnWWVzJyxcbiAgICAgIHZhbHVlOiAneWVzJyxcbiAgICB9KVxuICB9XG5cbiAgLy8gT25seSBzaG93IFwiYWx3YXlzIGFsbG93XCIgb3B0aW9ucyB3aGVuIG5vdCByZXN0cmljdGVkIGJ5IGFsbG93TWFuYWdlZFBlcm1pc3Npb25SdWxlc09ubHlcbiAgaWYgKHNob3VsZFNob3dBbHdheXNBbGxvd09wdGlvbnMoKSkge1xuICAgIC8vIFNob3cgYW4gZWRpdGFibGUgaW5wdXQgZm9yIHRoZSBwcmVmaXggcnVsZSBpbnN0ZWFkIG9mIHRoZVxuICAgIC8vIEhhaWt1LWdlbmVyYXRlZCBzdWdnZXN0aW9uIGxhYmVsIOKAlCBidXQgb25seSB3aGVuIHRoZSBzdWdnZXN0aW9uc1xuICAgIC8vIGRvbid0IGNvbnRhaW4gbm9uLUJhc2ggaXRlbXMgKGFkZERpcmVjdG9yaWVzLCBSZWFkIHJ1bGVzKSB0aGF0XG4gICAgLy8gdGhlIGVkaXRhYmxlIHByZWZpeCBjYW4ndCByZXByZXNlbnQuXG4gICAgY29uc3QgaGFzTm9uQmFzaFN1Z2dlc3Rpb25zID0gc3VnZ2VzdGlvbnMuc29tZShcbiAgICAgIHMgPT5cbiAgICAgICAgcy50eXBlID09PSAnYWRkRGlyZWN0b3JpZXMnIHx8XG4gICAgICAgIChzLnR5cGUgPT09ICdhZGRSdWxlcycgJiZcbiAgICAgICAgICBzLnJ1bGVzPy5zb21lKHIgPT4gci50b29sTmFtZSAhPT0gQkFTSF9UT09MX05BTUUpKSxcbiAgICApXG4gICAgaWYgKFxuICAgICAgZWRpdGFibGVQcmVmaXggIT09IHVuZGVmaW5lZCAmJlxuICAgICAgb25FZGl0YWJsZVByZWZpeENoYW5nZSAmJlxuICAgICAgIWhhc05vbkJhc2hTdWdnZXN0aW9ucyAmJlxuICAgICAgc3VnZ2VzdGlvbnMubGVuZ3RoID4gMFxuICAgICkge1xuICAgICAgb3B0aW9ucy5wdXNoKHtcbiAgICAgICAgdHlwZTogJ2lucHV0JyxcbiAgICAgICAgbGFiZWw6ICdZZXMsIGFuZCBkb25cXHUyMDE5dCBhc2sgYWdhaW4gZm9yJyxcbiAgICAgICAgdmFsdWU6ICd5ZXMtcHJlZml4LWVkaXRlZCcsXG4gICAgICAgIHBsYWNlaG9sZGVyOiAnY29tbWFuZCBwcmVmaXggKGUuZy4sIG5wbSBydW46KiknLFxuICAgICAgICBpbml0aWFsVmFsdWU6IGVkaXRhYmxlUHJlZml4LFxuICAgICAgICBvbkNoYW5nZTogb25FZGl0YWJsZVByZWZpeENoYW5nZSxcbiAgICAgICAgYWxsb3dFbXB0eVN1Ym1pdFRvQ2FuY2VsOiB0cnVlLFxuICAgICAgICBzaG93TGFiZWxXaXRoVmFsdWU6IHRydWUsXG4gICAgICAgIGxhYmVsVmFsdWVTZXBhcmF0b3I6ICc6ICcsXG4gICAgICAgIHJlc2V0Q3Vyc29yT25VcGRhdGU6IHRydWUsXG4gICAgICB9KVxuICAgIH0gZWxzZSBpZiAoc3VnZ2VzdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbGFiZWwgPSBnZW5lcmF0ZVNoZWxsU3VnZ2VzdGlvbnNMYWJlbChcbiAgICAgICAgc3VnZ2VzdGlvbnMsXG4gICAgICAgIEJBU0hfVE9PTF9OQU1FLFxuICAgICAgICBzdHJpcEJhc2hSZWRpcmVjdGlvbnMsXG4gICAgICApXG5cbiAgICAgIGlmIChsYWJlbCkge1xuICAgICAgICBvcHRpb25zLnB1c2goe1xuICAgICAgICAgIGxhYmVsLFxuICAgICAgICAgIHZhbHVlOiAneWVzLWFwcGx5LXN1Z2dlc3Rpb25zJyxcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBZGQgY2xhc3NpZmllci1yZXZpZXdlZCBvcHRpb24gaWYgZW5hYmxlZCwgdGhlIGluaXRpYWwgZGVzY3JpcHRpb24gd2FzXG4gICAgLy8gbm9uLWVtcHR5LCB0aGUgZGVzY3JpcHRpb24gZG9lc24ndCBhbHJlYWR5IGV4aXN0IGluIHRoZSBhbGxvdyBsaXN0LFxuICAgIC8vIGFuZCB0aGUgZGVjaXNpb24gcmVhc29uIGlzIE5PVCBhIHNlcnZlci1zaWRlIGNsYXNzaWZpZXIgYmxvY2tcbiAgICAvLyAocHJvbXB0LWJhc2VkIHJ1bGVzIGRvbid0IGhlbHAgd2hlbiB0aGUgc2VydmVyLXNpZGUgY2xhc3NpZmllciB0cmlnZ2VycyBmaXJzdCkuXG4gICAgLy8gU2tpcCB3aGVuIHRoZSBlZGl0YWJsZSBwcmVmaXggb3B0aW9uIGlzIGFscmVhZHkgc2hvd24g4oCUIHRoZXkgc2VydmUgdGhlXG4gICAgLy8gc2FtZSByb2xlIGFuZCBoYXZpbmcgdHdvIGlkZW50aWNhbC1sb29raW5nIFwiZG9uJ3QgYXNrIGFnYWluXCIgaW5wdXRzIGlzIGNvbmZ1c2luZy5cbiAgICBjb25zdCBlZGl0YWJsZVByZWZpeFNob3duID0gb3B0aW9ucy5zb21lKFxuICAgICAgbyA9PiBvLnZhbHVlID09PSAneWVzLXByZWZpeC1lZGl0ZWQnLFxuICAgIClcbiAgICBpZiAoXG4gICAgICBcImV4dGVybmFsXCIgPT09ICdhbnQnICYmXG4gICAgICAhZWRpdGFibGVQcmVmaXhTaG93biAmJlxuICAgICAgaXNDbGFzc2lmaWVyUGVybWlzc2lvbnNFbmFibGVkKCkgJiZcbiAgICAgIG9uQ2xhc3NpZmllckRlc2NyaXB0aW9uQ2hhbmdlICYmXG4gICAgICAhaW5pdGlhbENsYXNzaWZpZXJEZXNjcmlwdGlvbkVtcHR5ICYmXG4gICAgICAhZGVzY3JpcHRpb25BbHJlYWR5RXhpc3RzKFxuICAgICAgICBjbGFzc2lmaWVyRGVzY3JpcHRpb24gPz8gJycsXG4gICAgICAgIGV4aXN0aW5nQWxsb3dEZXNjcmlwdGlvbnMsXG4gICAgICApICYmXG4gICAgICBkZWNpc2lvblJlYXNvbj8udHlwZSAhPT0gJ2NsYXNzaWZpZXInXG4gICAgKSB7XG4gICAgICBvcHRpb25zLnB1c2goe1xuICAgICAgICB0eXBlOiAnaW5wdXQnLFxuICAgICAgICBsYWJlbDogJ1llcywgYW5kIGRvblxcdTIwMTl0IGFzayBhZ2FpbiBmb3InLFxuICAgICAgICB2YWx1ZTogJ3llcy1jbGFzc2lmaWVyLXJldmlld2VkJyxcbiAgICAgICAgcGxhY2Vob2xkZXI6ICdkZXNjcmliZSB3aGF0IHRvIGFsbG93Li4uJyxcbiAgICAgICAgaW5pdGlhbFZhbHVlOiBjbGFzc2lmaWVyRGVzY3JpcHRpb24gPz8gJycsXG4gICAgICAgIG9uQ2hhbmdlOiBvbkNsYXNzaWZpZXJEZXNjcmlwdGlvbkNoYW5nZSxcbiAgICAgICAgYWxsb3dFbXB0eVN1Ym1pdFRvQ2FuY2VsOiB0cnVlLFxuICAgICAgICBzaG93TGFiZWxXaXRoVmFsdWU6IHRydWUsXG4gICAgICAgIGxhYmVsVmFsdWVTZXBhcmF0b3I6ICc6ICcsXG4gICAgICAgIHJlc2V0Q3Vyc29yT25VcGRhdGU6IHRydWUsXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIGlmIChub0lucHV0TW9kZSkge1xuICAgIG9wdGlvbnMucHVzaCh7XG4gICAgICB0eXBlOiAnaW5wdXQnLFxuICAgICAgbGFiZWw6ICdObycsXG4gICAgICB2YWx1ZTogJ25vJyxcbiAgICAgIHBsYWNlaG9sZGVyOiAnYW5kIHRlbGwgQ2xhdWRlIHdoYXQgdG8gZG8gZGlmZmVyZW50bHknLFxuICAgICAgb25DaGFuZ2U6IG9uUmVqZWN0RmVlZGJhY2tDaGFuZ2UsXG4gICAgICBhbGxvd0VtcHR5U3VibWl0VG9DYW5jZWw6IHRydWUsXG4gICAgfSlcbiAgfSBlbHNlIHtcbiAgICBvcHRpb25zLnB1c2goe1xuICAgICAgbGFiZWw6ICdObycsXG4gICAgICB2YWx1ZTogJ25vJyxcbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIG9wdGlvbnNcbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsY0FBYyxRQUFRLHFDQUFxQztBQUNwRSxTQUFTQyx5QkFBeUIsUUFBUSxpQ0FBaUM7QUFDM0UsU0FBU0MsOEJBQThCLFFBQVEsOENBQThDO0FBQzdGLGNBQWNDLHdCQUF3QixRQUFRLGdEQUFnRDtBQUM5RixjQUFjQyxnQkFBZ0IsUUFBUSxzREFBc0Q7QUFDNUYsU0FBU0MsNEJBQTRCLFFBQVEsaURBQWlEO0FBQzlGLGNBQWNDLHFCQUFxQixRQUFRLDhCQUE4QjtBQUN6RSxTQUFTQyw2QkFBNkIsUUFBUSw4QkFBOEI7QUFFNUUsT0FBTyxLQUFLQyxpQkFBaUIsR0FDekIsS0FBSyxHQUNMLHVCQUF1QixHQUN2QixtQkFBbUIsR0FDbkIseUJBQXlCLEdBQ3pCLElBQUk7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQyx3QkFBd0JBLENBQy9CQyxXQUFXLEVBQUUsTUFBTSxFQUNuQkMsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLENBQy9CLEVBQUUsT0FBTyxDQUFDO0VBQ1QsTUFBTUMsVUFBVSxHQUFHRixXQUFXLENBQUNHLFdBQVcsQ0FBQyxDQUFDLENBQUNDLE9BQU8sQ0FB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