copy.tsx 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. import { c as _c } from "react/compiler-runtime";
  2. import { mkdir, writeFile } from 'fs/promises';
  3. import { marked, type Tokens } from 'marked';
  4. import { tmpdir } from 'os';
  5. import { join } from 'path';
  6. import React, { useRef } from 'react';
  7. import type { CommandResultDisplay } from '../../commands.js';
  8. import type { OptionWithDescription } from '../../components/CustomSelect/select.js';
  9. import { Select } from '../../components/CustomSelect/select.js';
  10. import { Byline } from '../../components/design-system/Byline.js';
  11. import { KeyboardShortcutHint } from '../../components/design-system/KeyboardShortcutHint.js';
  12. import { Pane } from '../../components/design-system/Pane.js';
  13. import type { KeyboardEvent } from '../../ink/events/keyboard-event.js';
  14. import { stringWidth } from '../../ink/stringWidth.js';
  15. import { setClipboard } from '../../ink/termio/osc.js';
  16. import { Box, Text } from '../../ink.js';
  17. import { logEvent } from '../../services/analytics/index.js';
  18. import type { LocalJSXCommandCall } from '../../types/command.js';
  19. import type { AssistantMessage, Message } from '../../types/message.js';
  20. import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js';
  21. import { extractTextContent, stripPromptXMLTags } from '../../utils/messages.js';
  22. import { countCharInString } from '../../utils/stringUtils.js';
  23. const COPY_DIR = join(tmpdir(), 'claude');
  24. const RESPONSE_FILENAME = 'response.md';
  25. const MAX_LOOKBACK = 20;
  26. type CodeBlock = {
  27. code: string;
  28. lang: string | undefined;
  29. };
  30. function extractCodeBlocks(markdown: string): CodeBlock[] {
  31. const tokens = marked.lexer(stripPromptXMLTags(markdown));
  32. const blocks: CodeBlock[] = [];
  33. for (const token of tokens) {
  34. if (token.type === 'code') {
  35. const codeToken = token as Tokens.Code;
  36. blocks.push({
  37. code: codeToken.text,
  38. lang: codeToken.lang
  39. });
  40. }
  41. }
  42. return blocks;
  43. }
  44. /**
  45. * Walk messages newest-first, returning text from assistant messages that
  46. * actually said something (skips tool-use-only turns and API errors).
  47. * Index 0 = latest, 1 = second-to-latest, etc. Caps at MAX_LOOKBACK.
  48. */
  49. export function collectRecentAssistantTexts(messages: Message[]): string[] {
  50. const texts: string[] = [];
  51. for (let i = messages.length - 1; i >= 0 && texts.length < MAX_LOOKBACK; i--) {
  52. const msg = messages[i];
  53. if (msg?.type !== 'assistant' || msg.isApiErrorMessage) continue;
  54. const content = (msg as AssistantMessage).message.content;
  55. if (!Array.isArray(content)) continue;
  56. const text = extractTextContent(content, '\n\n');
  57. if (text) texts.push(text);
  58. }
  59. return texts;
  60. }
  61. export function fileExtension(lang: string | undefined): string {
  62. if (lang) {
  63. // Sanitize to prevent path traversal (e.g. ```../../etc/passwd)
  64. // Language identifiers are alphanumeric: python, tsx, jsonc, etc.
  65. const sanitized = lang.replace(/[^a-zA-Z0-9]/g, '');
  66. if (sanitized && sanitized !== 'plaintext') {
  67. return `.${sanitized}`;
  68. }
  69. }
  70. return '.txt';
  71. }
  72. async function writeToFile(text: string, filename: string): Promise<string> {
  73. const filePath = join(COPY_DIR, filename);
  74. await mkdir(COPY_DIR, {
  75. recursive: true
  76. });
  77. await writeFile(filePath, text, 'utf-8');
  78. return filePath;
  79. }
  80. async function copyOrWriteToFile(text: string, filename: string): Promise<string> {
  81. const raw = await setClipboard(text);
  82. if (raw) process.stdout.write(raw);
  83. const lineCount = countCharInString(text, '\n') + 1;
  84. const charCount = text.length;
  85. // Also write to a temp file — clipboard paths are best-effort (OSC 52 needs
  86. // terminal support), so the file provides a reliable fallback.
  87. try {
  88. const filePath = await writeToFile(text, filename);
  89. return `已复制到剪贴板(${charCount} 个字符,${lineCount} 行)\n同时写入到 ${filePath}`;
  90. } catch {
  91. return `已复制到剪贴板(${charCount} 个字符,${lineCount} 行)`;
  92. }
  93. }
  94. function truncateLine(text: string, maxLen: number): string {
  95. const firstLine = text.split('\n')[0] ?? '';
  96. if (stringWidth(firstLine) <= maxLen) {
  97. return firstLine;
  98. }
  99. let result = '';
  100. let width = 0;
  101. const targetWidth = maxLen - 1;
  102. for (const char of firstLine) {
  103. const charWidth = stringWidth(char);
  104. if (width + charWidth > targetWidth) break;
  105. result += char;
  106. width += charWidth;
  107. }
  108. return result + '\u2026';
  109. }
  110. type PickerProps = {
  111. fullText: string;
  112. codeBlocks: CodeBlock[];
  113. messageAge: number;
  114. onDone: (result?: string, options?: {
  115. display?: CommandResultDisplay;
  116. }) => void;
  117. };
  118. type PickerSelection = number | 'full' | 'always';
  119. function CopyPicker(t0) {
  120. const $ = _c(33);
  121. const {
  122. fullText,
  123. codeBlocks,
  124. messageAge,
  125. onDone
  126. } = t0;
  127. const focusedRef = useRef("full");
  128. const t1 = `${fullText.length} chars, ${countCharInString(fullText, "\n") + 1} lines`;
  129. let t2;
  130. if ($[0] !== t1) {
  131. t2 = {
  132. label: "完整响应",
  133. value: "full" as const,
  134. description: t1
  135. };
  136. $[0] = t1;
  137. $[1] = t2;
  138. } else {
  139. t2 = $[1];
  140. }
  141. let t3;
  142. if ($[2] !== codeBlocks || $[3] !== t2) {
  143. let t4;
  144. if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
  145. t4 = {
  146. label: "始终复制完整响应",
  147. value: "always" as const,
  148. description: "将来跳过此选择器(通过 /config 还原)"
  149. };
  150. $[5] = t4;
  151. } else {
  152. t4 = $[5];
  153. }
  154. t3 = [t2, ...codeBlocks.map(_temp), t4];
  155. $[2] = codeBlocks;
  156. $[3] = t2;
  157. $[4] = t3;
  158. } else {
  159. t3 = $[4];
  160. }
  161. const options = t3;
  162. let t4;
  163. if ($[6] !== codeBlocks || $[7] !== fullText) {
  164. t4 = function getSelectionContent(selected) {
  165. if (selected === "full" || selected === "always") {
  166. return {
  167. text: fullText,
  168. filename: RESPONSE_FILENAME
  169. };
  170. }
  171. const block_0 = codeBlocks[selected];
  172. return {
  173. text: block_0.code,
  174. filename: `copy${fileExtension(block_0.lang)}`,
  175. blockIndex: selected
  176. };
  177. };
  178. $[6] = codeBlocks;
  179. $[7] = fullText;
  180. $[8] = t4;
  181. } else {
  182. t4 = $[8];
  183. }
  184. const getSelectionContent = t4;
  185. let t5;
  186. if ($[9] !== codeBlocks.length || $[10] !== getSelectionContent || $[11] !== messageAge || $[12] !== onDone) {
  187. t5 = async function handleSelect(selected_0) {
  188. const content = getSelectionContent(selected_0);
  189. if (selected_0 === "always") {
  190. if (!getGlobalConfig().copyFullResponse) {
  191. saveGlobalConfig(_temp2);
  192. }
  193. logEvent("tengu_copy", {
  194. block_count: codeBlocks.length,
  195. always: true,
  196. message_age: messageAge
  197. });
  198. const result = await copyOrWriteToFile(content.text, content.filename);
  199. onDone(`${result}\n首选项已保存。使用 /config 更改 copyFullResponse`);
  200. return;
  201. }
  202. logEvent("tengu_copy", {
  203. selected_block: content.blockIndex,
  204. block_count: codeBlocks.length,
  205. message_age: messageAge
  206. });
  207. const result_0 = await copyOrWriteToFile(content.text, content.filename);
  208. onDone(result_0);
  209. };
  210. $[9] = codeBlocks.length;
  211. $[10] = getSelectionContent;
  212. $[11] = messageAge;
  213. $[12] = onDone;
  214. $[13] = t5;
  215. } else {
  216. t5 = $[13];
  217. }
  218. const handleSelect = t5;
  219. let t6;
  220. if ($[14] !== codeBlocks.length || $[15] !== getSelectionContent || $[16] !== messageAge || $[17] !== onDone) {
  221. const handleWrite = async function handleWrite(selected_1) {
  222. const content_0 = getSelectionContent(selected_1);
  223. logEvent("tengu_copy", {
  224. selected_block: content_0.blockIndex,
  225. block_count: codeBlocks.length,
  226. message_age: messageAge,
  227. write_shortcut: true
  228. });
  229. ;
  230. try {
  231. const filePath = await writeToFile(content_0.text, content_0.filename);
  232. onDone(`已写入 ${filePath}`);
  233. } catch (t7) {
  234. const e = t7;
  235. onDone(`写入文件失败:${e instanceof Error ? e.message : e}`);
  236. }
  237. };
  238. t6 = function handleKeyDown(e_0) {
  239. if (e_0.key === "w") {
  240. e_0.preventDefault();
  241. handleWrite(focusedRef.current);
  242. }
  243. };
  244. $[14] = codeBlocks.length;
  245. $[15] = getSelectionContent;
  246. $[16] = messageAge;
  247. $[17] = onDone;
  248. $[18] = t6;
  249. } else {
  250. t6 = $[18];
  251. }
  252. const handleKeyDown = t6;
  253. let t7;
  254. if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
  255. t7 = <Text dimColor={true}>选择要复制的内容:</Text>;
  256. $[19] = t7;
  257. } else {
  258. t7 = $[19];
  259. }
  260. let t8;
  261. if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
  262. t8 = value => {
  263. focusedRef.current = value;
  264. };
  265. $[20] = t8;
  266. } else {
  267. t8 = $[20];
  268. }
  269. let t9;
  270. if ($[21] !== handleSelect) {
  271. t9 = selected_2 => {
  272. handleSelect(selected_2);
  273. };
  274. $[21] = handleSelect;
  275. $[22] = t9;
  276. } else {
  277. t9 = $[22];
  278. }
  279. let t10;
  280. if ($[23] !== onDone) {
  281. t10 = () => {
  282. onDone("复制已取消", {
  283. display: "system"
  284. });
  285. };
  286. $[23] = onDone;
  287. $[24] = t10;
  288. } else {
  289. t10 = $[24];
  290. }
  291. let t11;
  292. if ($[25] !== options || $[26] !== t10 || $[27] !== t9) {
  293. t11 = <Select options={options} hideIndexes={false} onFocus={t8} onChange={t9} onCancel={t10} />;
  294. $[25] = options;
  295. $[26] = t10;
  296. $[27] = t9;
  297. $[28] = t11;
  298. } else {
  299. t11 = $[28];
  300. }
  301. let t12;
  302. if ($[29] === Symbol.for("react.memo_cache_sentinel")) {
  303. t12 = <Text dimColor={true}><Byline><KeyboardShortcutHint shortcut="enter" action="复制" /><KeyboardShortcutHint shortcut="w" action="写入文件" /><KeyboardShortcutHint shortcut="esc" action="取消" /></Byline></Text>;
  304. $[29] = t12;
  305. } else {
  306. t12 = $[29];
  307. }
  308. let t13;
  309. if ($[30] !== handleKeyDown || $[31] !== t11) {
  310. t13 = <Pane><Box flexDirection="column" gap={1} tabIndex={0} autoFocus={true} onKeyDown={handleKeyDown}>{t7}{t11}{t12}</Box></Pane>;
  311. $[30] = handleKeyDown;
  312. $[31] = t11;
  313. $[32] = t13;
  314. } else {
  315. t13 = $[32];
  316. }
  317. return t13;
  318. }
  319. function _temp2(c) {
  320. return {
  321. ...c,
  322. copyFullResponse: true
  323. };
  324. }
  325. function _temp(block, index) {
  326. const blockLines = countCharInString(block.code, "\n") + 1;
  327. return {
  328. label: truncateLine(block.code, 60),
  329. value: index,
  330. description: [block.lang, blockLines > 1 ? `${blockLines} lines` : undefined].filter(Boolean).join(", ") || undefined
  331. };
  332. }
  333. export const call: LocalJSXCommandCall = async (onDone, context, args) => {
  334. const texts = collectRecentAssistantTexts(context.messages);
  335. if (texts.length === 0) {
  336. onDone('没有可复制的助手消息');
  337. return null;
  338. }
  339. // /copy N reaches back N-1 messages (1 = latest, 2 = second-to-latest, ...)
  340. let age = 0;
  341. const arg = args?.trim();
  342. if (arg) {
  343. const n = Number(arg);
  344. if (!Number.isInteger(n) || n < 1) {
  345. onDone(`用法:/copy [N],其中 N 是 1(最新)、2、3、\u2026。得到:${arg}`);
  346. return null;
  347. }
  348. if (n > texts.length) {
  349. onDone(`只有 ${texts.length} 个助手${texts.length === 1 ? '消息' : '消息'} 可供复制`);
  350. return null;
  351. }
  352. age = n - 1;
  353. }
  354. const text = texts[age]!;
  355. const codeBlocks = extractCodeBlocks(text);
  356. const config = getGlobalConfig();
  357. if (codeBlocks.length === 0 || config.copyFullResponse) {
  358. logEvent('tengu_copy', {
  359. always: config.copyFullResponse,
  360. block_count: codeBlocks.length,
  361. message_age: age
  362. });
  363. const result = await copyOrWriteToFile(text, RESPONSE_FILENAME);
  364. onDone(result);
  365. return null;
  366. }
  367. return <CopyPicker fullText={text} codeBlocks={codeBlocks} messageAge={age} onDone={onDone} />;
  368. };
  369. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJta2RpciIsIndyaXRlRmlsZSIsIm1hcmtlZCIsIlRva2VucyIsInRtcGRpciIsImpvaW4iLCJSZWFjdCIsInVzZVJlZiIsIkNvbW1hbmRSZXN1bHREaXNwbGF5IiwiT3B0aW9uV2l0aERlc2NyaXB0aW9uIiwiU2VsZWN0IiwiQnlsaW5lIiwiS2V5Ym9hcmRTaG9ydGN1dEhpbnQiLCJQYW5lIiwiS2V5Ym9hcmRFdmVudCIsInN0cmluZ1dpZHRoIiwic2V0Q2xpcGJvYXJkIiwiQm94IiwiVGV4dCIsImxvZ0V2ZW50IiwiTG9jYWxKU1hDb21tYW5kQ2FsbCIsIkFzc2lzdGFudE1lc3NhZ2UiLCJNZXNzYWdlIiwiZ2V0R2xvYmFsQ29uZmlnIiwic2F2ZUdsb2JhbENvbmZpZyIsImV4dHJhY3RUZXh0Q29udGVudCIsInN0cmlwUHJvbXB0WE1MVGFncyIsImNvdW50Q2hhckluU3RyaW5nIiwiQ09QWV9ESVIiLCJSRVNQT05TRV9GSUxFTkFNRSIsIk1BWF9MT09LQkFDSyIsIkNvZGVCbG9jayIsImNvZGUiLCJsYW5nIiwiZXh0cmFjdENvZGVCbG9ja3MiLCJtYXJrZG93biIsInRva2VucyIsImxleGVyIiwiYmxvY2tzIiwidG9rZW4iLCJ0eXBlIiwiY29kZVRva2VuIiwiQ29kZSIsInB1c2giLCJ0ZXh0IiwiY29sbGVjdFJlY2VudEFzc2lzdGFudFRleHRzIiwibWVzc2FnZXMiLCJ0ZXh0cyIsImkiLCJsZW5ndGgiLCJtc2ciLCJpc0FwaUVycm9yTWVzc2FnZSIsImNvbnRlbnQiLCJtZXNzYWdlIiwiQXJyYXkiLCJpc0FycmF5IiwiZmlsZUV4dGVuc2lvbiIsInNhbml0aXplZCIsInJlcGxhY2UiLCJ3cml0ZVRvRmlsZSIsImZpbGVuYW1lIiwiUHJvbWlzZSIsImZpbGVQYXRoIiwicmVjdXJzaXZlIiwiY29weU9yV3JpdGVUb0ZpbGUiLCJyYXciLCJwcm9jZXNzIiwic3Rkb3V0Iiwid3JpdGUiLCJsaW5lQ291bnQiLCJjaGFyQ291bnQiLCJ0cnVuY2F0ZUxpbmUiLCJtYXhMZW4iLCJmaXJzdExpbmUiLCJzcGxpdCIsInJlc3VsdCIsIndpZHRoIiwidGFyZ2V0V2lkdGgiLCJjaGFyIiwiY2hhcldpZHRoIiwiUGlja2VyUHJvcHMiLCJmdWxsVGV4dCIsImNvZGVCbG9ja3MiLCJtZXNzYWdlQWdlIiwib25Eb25lIiwib3B0aW9ucyIsImRpc3BsYXkiLCJQaWNrZXJTZWxlY3Rpb24iLCJDb3B5UGlja2VyIiwidDAiLCIkIiwiX2MiLCJmb2N1c2VkUmVmIiwidDEiLCJ0MiIsImxhYmVsIiwidmFsdWUiLCJjb25zdCIsImRlc2NyaXB0aW9uIiwidDMiLCJ0NCIsIlN5bWJvbCIsImZvciIsIm1hcCIsIl90ZW1wIiwiZ2V0U2VsZWN0aW9uQ29udGVudCIsInNlbGVjdGVkIiwiYmxvY2tfMCIsImJsb2NrIiwiYmxvY2tJbmRleCIsInQ1IiwiaGFuZGxlU2VsZWN0Iiwic2VsZWN0ZWRfMCIsImNvcHlGdWxsUmVzcG9uc2UiLCJfdGVtcDIiLCJibG9ja19jb3VudCIsImFsd2F5cyIsIm1lc3NhZ2VfYWdlIiwic2VsZWN0ZWRfYmxvY2siLCJyZXN1bHRfMCIsInQ2IiwiaGFuZGxlV3JpdGUiLCJzZWxlY3RlZF8xIiwiY29udGVudF8wIiwid3JpdGVfc2hvcnRjdXQiLCJ0NyIsImUiLCJFcnJvciIsImhhbmRsZUtleURvd24iLCJlXzAiLCJrZXkiLCJwcmV2ZW50RGVmYXVsdCIsImN1cnJlbnQiLCJ0OCIsInQ5Iiwic2VsZWN0ZWRfMiIsInQxMCIsInQxMSIsInQxMiIsInQxMyIsImMiLCJpbmRleCIsImJsb2NrTGluZXMiLCJ1bmRlZmluZWQiLCJmaWx0ZXIiLCJCb29sZWFuIiwiY2FsbCIsImNvbnRleHQiLCJhcmdzIiwiYWdlIiwiYXJnIiwidHJpbSIsIm4iLCJOdW1iZXIiLCJpc0ludGVnZXIiLCJjb25maWciXSwic291cmNlcyI6WyJjb3B5LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBta2Rpciwgd3JpdGVGaWxlIH0gZnJvbSAnZnMvcHJvbWlzZXMnXG5pbXBvcnQgeyBtYXJrZWQsIHR5cGUgVG9rZW5zIH0gZnJvbSAnbWFya2VkJ1xuaW1wb3J0IHsgdG1wZGlyIH0gZnJvbSAnb3MnXG5pbXBvcnQgeyBqb2luIH0gZnJvbSAncGF0aCdcbmltcG9ydCBSZWFjdCwgeyB1c2VSZWYgfSBmcm9tICdyZWFjdCdcbmltcG9ydCB0eXBlIHsgQ29tbWFuZFJlc3VsdERpc3BsYXkgfSBmcm9tICcuLi8uLi9jb21tYW5kcy5qcydcbmltcG9ydCB0eXBlIHsgT3B0aW9uV2l0aERlc2NyaXB0aW9uIH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9DdXN0b21TZWxlY3Qvc2VsZWN0LmpzJ1xuaW1wb3J0IHsgU2VsZWN0IH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9DdXN0b21TZWxlY3Qvc2VsZWN0LmpzJ1xuaW1wb3J0IHsgQnlsaW5lIH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9kZXNpZ24tc3lzdGVtL0J5bGluZS5qcydcbmltcG9ydCB7IEtleWJvYXJkU2hvcnRjdXRIaW50IH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9kZXNpZ24tc3lzdGVtL0tleWJvYXJkU2hvcnRjdXRIaW50LmpzJ1xuaW1wb3J0IHsgUGFuZSB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvZGVzaWduLXN5c3RlbS9QYW5lLmpzJ1xuaW1wb3J0IHR5cGUgeyBLZXlib2FyZEV2ZW50IH0gZnJvbSAnLi4vLi4vaW5rL2V2ZW50cy9rZXlib2FyZC1ldmVudC5qcydcbmltcG9ydCB7IHN0cmluZ1dpZHRoIH0gZnJvbSAnLi4vLi4vaW5rL3N0cmluZ1dpZHRoLmpzJ1xuaW1wb3J0IHsgc2V0Q2xpcGJvYXJkIH0gZnJvbSAnLi4vLi4vaW5rL3Rlcm1pby9vc2MuanMnXG5pbXBvcnQgeyBCb3gsIFRleHQgfSBmcm9tICcuLi8uLi9pbmsuanMnXG5pbXBvcnQgeyBsb2dFdmVudCB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FuYWx5dGljcy9pbmRleC5qcydcbmltcG9ydCB0eXBlIHsgTG9jYWxKU1hDb21tYW5kQ2FsbCB9IGZyb20gJy4uLy4uL3R5cGVzL2NvbW1hbmQuanMnXG5pbXBvcnQgdHlwZSB7IEFzc2lzdGFudE1lc3NhZ2UsIE1lc3NhZ2UgfSBmcm9tICcuLi8uLi90eXBlcy9tZXNzYWdlLmpzJ1xuaW1wb3J0IHsgZ2V0R2xvYmFsQ29uZmlnLCBzYXZlR2xvYmFsQ29uZmlnIH0gZnJvbSAnLi4vLi4vdXRpbHMvY29uZmlnLmpzJ1xuaW1wb3J0IHsgZXh0cmFjdFRleHRDb250ZW50LCBzdHJpcFByb21wdFhNTFRhZ3MgfSBmcm9tICcuLi8uLi91dGlscy9tZXNzYWdlcy5qcydcbmltcG9ydCB7IGNvdW50Q2hhckluU3RyaW5nIH0gZnJvbSAnLi4vLi4vdXRpbHMvc3RyaW5nVXRpbHMuanMnXG5cbmNvbnN0IENPUFlfRElSID0gam9pbih0bXBkaXIoKSwgJ2NsYXVkZScpXG5jb25zdCBSRVNQT05TRV9GSUxFTkFNRSA9ICdyZXNwb25zZS5tZCdcbmNvbnN0IE1BWF9MT09LQkFDSyA9IDIwXG5cbnR5cGUgQ29kZUJsb2NrID0ge1xuICBjb2RlOiBzdHJpbmdcbiAgbGFuZzogc3RyaW5nIHwgdW5kZWZpbmVkXG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RDb2RlQmxvY2tzKG1hcmtkb3duOiBzdHJpbmcpOiBDb2RlQmxvY2tbXSB7XG4gIGNvbnN0IHRva2VucyA9IG1hcmtlZC5sZXhlcihzdHJpcFByb21wdFhNTFRhZ3MobWFya2Rvd24pKVxuICBjb25zdCBibG9ja3M6IENvZGVCbG9ja1tdID0gW11cbiAgZm9yIChjb25zdCB0b2tlbiBvZiB0b2tlbnMpIHtcbiAgICBpZiAodG9rZW4udHlwZSA9PT0gJ2NvZGUnKSB7XG4gICAgICBjb25zdCBjb2RlVG9rZW4gPSB0b2tlbiBhcyBUb2tlbnMuQ29kZVxuICAgICAgYmxvY2tzLnB1c2goeyBjb2RlOiBjb2RlVG9rZW4udGV4dCwgbGFuZzogY29kZVRva2VuLmxhbmcgfSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJsb2Nrc1xufVxuXG4vKipcbiAqIFdhbGsgbWVzc2FnZXMgbmV3ZXN0LWZpcnN0LCByZXR1cm5pbmcgdGV4dCBmcm9tIGFzc2lzdGFudCBtZXNzYWdlcyB0aGF0XG4gKiBhY3R1YWxseSBzYWlkIHNvbWV0aGluZyAoc2tpcHMgdG9vbC11c2Utb25seSB0dXJucyBhbmQgQVBJIGVycm9ycykuXG4gKiBJbmRleCAwID0gbGF0ZXN0LCAxID0gc2Vjb25kLXRvLWxhdGVzdCwgZXRjLiBDYXBzIGF0IE1BWF9MT09LQkFDSy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbGxlY3RSZWNlbnRBc3Npc3RhbnRUZXh0cyhtZXNzYWdlczogTWVzc2FnZVtdKTogc3RyaW5nW10ge1xuICBjb25zdCB0ZXh0czogc3RyaW5nW10gPSBbXVxuICBmb3IgKFxuICAgIGxldCBpID0gbWVzc2FnZXMubGVuZ3RoIC0gMTtcbiAgICBpID49IDAgJiYgdGV4dHMubGVuZ3RoIDwgTUFYX0xPT0tCQUNLO1xuICAgIGktLVxuICApIHtcbiAgICBjb25zdCBtc2cgPSBtZXNzYWdlc1tpXVxuICAgIGlmIChtc2c/LnR5cGUgIT09ICdhc3Npc3RhbnQnIHx8IG1zZy5pc0FwaUVycm9yTWVzc2FnZSkgY29udGludWVcbiAgICBjb25zdCBjb250ZW50ID0gKG1zZyBhcyBBc3Npc3RhbnRNZXNzYWdlKS5tZXNzYWdlLmNvbnRlbnRcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoY29udGVudCkpIGNvbnRpbnVlXG4gICAgY29uc3QgdGV4dCA9IGV4dHJhY3RUZXh0Q29udGVudChjb250ZW50LCAnXFxuXFxuJylcbiAgICBpZiAodGV4dCkgdGV4dHMucHVzaCh0ZXh0KVxuICB9XG4gIHJldHVybiB0ZXh0c1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmlsZUV4dGVuc2lvbihsYW5nOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICBpZiAobGFuZykge1xuICAgIC8vIFNhbml0aXplIHRvIHByZXZlbnQgcGF0aCB0cmF2ZXJzYWwgKGUuZy4gYGBgLi4vLi4vZXRjL3Bhc3N3ZClcbiAgICAvLyBMYW5ndWFnZSBpZGVudGlmaWVycyBhcmUgYWxwaGFudW1lcmljOiBweXRob24sIHRzeCwganNvbmMsIGV0Yy5cbiAgICBjb25zdCBzYW5pdGl6ZWQgPSBsYW5nLnJlcGxhY2UoL1teYS16QS1aMC05XS9nLCAnJylcbiAgICBpZiAoc2FuaXRpemVkICYmIHNhbml0aXplZCAhPT0gJ3BsYWludGV4dCcpIHtcbiAgICAgIHJldHVybiBgLiR7c2FuaXRpemVkfWBcbiAgICB9XG4gIH1cbiAgcmV0dXJuICcudHh0J1xufVxuXG5hc3luYyBmdW5jdGlvbiB3cml0ZVRvRmlsZSh0ZXh0OiBzdHJpbmcsIGZpbGVuYW1lOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBmaWxlUGF0aCA9IGpvaW4oQ09QWV9ESVIsIGZpbGVuYW1lKVxuICBhd2FpdCBta2RpcihDT1BZX0RJUiwgeyByZWN1cnNpdmU6IHRydWUgfSlcbiAgYXdhaXQgd3JpdGVGaWxlKGZpbGVQYXRoLCB0ZXh0LCAndXRmLTgnKVxuICByZXR1cm4gZmlsZVBhdGhcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29weU9yV3JpdGVUb0ZpbGUoXG4gIHRleHQ6IHN0cmluZyxcbiAgZmlsZW5hbWU6IHN0cmluZyxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHJhdyA9IGF3YWl0IHNldENsaXBib2FyZCh0ZXh0KVxuICBpZiAocmF3KSBwcm9jZXNzLnN0ZG91dC53cml0ZShyYXcpXG4gIGNvbnN0IGxpbmVDb3VudCA9IGNvdW50Q2hhckluU3RyaW5nKHRleHQsICdcXG4nKSArIDFcbiAgY29uc3QgY2hhckNvdW50ID0gdGV4dC5sZW5ndGhcbiAgLy8gQWxzbyB3cml0ZSB0byBhIHRlbXAgZmlsZSDigJQgY2xpcGJvYXJkIHBhdGhzIGFyZSBiZXN0LWVmZm9ydCAoT1NDIDUyIG5lZWRzXG4gIC8vIHRlcm1pbmFsIHN1cHBvcnQpLCBzbyB0aGUgZmlsZSBwcm92aWRlcyBhIHJlbGlhYmxlIGZhbGxiYWNrLlxuICB0cnkge1xuICAgIGNvbnN0IGZpbGVQYXRoID0gYXdhaXQgd3JpdGVUb0ZpbGUodGV4dCwgZmlsZW5hbWUpXG4gICAgcmV0dXJuIGBDb3BpZWQgdG8gY2xpcGJvYXJkICgke2NoYXJDb3VudH0gY2hhcmFjdGVycywgJHtsaW5lQ291bnR9IGxpbmVzKVxcbkFsc28gd3JpdHRlbiB0byAke2ZpbGVQYXRofWBcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGBDb3BpZWQgdG8gY2xpcGJvYXJkICgke2NoYXJDb3VudH0gY2hhcmFjdGVycywgJHtsaW5lQ291bnR9IGxpbmVzKWBcbiAgfVxufVxuXG5mdW5jdGlvbiB0cnVuY2F0ZUxpbmUodGV4dDogc3RyaW5nLCBtYXhMZW46IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGZpcnN0TGluZSA9IHRleHQuc3BsaXQoJ1xcbicpWzBdID8/ICcnXG4gIGlmIChzdHJpbmdXaWR0aChmaXJzdExpbmUpIDw9IG1heExlbikge1xuICAgIHJldHVybiBmaXJzdExpbmVcbiAgfVxuICBsZXQgcmVzdWx0ID0gJydcbiAgbGV0IHdpZHRoID0gMFxuICBjb25zdCB0YXJnZXRXaWR0aCA9IG1heExlbiAtIDFcbiAgZm9yIChjb25zdCBjaGFyIG9mIGZpcnN0TGluZSkge1xuICAgIGNvbnN0IGNoYXJXaWR0aCA9IHN0cmluZ1dpZHRoKGNoYXIpXG4gICAgaWYgKHdpZHRoICsgY2hhcldpZHRoID4gdGFyZ2V0V2lkdGgpIGJyZWFrXG4gICAgcmVzdWx0ICs9IGNoYXJcbiAgICB3aWR0aCArPSBjaGFyV2lkdGhcbiAgfVxuICByZXR1cm4gcmVzdWx0ICsgJ1xcdTIwMjYnXG59XG5cbnR5cGUgUGlja2VyUHJvcHMgPSB7XG4gIGZ1bGxUZXh0OiBzdHJpbmdcbiAgY29kZUJsb2NrczogQ29kZUJsb2NrW11cbiAgbWVzc2FnZUFnZTogbnVtYmVyXG4gIG9uRG9uZTogKFxuICAgIHJlc3VsdD86IHN0cmluZyxcbiAgICBvcHRpb25zPzogeyBkaXNwbGF5PzogQ29tbWFuZFJlc3VsdERpc3BsYXkgfSxcbiAgKSA9PiB2b2lkXG59XG5cbnR5cGUgUGlja2VyU2VsZWN0aW9uID0gbnVtYmVyIHwgJ2Z1bGwnIHwgJ2Fsd2F5cydcblxuZnVuY3Rpb24gQ29weVBpY2tlcih7XG4gIGZ1bGxUZXh0LFxuICBjb2RlQmxvY2tzLFxuICBtZXNzYWdlQWdlLFxuICBvbkRvbmUsXG59OiBQaWNrZXJQcm9wcyk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IGZvY3VzZWRSZWYgPSB1c2VSZWY8UGlja2VyU2VsZWN0aW9uPignZnVsbCcpXG5cbiAgY29uc3Qgb3B0aW9uczogT3B0aW9uV2l0aERlc2NyaXB0aW9uPFBpY2tlclNlbGVjdGlvbj5bXSA9IFtcbiAgICB7XG4gICAgICBsYWJlbDogJ0Z1bGwgcmVzcG9uc2UnLFxuICAgICAgdmFsdWU6ICdmdWxsJyBhcyBjb25zdCxcbiAgICAgIGRlc2NyaXB0aW9uOiBgJHtmdWxsVGV4dC5sZW5ndGh9IGNoYXJzLCAke2NvdW50Q2hhckluU3RyaW5nKGZ1bGxUZXh0LCAnXFxuJykgKyAxfSBsaW5lc2AsXG4gICAgfSxcbiAgICAuLi5jb2RlQmxvY2tzLm1hcCgoYmxvY2ssIGluZGV4KSA9PiB7XG4gICAgICBjb25zdCBibG9ja0xpbmVzID0gY291bnRDaGFySW5TdHJpbmcoYmxvY2suY29kZSwgJ1xcbicpICsgMVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbGFiZWw6IHRydW5jYXRlTGluZShibG9jay5jb2RlLCA2MCksXG4gICAgICAgIHZhbHVlOiBpbmRleCxcbiAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgW2Jsb2NrLmxhbmcsIGJsb2NrTGluZXMgPiAxID8gYCR7YmxvY2tMaW5lc30gbGluZXNgIDogdW5kZWZpbmVkXVxuICAgICAgICAgICAgLmZpbHRlcihCb29sZWFuKVxuICAgICAgICAgICAgLmpvaW4oJywgJykgfHwgdW5kZWZpbmVkLFxuICAgICAgfVxuICAgIH0pLFxuICAgIHtcbiAgICAgIGxhYmVsOiAnQWx3YXlzIGNvcHkgZnVsbCByZXNwb25zZScsXG4gICAgICB2YWx1ZTogJ2Fsd2F5cycgYXMgY29uc3QsXG4gICAgICBkZXNjcmlwdGlvbjogJ1NraXAgdGhpcyBwaWNrZXIgaW4gdGhlIGZ1dHVyZSAocmV2ZXJ0IHZpYSAvY29uZmlnKScsXG4gICAgfSxcbiAgXVxuXG4gIGZ1bmN0aW9uIGdldFNlbGVjdGlvbkNvbnRlbnQoc2VsZWN0ZWQ6IFBpY2tlclNlbGVjdGlvbik6IHtcbiAgICB0ZXh0OiBzdHJpbmdcbiAgICBmaWxlbmFtZTogc3RyaW5nXG4gICAgYmxvY2tJbmRleD86IG51bWJlclxuICB9IHtcbiAgICBpZiAoc2VsZWN0ZWQgPT09ICdmdWxsJyB8fCBzZWxlY3RlZCA9PT0gJ2Fsd2F5cycpIHtcbiAgICAgIHJldHVybiB7IHRleHQ6IGZ1bGxUZXh0LCBmaWxlbmFtZTogUkVTUE9OU0VfRklMRU5BTUUgfVxuICAgIH1cbiAgICBjb25zdCBibG9jayA9IGNvZGVCbG9ja3Nbc2VsZWN0ZWRdIVxuICAgIHJldHVybiB7XG4gICAgICB0ZXh0OiBibG9jay5jb2RlLFxuICAgICAgZmlsZW5hbWU6IGBjb3B5JHtmaWxlRXh0ZW5zaW9uKGJsb2NrLmxhbmcpfWAsXG4gICAgICBibG9ja0luZGV4OiBzZWxlY3RlZCxcbiAgICB9XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBoYW5kbGVTZWxlY3Qoc2VsZWN0ZWQ6IFBpY2tlclNlbGVjdGlvbik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNvbnRlbnQgPSBnZXRTZWxlY3Rpb25Db250ZW50KHNlbGVjdGVkKVxuICAgIGlmIChzZWxlY3RlZCA9PT0gJ2Fsd2F5cycpIHtcbiAgICAgIGlmICghZ2V0R2xvYmFsQ29uZmlnKCkuY29weUZ1bGxSZXNwb25zZSkge1xuICAgICAgICBzYXZlR2xvYmFsQ29uZmlnKGMgPT4gKHsgLi4uYywgY29weUZ1bGxSZXNwb25zZTogdHJ1ZSB9KSlcbiAgICAgIH1cbiAgICAgIGxvZ0V2ZW50KCd0ZW5ndV9jb3B5Jywge1xuICAgICAgICBibG9ja19jb3VudDogY29kZUJsb2Nrcy5sZW5ndGgsXG4gICAgICAgIGFsd2F5czogdHJ1ZSxcbiAgICAgICAgbWVzc2FnZV9hZ2U6IG1lc3NhZ2VBZ2UsXG4gICAgICB9KVxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29weU9yV3JpdGVUb0ZpbGUoY29udGVudC50ZXh0LCBjb250ZW50LmZpbGVuYW1lKVxuICAgICAgb25Eb25lKFxuICAgICAgICBgJHtyZXN1bHR9XFxuUHJlZmVyZW5jZSBzYXZlZC4gVXNlIC9jb25maWcgdG8gY2hhbmdlIGNvcHlGdWxsUmVzcG9uc2VgLFxuICAgICAgKVxuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGxvZ0V2ZW50KCd0ZW5ndV9jb3B5Jywge1xuICAgICAgc2VsZWN0ZWRfYmxvY2s6IGNvbnRlbnQuYmxvY2tJbmRleCxcbiAgICAgIGJsb2NrX2NvdW50OiBjb2RlQmxvY2tzLmxlbmd0aCxcbiAgICAgIG1lc3NhZ2VfYWdlOiBtZXNzYWdlQWdlLFxuICAgIH0pXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29weU9yV3JpdGVUb0ZpbGUoY29udGVudC50ZXh0LCBjb250ZW50LmZpbGVuYW1lKVxuICAgIG9uRG9uZShyZXN1bHQpXG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBoYW5kbGVXcml0ZShzZWxlY3RlZDogUGlja2VyU2VsZWN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY29udGVudCA9IGdldFNlbGVjdGlvbkNvbnRlbnQoc2VsZWN0ZWQpXG4gICAgbG9nRXZlbnQoJ3Rlbmd1X2NvcHknLCB7XG4gICAgICBzZWxlY3RlZF9ibG9jazogY29udGVudC5ibG9ja0luZGV4LFxuICAgICAgYmxvY2tfY291bnQ6IGNvZGVCbG9ja3MubGVuZ3RoLFxuICAgICAgbWVzc2FnZV9hZ2U6IG1lc3NhZ2VBZ2UsXG4gICAgICB3cml0ZV9zaG9ydGN1dDogdHJ1ZSxcbiAgICB9KVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBmaWxlUGF0aCA9IGF3YWl0IHdyaXRlVG9GaWxlKGNvbnRlbnQudGV4dCwgY29udGVudC5maWxlbmFtZSlcbiAgICAgIG9uRG9uZShgV3JpdHRlbiB0byAke2ZpbGVQYXRofWApXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgb25Eb25lKGBGYWlsZWQgdG8gd3JpdGUgZmlsZTogJHtlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBlfWApXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlS2V5RG93bihlOiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGUua2V5ID09PSAndycpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKVxuICAgICAgdm9pZCBoYW5kbGVXcml0ZShmb2N1c2VkUmVmLmN1cnJlbnQpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIChcbiAgICA8UGFuZT5cbiAgICAgIDxCb3hcbiAgICAgICAgZmxleERpcmVjdGlvbj1cImNvbHVtblwiXG4gICAgICAgIGdhcD17MX1cbiAgICAgICAgdGFiSW5kZXg9ezB9XG4gICAgICAgIGF1dG9Gb2N1c1xuICAgICAgICBvbktleURvd249e2hhbmRsZUtleURvd259XG4gICAgICA+XG4gICAgICAgIDxUZXh0IGRpbUNvbG9yPlNlbGVjdCBjb250ZW50IHRvIGNvcHk6PC9UZXh0PlxuICAgICAgICA8U2VsZWN0PFBpY2tlclNlbGVjdGlvbj5cbiAgICAgICAgICBvcHRpb25zPXtvcHRpb25zfVxuICAgICAgICAgIGhpZGVJbmRleGVzPXtmYWxzZX1cbiAgICAgICAgICBvbkZvY3VzPXt2YWx1ZSA9PiB7XG4gICAgICAgICAgICBmb2N1c2VkUmVmLmN1cnJlbnQgPSB2YWx1ZVxuICAgICAgICAgIH19XG4gICAgICAgICAgb25DaGFuZ2U9e3NlbGVjdGVkID0+IHtcbiAgICAgICAgICAgIHZvaWQgaGFuZGxlU2VsZWN0KHNlbGVjdGVkKVxuICAgICAgICAgIH19XG4gICAgICAgICAgb25DYW5jZWw9eygpID0+IHtcbiAgICAgICAgICAgIG9uRG9uZSgnQ29weSBjYW5jZWxsZWQnLCB7IGRpc3BsYXk6ICdzeXN0ZW0nIH0pXG4gICAgICAgICAgfX1cbiAgICAgICAgLz5cbiAgICAgICAgPFRleHQgZGltQ29sb3I+XG4gICAgICAgICAgPEJ5bGluZT5cbiAgICAgICAgICAgIDxLZXlib2FyZFNob3J0Y3V0SGludCBzaG9ydGN1dD1cImVudGVyXCIgYWN0aW9uPVwiY29weVwiIC8+XG4gICAgICAgICAgICA8S2V5Ym9hcmRTaG9ydGN1dEhpbnQgc2hvcnRjdXQ9XCJ3XCIgYWN0aW9uPVwid3JpdGUgdG8gZmlsZVwiIC8+XG4gICAgICAgICAgICA8S2V5Ym9hcmRTaG9ydGN1dEhpbnQgc2hvcnRjdXQ9XCJlc2NcIiBhY3Rpb249XCJjYW5jZWxcIiAvPlxuICAgICAgICAgIDwvQnlsaW5lPlxuICAgICAgICA8L1RleHQ+XG4gICAgICA8L0JveD5cbiAgICA8L1BhbmU+XG4gIClcbn1cblxuZXhwb3J0IGNvbnN0IGNhbGw6IExvY2FsSlNYQ29tbWFuZENhbGwgPSBhc3luYyAob25Eb25lLCBjb250ZXh0LCBhcmdzKSA9PiB7XG4gIGNvbnN0IHRleHRzID0gY29sbGVjdFJlY2VudEFzc2lzdGFudFRleHRzKGNvbnRleHQubWVzc2FnZXMpXG5cbiAgaWYgKHRleHRzLmxlbmd0aCA9PT0gMCkge1xuICAgIG9uRG9uZSgnTm8gYXNzaXN0YW50IG1lc3NhZ2UgdG8gY29weScpXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8vIC9jb3B5IE4gcmVhY2hlcyBiYWNrIE4tMSBtZXNzYWdlcyAoMSA9IGxhdGVzdCwgMiA9IHNlY29uZC10by1sYXRlc3QsIC4uLilcbiAgbGV0IGFnZSA9IDBcbiAgY29uc3QgYXJnID0gYXJncz8udHJpbSgpXG4gIGlmIChhcmcpIHtcbiAgICBjb25zdCBuID0gTnVtYmVyKGFyZylcbiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobikgfHwgbiA8IDEpIHtcbiAgICAgIG9uRG9uZShgVXNhZ2U6IC9jb3B5IFtOXSB3aGVyZSBOIGlzIDEgKGxhdGVzdCksIDIsIDMsIFxcdTIwMjYgR290OiAke2FyZ31gKVxuICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG4gICAgaWYgKG4gPiB0ZXh0cy5sZW5ndGgpIHtcbiAgICAgIG9uRG9uZShcbiAgICAgICAgYE9ubHkgJHt0ZXh0cy5sZW5ndGh9IGFzc2lzdGFudCAke3RleHRzLmxlbmd0aCA9PT0gMSA/ICdtZXNzYWdlJyA6ICdtZXNzYWdlcyd9IGF2YWlsYWJsZSB0byBjb3B5YCxcbiAgICAgIClcbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICAgIGFnZSA9IG4gLSAxXG4gIH1cblxuICBjb25zdCB0ZXh0ID0gdGV4dHNbYWdlXSFcbiAgY29uc3QgY29kZUJsb2NrcyA9IGV4dHJhY3RDb2RlQmxvY2tzKHRleHQpXG4gIGNvbnN0IGNvbmZpZyA9IGdldEdsb2JhbENvbmZpZygpXG5cbiAgaWYgKGNvZGVCbG9ja3MubGVuZ3RoID09PSAwIHx8IGNvbmZpZy5jb3B5RnVsbFJlc3BvbnNlKSB7XG4gICAgbG9nRXZlbnQoJ3Rlbmd1X2NvcHknLCB7XG4gICAgICBhbHdheXM6IGNvbmZpZy5jb3B5RnVsbFJlc3BvbnNlLFxuICAgICAgYmxvY2tfY291bnQ6IGNvZGVCbG9ja3MubGVuZ3RoLFxuICAgICAgbWVzc2FnZV9hZ2U6IGFnZSxcbiAgICB9KVxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvcHlPcldyaXRlVG9GaWxlKHRleHQsIFJFU1BPTlNFX0ZJTEVOQU1FKVxuICAgIG9uRG9uZShyZXN1bHQpXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPENvcHlQaWNrZXJcbiAgICAgIGZ1bGxUZXh0PXt0ZXh0fVxuICAgICAgY29kZUJsb2Nrcz17Y29kZUJsb2Nrc31cbiAgICAgIG1lc3NhZ2VBZ2U9e2FnZX1cbiAgICAgIG9uRG9uZT17b25Eb25lfVxuICAgIC8+XG4gIClcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLFNBQVNBLEtBQUssRUFBRUMsU0FBUyxRQUFRLGFBQWE7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