@dollhousemcp/mcp-server 2.0.28 → 2.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/generated/version.d.ts +2 -2
  3. package/dist/generated/version.js +3 -3
  4. package/dist/services/BuildInfoService.d.ts +9 -1
  5. package/dist/services/BuildInfoService.d.ts.map +1 -1
  6. package/dist/services/BuildInfoService.js +37 -3
  7. package/dist/tools/portfolio/submitToPortfolioTool.d.ts.map +1 -1
  8. package/dist/tools/portfolio/submitToPortfolioTool.js +4 -3
  9. package/dist/utils/permissionHookInstallers.d.ts +27 -0
  10. package/dist/utils/permissionHookInstallers.d.ts.map +1 -0
  11. package/dist/utils/permissionHookInstallers.js +465 -0
  12. package/dist/utils/permissionHookShared.d.ts +126 -0
  13. package/dist/utils/permissionHookShared.d.ts.map +1 -0
  14. package/dist/utils/permissionHookShared.js +388 -0
  15. package/dist/utils/permissionHookStatus.d.ts +10 -0
  16. package/dist/utils/permissionHookStatus.d.ts.map +1 -0
  17. package/dist/utils/permissionHookStatus.js +256 -0
  18. package/dist/utils/permissionHooks.d.ts +3 -73
  19. package/dist/utils/permissionHooks.d.ts.map +1 -1
  20. package/dist/utils/permissionHooks.js +4 -780
  21. package/dist/web/public/permissions.js +10 -0
  22. package/dist/web/public/setup.js +36 -0
  23. package/dist/web/routes/healthRoutes.d.ts +3 -0
  24. package/dist/web/routes/healthRoutes.d.ts.map +1 -1
  25. package/dist/web/routes/healthRoutes.js +22 -2
  26. package/dist/web/routes/permissionRoutes.d.ts +1 -0
  27. package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
  28. package/dist/web/routes/permissionRoutes.js +28 -7
  29. package/dist/web/routes/setupRoutes.d.ts +5 -1
  30. package/dist/web/routes/setupRoutes.d.ts.map +1 -1
  31. package/dist/web/routes/setupRoutes.js +28 -14
  32. package/dist/web/server.d.ts.map +1 -1
  33. package/dist/web/server.js +12 -1
  34. package/package.json +3 -1
  35. package/scripts/permission-hook-config.sh +67 -0
  36. package/scripts/pretooluse-dollhouse.sh +42 -13
  37. package/scripts/pretooluse-vscode.sh +23 -10
  38. package/scripts/pretooluse-windsurf.sh +6 -6
  39. package/server.json +2 -2
@@ -1,780 +1,4 @@
1
- import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
2
- import { access, chmod, copyFile, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
3
- import { dirname, join } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { homedir, platform } from 'node:os';
6
- import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
7
- import { logger } from './logger.js';
8
- function repoRootFromModule() {
9
- const currentFile = fileURLToPath(import.meta.url);
10
- return dirname(dirname(dirname(currentFile)));
11
- }
12
- function isMissingFileError(error) {
13
- return Boolean(error
14
- && typeof error === 'object'
15
- && 'code' in error
16
- && error.code === 'ENOENT');
17
- }
18
- function detectIndent(raw) {
19
- for (const line of raw.split('\n')) {
20
- if (line.length === 0 || line.startsWith('{') || line.startsWith('}'))
21
- continue;
22
- if (line.startsWith('\t'))
23
- return '\t';
24
- if (line.startsWith(' ')) {
25
- const spaces = line.length - line.trimStart().length;
26
- if (spaces >= 2)
27
- return spaces;
28
- }
29
- }
30
- return 2;
31
- }
32
- export function getPermissionHookScriptPath(homeDir = homedir()) {
33
- return join(homeDir, '.dollhouse', 'hooks', 'pretooluse-dollhouse.sh');
34
- }
35
- function getPermissionHookRunDir(homeDir = homedir()) {
36
- return join(homeDir, '.dollhouse', 'run');
37
- }
38
- function normalizeHookHost(host) {
39
- return UnicodeValidator.normalize(host).normalizedContent.trim().toLowerCase();
40
- }
41
- function isHookMarkerFilename(entry) {
42
- return entry.startsWith('hook-installed-') && entry.endsWith('.json');
43
- }
44
- function readHostSpecificHookStatus(homeDir, host) {
45
- const normalized = normalizeHookHost(host);
46
- const status = readMarkerStatus(getPermissionHookMarkerPath(homeDir, normalized));
47
- if (status.installed || status.assetsPrepared) {
48
- return status;
49
- }
50
- if (normalized === 'claude-code') {
51
- return readMarkerStatus(getPermissionHookMarkerPath(homeDir));
52
- }
53
- return { installed: false };
54
- }
55
- function collectHookMarkerPaths(homeDir) {
56
- const markerPaths = new Set([getPermissionHookMarkerPath(homeDir)]);
57
- const runDir = getPermissionHookRunDir(homeDir);
58
- try {
59
- for (const entry of readdirSync(runDir)) {
60
- if (isHookMarkerFilename(entry)) {
61
- markerPaths.add(join(runDir, entry));
62
- }
63
- }
64
- }
65
- catch {
66
- // No run dir yet — fall through to default false.
67
- }
68
- return markerPaths;
69
- }
70
- async function collectHookMarkerPathsAsync(homeDir) {
71
- const markerPaths = new Set([getPermissionHookMarkerPath(homeDir)]);
72
- const runDir = getPermissionHookRunDir(homeDir);
73
- try {
74
- for (const entry of await readdir(runDir)) {
75
- if (isHookMarkerFilename(entry)) {
76
- markerPaths.add(join(runDir, entry));
77
- }
78
- }
79
- }
80
- catch {
81
- // No run dir yet — fall through to default false.
82
- }
83
- return markerPaths;
84
- }
85
- function summarizeMarkerStatuses(markerPaths) {
86
- let fallback = { installed: false };
87
- for (const markerPath of markerPaths) {
88
- const status = readMarkerStatus(markerPath);
89
- if (status.installed)
90
- return status;
91
- if (!fallback.assetsPrepared && status.assetsPrepared)
92
- fallback = status;
93
- }
94
- return fallback;
95
- }
96
- function getHookWrapperBasename(host) {
97
- switch (normalizeHookHost(host)) {
98
- case 'vscode':
99
- return 'pretooluse-vscode.sh';
100
- case 'cursor':
101
- return 'pretooluse-cursor.sh';
102
- case 'windsurf':
103
- return 'pretooluse-windsurf.sh';
104
- case 'gemini-cli':
105
- return 'pretooluse-gemini.sh';
106
- case 'codex':
107
- return 'pretooluse-codex.sh';
108
- default:
109
- return null;
110
- }
111
- }
112
- function getHookWrapperPath(host, homeDir = homedir()) {
113
- const basename = getHookWrapperBasename(host);
114
- return basename ? join(homeDir, '.dollhouse', 'hooks', basename) : null;
115
- }
116
- function getHookSourcePath(host) {
117
- const root = repoRootFromModule();
118
- const basename = getHookWrapperBasename(host);
119
- return basename ? join(root, 'scripts', basename) : join(root, 'scripts', 'pretooluse-dollhouse.sh');
120
- }
121
- export function getPermissionHookMarkerPath(homeDir = homedir(), host) {
122
- if (!host) {
123
- return join(getPermissionHookRunDir(homeDir), 'hook-installed.json');
124
- }
125
- return join(getPermissionHookRunDir(homeDir), `hook-installed-${normalizeHookHost(host)}.json`);
126
- }
127
- export function getClaudeHookSettingsPath(homeDir = homedir()) {
128
- return join(homeDir, '.claude', 'settings.json');
129
- }
130
- export function getVsCodeHookSettingsPath(homeDir = homedir()) {
131
- return join(homeDir, '.copilot', 'hooks', 'dollhouse-permissions.json');
132
- }
133
- export function getVsCodeUserSettingsPath(homeDir = homedir()) {
134
- const currentPlatform = platform();
135
- if (currentPlatform === 'darwin') {
136
- return join(homeDir, 'Library', 'Application Support', 'Code', 'User', 'settings.json');
137
- }
138
- if (currentPlatform === 'win32') {
139
- const appData = process.env.APPDATA || join(homeDir, 'AppData', 'Roaming');
140
- return join(appData, 'Code', 'User', 'settings.json');
141
- }
142
- return join(homeDir, '.config', 'Code', 'User', 'settings.json');
143
- }
144
- export function getGeminiHookSettingsPath(homeDir = homedir()) {
145
- return join(homeDir, '.gemini', 'settings.json');
146
- }
147
- export function getCursorHookSettingsPath(homeDir = homedir()) {
148
- return join(homeDir, '.cursor', 'hooks.json');
149
- }
150
- export function getWindsurfHookSettingsPath(homeDir = homedir()) {
151
- return join(homeDir, '.codeium', 'windsurf', 'hooks.json');
152
- }
153
- export function getCodexHookSettingsPath(homeDir = homedir()) {
154
- return join(homeDir, '.codex', 'hooks.json');
155
- }
156
- export function getCodexConfigPath(homeDir = homedir()) {
157
- return join(homeDir, '.codex', 'config.toml');
158
- }
159
- function toPermissionHookStatus(raw) {
160
- if (typeof raw.host !== 'string' ||
161
- typeof raw.scriptPath !== 'string') {
162
- return { installed: false };
163
- }
164
- const scriptReady = existsSync(raw.scriptPath);
165
- const settingsReady = !raw.settingsPath || existsSync(raw.settingsPath);
166
- const additionalPathsReady = !raw.additionalPaths || raw.additionalPaths.every((path) => existsSync(path));
167
- const assetsPrepared = (raw.assetsPrepared ?? raw.configured ?? true) && scriptReady;
168
- const configured = (raw.configured ?? true) && scriptReady && settingsReady && additionalPathsReady;
169
- return {
170
- installed: configured,
171
- configured,
172
- assetsPrepared,
173
- host: raw.host,
174
- scriptPath: raw.scriptPath,
175
- settingsPath: raw.settingsPath,
176
- additionalPaths: raw.additionalPaths,
177
- };
178
- }
179
- function readMarkerStatus(markerPath) {
180
- try {
181
- const raw = readFileSync(markerPath, 'utf-8');
182
- return toPermissionHookStatus(JSON.parse(raw));
183
- }
184
- catch (error) {
185
- if (!isMissingFileError(error)) {
186
- logger.warn(`[Permissions] Failed to read hook marker at ${markerPath}: ${String(error)}`);
187
- }
188
- return { installed: false };
189
- }
190
- }
191
- export function getPermissionHookStatus(homeDir = homedir(), host) {
192
- if (host) {
193
- return readHostSpecificHookStatus(homeDir, host);
194
- }
195
- return summarizeMarkerStatuses(collectHookMarkerPaths(homeDir));
196
- }
197
- export async function getPermissionHookStatusAsync(homeDir = homedir(), host) {
198
- if (host) {
199
- return readHostSpecificHookStatus(homeDir, host);
200
- }
201
- return summarizeMarkerStatuses(await collectHookMarkerPathsAsync(homeDir));
202
- }
203
- function normalizeHooksRoot(parsed) {
204
- const hooksValue = parsed.hooks;
205
- if (!hooksValue || typeof hooksValue !== 'object' || Array.isArray(hooksValue)) {
206
- parsed.hooks = {};
207
- }
208
- return parsed.hooks;
209
- }
210
- function ensureCommandHook(parsed, eventName, command, matcher, extraHookFields = {}) {
211
- const hooksRoot = normalizeHooksRoot(parsed);
212
- const existingEntries = Array.isArray(hooksRoot[eventName])
213
- ? hooksRoot[eventName].filter((entry) => typeof entry === 'object' && entry !== null)
214
- : [];
215
- hooksRoot[eventName] = existingEntries;
216
- const commandExists = existingEntries.some((entry) => {
217
- const hooks = Array.isArray(entry?.hooks) ? entry.hooks : [];
218
- return hooks.some((hook) => hook?.type === 'command' && hook?.command === command);
219
- });
220
- if (commandExists) {
221
- return { changed: false, parsed };
222
- }
223
- const wildcardEntry = existingEntries.find((entry) => (entry?.matcher === matcher || entry?.matcher === undefined) && Array.isArray(entry?.hooks));
224
- if (wildcardEntry) {
225
- const hooks = wildcardEntry.hooks;
226
- hooks.push({
227
- type: 'command',
228
- command,
229
- ...extraHookFields,
230
- });
231
- }
232
- else {
233
- existingEntries.push({
234
- matcher,
235
- hooks: [
236
- {
237
- type: 'command',
238
- command,
239
- ...extraHookFields,
240
- },
241
- ],
242
- });
243
- }
244
- return { changed: true, parsed };
245
- }
246
- export function ensureClaudePreToolUseHook(parsed, command) {
247
- return ensureCommandHook(parsed, 'PreToolUse', command, '*');
248
- }
249
- export function ensureVsCodePreToolUseHook(parsed, command) {
250
- return ensureCommandHook(parsed, 'PreToolUse', command, '*');
251
- }
252
- export function ensureGeminiBeforeToolHook(parsed, command) {
253
- return ensureCommandHook(parsed, 'BeforeTool', command, '.*');
254
- }
255
- export function ensureCodexPreToolUseHook(parsed, command) {
256
- return ensureCommandHook(parsed, 'PreToolUse', command, 'Bash', {
257
- statusMessage: 'Checking Bash permissions',
258
- });
259
- }
260
- export function ensureCursorPreToolUseHook(parsed, command) {
261
- if (parsed.version !== 1) {
262
- parsed.version = 1;
263
- }
264
- const hooksRoot = normalizeHooksRoot(parsed);
265
- const existingEntries = Array.isArray(hooksRoot.preToolUse)
266
- ? hooksRoot.preToolUse.filter((entry) => typeof entry === 'object' && entry !== null)
267
- : [];
268
- hooksRoot.preToolUse = existingEntries;
269
- const commandExists = existingEntries.some((entry) => entry.command === command
270
- && (entry.type === 'command' || entry.type === undefined));
271
- if (commandExists) {
272
- return { changed: false, parsed };
273
- }
274
- existingEntries.push({
275
- type: 'command',
276
- command,
277
- matcher: '.*',
278
- });
279
- return { changed: true, parsed };
280
- }
281
- export function ensureWindsurfHooks(parsed, command) {
282
- const hooksRoot = normalizeHooksRoot(parsed);
283
- let changed = false;
284
- const ensureEventHook = (eventName) => {
285
- const existingEntries = Array.isArray(hooksRoot[eventName])
286
- ? hooksRoot[eventName].filter((entry) => typeof entry === 'object' && entry !== null)
287
- : [];
288
- hooksRoot[eventName] = existingEntries;
289
- const commandExists = existingEntries.some((entry) => entry.command === command && (entry.type === 'command' || entry.type === undefined));
290
- if (commandExists) {
291
- return;
292
- }
293
- existingEntries.push({
294
- type: 'command',
295
- command,
296
- });
297
- changed = true;
298
- };
299
- ensureEventHook('pre_run_command');
300
- ensureEventHook('pre_mcp_tool_use');
301
- return { changed, parsed };
302
- }
303
- async function copyHookAsset(sourcePath, targetPath) {
304
- await mkdir(dirname(targetPath), { recursive: true });
305
- const sourceRaw = await readFile(sourcePath, 'utf-8');
306
- let targetRaw;
307
- try {
308
- targetRaw = await readFile(targetPath, 'utf-8');
309
- }
310
- catch (error) {
311
- if (!isMissingFileError(error)) {
312
- throw error;
313
- }
314
- }
315
- const changed = targetRaw === undefined || sourceRaw !== targetRaw;
316
- if (changed) {
317
- await copyFile(sourcePath, targetPath);
318
- }
319
- else {
320
- await access(targetPath);
321
- }
322
- await chmod(targetPath, 0o755);
323
- return changed;
324
- }
325
- async function readOptionalUtf8(filePath, fallback) {
326
- try {
327
- return await readFile(filePath, 'utf-8');
328
- }
329
- catch (error) {
330
- if (isMissingFileError(error)) {
331
- return fallback;
332
- }
333
- throw error;
334
- }
335
- }
336
- async function writeBackupIfPresent(filePath, raw) {
337
- if (!existsSync(filePath)) {
338
- return undefined;
339
- }
340
- const backupPath = `${filePath}.dollhouse.bak`;
341
- await writeFile(backupPath, raw, 'utf-8');
342
- return backupPath;
343
- }
344
- async function mergeClaudeSettings(settingsPath, command) {
345
- await mkdir(dirname(settingsPath), { recursive: true });
346
- const raw = await readOptionalUtf8(settingsPath, '{}\n');
347
- const indent = detectIndent(raw);
348
- const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
349
- const { changed, parsed: updated } = ensureClaudePreToolUseHook(parsed, command);
350
- if (!changed) {
351
- return { changed: false };
352
- }
353
- const backupPath = await writeBackupIfPresent(settingsPath, raw);
354
- await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
355
- return { changed: true, backupPath };
356
- }
357
- async function mergeVsCodeHookSettings(settingsPath, command) {
358
- await mkdir(dirname(settingsPath), { recursive: true });
359
- const raw = await readOptionalUtf8(settingsPath, '{}\n');
360
- const indent = detectIndent(raw);
361
- const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
362
- const { changed, parsed: updated } = ensureVsCodePreToolUseHook(parsed, command);
363
- if (!changed) {
364
- return { changed: false };
365
- }
366
- const backupPath = await writeBackupIfPresent(settingsPath, raw);
367
- await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
368
- return { changed: true, backupPath };
369
- }
370
- async function mergeVsCodeUserSettings(settingsPath) {
371
- await mkdir(dirname(settingsPath), { recursive: true });
372
- const raw = await readOptionalUtf8(settingsPath, '{}\n');
373
- const indent = detectIndent(raw);
374
- const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
375
- const current = parsed['chat.hookFilesLocations'];
376
- const locations = (current && typeof current === 'object' && !Array.isArray(current))
377
- ? { ...current }
378
- : {};
379
- if (locations['~/.copilot/hooks'] === true) {
380
- return { changed: false };
381
- }
382
- locations['~/.copilot/hooks'] = true;
383
- parsed['chat.hookFilesLocations'] = locations;
384
- const backupPath = await writeBackupIfPresent(settingsPath, raw);
385
- await writeFile(settingsPath, JSON.stringify(parsed, null, indent) + '\n', 'utf-8');
386
- return { changed: true, backupPath };
387
- }
388
- async function mergeGeminiSettings(settingsPath, command) {
389
- await mkdir(dirname(settingsPath), { recursive: true });
390
- const raw = await readOptionalUtf8(settingsPath, '{}\n');
391
- const indent = detectIndent(raw);
392
- const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
393
- const { changed, parsed: updated } = ensureGeminiBeforeToolHook(parsed, command);
394
- if (!changed) {
395
- return { changed: false };
396
- }
397
- const backupPath = await writeBackupIfPresent(settingsPath, raw);
398
- await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
399
- return { changed: true, backupPath };
400
- }
401
- async function mergeCursorHooks(settingsPath, command) {
402
- await mkdir(dirname(settingsPath), { recursive: true });
403
- const raw = await readOptionalUtf8(settingsPath, '{\n "version": 1,\n "hooks": {}\n}\n');
404
- const indent = detectIndent(raw);
405
- const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
406
- const { changed, parsed: updated } = ensureCursorPreToolUseHook(parsed, command);
407
- if (!changed) {
408
- return { changed: false };
409
- }
410
- const backupPath = await writeBackupIfPresent(settingsPath, raw);
411
- await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
412
- return { changed: true, backupPath };
413
- }
414
- async function mergeWindsurfHooks(settingsPath, command) {
415
- await mkdir(dirname(settingsPath), { recursive: true });
416
- const raw = await readOptionalUtf8(settingsPath, '{\n "hooks": {}\n}\n');
417
- const indent = detectIndent(raw);
418
- const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
419
- const { changed, parsed: updated } = ensureWindsurfHooks(parsed, command);
420
- if (!changed) {
421
- return { changed: false };
422
- }
423
- const backupPath = await writeBackupIfPresent(settingsPath, raw);
424
- await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
425
- return { changed: true, backupPath };
426
- }
427
- async function mergeCodexHooks(hooksPath, command) {
428
- await mkdir(dirname(hooksPath), { recursive: true });
429
- const raw = await readOptionalUtf8(hooksPath, '{}\n');
430
- const indent = detectIndent(raw);
431
- const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
432
- const { changed, parsed: updated } = ensureCodexPreToolUseHook(parsed, command);
433
- if (!changed) {
434
- return { changed: false };
435
- }
436
- const backupPath = await writeBackupIfPresent(hooksPath, raw);
437
- await writeFile(hooksPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
438
- return { changed: true, backupPath };
439
- }
440
- function getTomlLineContent(line) {
441
- const commentIndex = line.indexOf('#');
442
- return (commentIndex >= 0 ? line.slice(0, commentIndex) : line).trim();
443
- }
444
- function isTomlSectionLine(line, section) {
445
- return getTomlLineContent(line) === `[${section}]`;
446
- }
447
- function parseTomlBooleanAssignment(line, key) {
448
- const content = getTomlLineContent(line);
449
- if (!content.startsWith(`${key} = `)) {
450
- return null;
451
- }
452
- const value = content.slice(`${key} = `.length).trim();
453
- if (value === 'true')
454
- return true;
455
- if (value === 'false')
456
- return false;
457
- return null;
458
- }
459
- function updateTomlBooleanAssignment(line, key, nextValue) {
460
- const commentIndex = line.indexOf('#');
461
- const commentSuffix = commentIndex >= 0 ? line.slice(commentIndex) : '';
462
- let prefixLength = 0;
463
- while (prefixLength < line.length && /\s/.test(line.charAt(prefixLength))) {
464
- prefixLength += 1;
465
- }
466
- const prefix = line.slice(0, prefixLength);
467
- const assignment = `${prefix}${key} = ${nextValue ? 'true' : 'false'}`;
468
- const trimmedCommentSuffix = commentSuffix.trimStart();
469
- const suffix = trimmedCommentSuffix.length > 0 ? ` ${trimmedCommentSuffix}` : '';
470
- return `${assignment}${suffix}`.trimEnd();
471
- }
472
- function stripTrailingNewlines(value) {
473
- let end = value.length;
474
- while (end > 0 && value.charAt(end - 1) === '\n') {
475
- end -= 1;
476
- }
477
- return value.slice(0, end);
478
- }
479
- function ensureCodexHooksEnabled(raw) {
480
- const lines = raw.length > 0 ? raw.split('\n') : [];
481
- const dottedIndex = lines.findIndex((line) => parseTomlBooleanAssignment(line, 'features.codex_hooks') !== null);
482
- if (dottedIndex >= 0) {
483
- if (parseTomlBooleanAssignment(lines[dottedIndex], 'features.codex_hooks') === true) {
484
- return { changed: false, content: raw };
485
- }
486
- const updatedLines = [...lines];
487
- updatedLines[dottedIndex] = updateTomlBooleanAssignment(updatedLines[dottedIndex], 'features.codex_hooks', true);
488
- return { changed: true, content: `${stripTrailingNewlines(updatedLines.join('\n'))}\n` };
489
- }
490
- const sectionIndex = lines.findIndex((line) => isTomlSectionLine(line, 'features'));
491
- if (sectionIndex >= 0) {
492
- const nextSectionIndex = lines.findIndex((line, index) => index > sectionIndex && getTomlLineContent(line).startsWith('[') && getTomlLineContent(line).endsWith(']'));
493
- const sectionEnd = nextSectionIndex >= 0 ? nextSectionIndex : lines.length;
494
- const keyIndex = lines.findIndex((line, index) => index > sectionIndex && index < sectionEnd && parseTomlBooleanAssignment(line, 'codex_hooks') !== null);
495
- if (keyIndex >= 0) {
496
- if (parseTomlBooleanAssignment(lines[keyIndex], 'codex_hooks') === true) {
497
- return { changed: false, content: raw };
498
- }
499
- const updatedLines = [...lines];
500
- updatedLines[keyIndex] = updateTomlBooleanAssignment(updatedLines[keyIndex], 'codex_hooks', true);
501
- return { changed: true, content: `${stripTrailingNewlines(updatedLines.join('\n'))}\n` };
502
- }
503
- const updatedLines = [...lines];
504
- updatedLines.splice(sectionIndex + 1, 0, 'codex_hooks = true');
505
- return { changed: true, content: `${stripTrailingNewlines(updatedLines.join('\n'))}\n` };
506
- }
507
- const prefix = raw.trim().length > 0 ? `${stripTrailingNewlines(raw)}\n\n` : '';
508
- return {
509
- changed: true,
510
- content: `${prefix}[features]\ncodex_hooks = true\n`,
511
- };
512
- }
513
- async function mergeCodexConfig(configPath) {
514
- await mkdir(dirname(configPath), { recursive: true });
515
- const raw = await readOptionalUtf8(configPath, '');
516
- const { changed, content } = ensureCodexHooksEnabled(raw);
517
- if (!changed) {
518
- return { changed: false };
519
- }
520
- const backupPath = await writeBackupIfPresent(configPath, raw);
521
- await writeFile(configPath, content, 'utf-8');
522
- return { changed: true, backupPath };
523
- }
524
- async function writeHookMarker(homeDir, marker) {
525
- const markerPath = getPermissionHookMarkerPath(homeDir, marker.host);
526
- await mkdir(dirname(markerPath), { recursive: true });
527
- await writeFile(markerPath, JSON.stringify(marker, null, 2) + '\n', 'utf-8');
528
- return markerPath;
529
- }
530
- async function installHookAssetsForHost(client, homeDir, sourceScriptPath) {
531
- const normalizedClient = normalizeHookHost(client);
532
- const hooksDir = dirname(getPermissionHookScriptPath(homeDir));
533
- const sharedTargetPath = getPermissionHookScriptPath(homeDir);
534
- const sharedSourcePath = sourceScriptPath ?? join(repoRootFromModule(), 'scripts', 'pretooluse-dollhouse.sh');
535
- const portHelperSourcePath = join(repoRootFromModule(), 'scripts', 'permission-port-discovery.sh');
536
- const portHelperTargetPath = join(hooksDir, 'permission-port-discovery.sh');
537
- const sharedStat = statSync(sharedSourcePath);
538
- if (!sharedStat.isFile()) {
539
- logger.warn(`[PermissionHooks] Shared hook bridge missing for ${normalizedClient}: ${sharedSourcePath}`);
540
- throw new Error(`Permission hook source script not found: ${sharedSourcePath}`);
541
- }
542
- await copyHookAsset(sharedSourcePath, sharedTargetPath);
543
- const portHelperStat = statSync(portHelperSourcePath);
544
- if (!portHelperStat.isFile()) {
545
- logger.warn(`[PermissionHooks] Port discovery helper missing for ${normalizedClient}: ${portHelperSourcePath}`);
546
- throw new Error(`Permission hook helper script not found: ${portHelperSourcePath}`);
547
- }
548
- await copyHookAsset(portHelperSourcePath, portHelperTargetPath);
549
- const wrapperTargetPath = getHookWrapperPath(normalizedClient, homeDir);
550
- if (!wrapperTargetPath) {
551
- return { scriptPath: sharedTargetPath };
552
- }
553
- const wrapperSourcePath = getHookSourcePath(normalizedClient);
554
- const wrapperStat = statSync(wrapperSourcePath);
555
- if (!wrapperStat.isFile()) {
556
- logger.warn(`[PermissionHooks] Wrapper hook script missing for ${normalizedClient}: ${wrapperSourcePath}`);
557
- throw new Error(`Permission hook wrapper script not found: ${wrapperSourcePath}`);
558
- }
559
- await copyHookAsset(wrapperSourcePath, wrapperTargetPath);
560
- return { scriptPath: wrapperTargetPath };
561
- }
562
- async function installClaudeCodePermissionHook(homeDir, installedAt, sourceScriptPath) {
563
- const host = 'claude-code';
564
- const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
565
- const settingsPath = getClaudeHookSettingsPath(homeDir);
566
- const settingsResult = await mergeClaudeSettings(settingsPath, `bash ${scriptPath}`);
567
- const markerPath = await writeHookMarker(homeDir, {
568
- host,
569
- scriptPath,
570
- settingsPath,
571
- configured: true,
572
- assetsPrepared: true,
573
- installedAt,
574
- });
575
- return {
576
- supported: true,
577
- installed: true,
578
- configured: true,
579
- assetsPrepared: true,
580
- host,
581
- scriptPath,
582
- settingsPath,
583
- markerPath,
584
- backupPath: settingsResult.backupPath,
585
- message: 'Installed Claude Code permission hook and updated settings.json.',
586
- };
587
- }
588
- async function installVsCodePermissionHook(homeDir, installedAt, sourceScriptPath) {
589
- const host = 'vscode';
590
- const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
591
- const settingsPath = getVsCodeHookSettingsPath(homeDir);
592
- const userSettingsPath = getVsCodeUserSettingsPath(homeDir);
593
- const hookResult = await mergeVsCodeHookSettings(settingsPath, `bash ${scriptPath}`);
594
- const userSettingsResult = await mergeVsCodeUserSettings(userSettingsPath);
595
- const markerPath = await writeHookMarker(homeDir, {
596
- host,
597
- scriptPath,
598
- settingsPath,
599
- additionalPaths: [userSettingsPath],
600
- configured: true,
601
- assetsPrepared: true,
602
- installedAt,
603
- });
604
- return {
605
- supported: true,
606
- installed: true,
607
- configured: true,
608
- assetsPrepared: true,
609
- host,
610
- scriptPath,
611
- settingsPath,
612
- additionalPaths: [userSettingsPath],
613
- markerPath,
614
- backupPath: hookResult.backupPath ?? userSettingsResult.backupPath,
615
- message: 'Installed VS Code permission hook and enabled chat.hookFilesLocations for ~/.copilot/hooks.',
616
- };
617
- }
618
- async function installGeminiCliPermissionHook(homeDir, installedAt, sourceScriptPath) {
619
- const host = 'gemini-cli';
620
- const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
621
- const settingsPath = getGeminiHookSettingsPath(homeDir);
622
- const settingsResult = await mergeGeminiSettings(settingsPath, `bash ${scriptPath}`);
623
- const markerPath = await writeHookMarker(homeDir, {
624
- host,
625
- scriptPath,
626
- settingsPath,
627
- configured: true,
628
- assetsPrepared: true,
629
- installedAt,
630
- });
631
- return {
632
- supported: true,
633
- installed: true,
634
- configured: true,
635
- assetsPrepared: true,
636
- host,
637
- scriptPath,
638
- settingsPath,
639
- markerPath,
640
- backupPath: settingsResult.backupPath,
641
- message: 'Installed Gemini CLI permission hook and updated settings.json.',
642
- };
643
- }
644
- async function installCursorPermissionHook(homeDir, installedAt, sourceScriptPath) {
645
- const host = 'cursor';
646
- const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
647
- const settingsPath = getCursorHookSettingsPath(homeDir);
648
- const settingsResult = await mergeCursorHooks(settingsPath, `bash ${scriptPath}`);
649
- const markerPath = await writeHookMarker(homeDir, {
650
- host,
651
- scriptPath,
652
- settingsPath,
653
- configured: true,
654
- assetsPrepared: true,
655
- installedAt,
656
- });
657
- return {
658
- supported: true,
659
- installed: true,
660
- configured: true,
661
- assetsPrepared: true,
662
- host,
663
- scriptPath,
664
- settingsPath,
665
- markerPath,
666
- backupPath: settingsResult.backupPath,
667
- message: 'Installed Cursor permission hook and updated hooks.json.',
668
- };
669
- }
670
- async function installWindsurfPermissionHook(homeDir, installedAt, sourceScriptPath) {
671
- const host = 'windsurf';
672
- const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
673
- const settingsPath = getWindsurfHookSettingsPath(homeDir);
674
- const settingsResult = await mergeWindsurfHooks(settingsPath, `bash ${scriptPath}`);
675
- const markerPath = await writeHookMarker(homeDir, {
676
- host,
677
- scriptPath,
678
- settingsPath,
679
- configured: true,
680
- assetsPrepared: true,
681
- installedAt,
682
- });
683
- return {
684
- supported: true,
685
- installed: true,
686
- configured: true,
687
- assetsPrepared: true,
688
- host,
689
- scriptPath,
690
- settingsPath,
691
- markerPath,
692
- backupPath: settingsResult.backupPath,
693
- message: 'Installed Windsurf permission hooks and updated hooks.json.',
694
- };
695
- }
696
- async function installCodexPermissionHook(homeDir, installedAt, sourceScriptPath) {
697
- const host = 'codex';
698
- const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
699
- const settingsPath = getCodexHookSettingsPath(homeDir);
700
- const configPath = getCodexConfigPath(homeDir);
701
- const hooksResult = await mergeCodexHooks(settingsPath, `bash ${scriptPath}`);
702
- const configResult = await mergeCodexConfig(configPath);
703
- const markerPath = await writeHookMarker(homeDir, {
704
- host,
705
- scriptPath,
706
- settingsPath,
707
- additionalPaths: [configPath],
708
- configured: true,
709
- assetsPrepared: true,
710
- installedAt,
711
- });
712
- return {
713
- supported: true,
714
- installed: true,
715
- configured: true,
716
- assetsPrepared: true,
717
- host,
718
- scriptPath,
719
- settingsPath,
720
- additionalPaths: [configPath],
721
- markerPath,
722
- backupPath: hooksResult.backupPath ?? configResult.backupPath,
723
- message: 'Installed Codex Bash permission hook, created hooks.json, and enabled features.codex_hooks in config.toml.',
724
- };
725
- }
726
- async function installManualPermissionHookAssets(normalizedClient, homeDir, installedAt, sourceScriptPath) {
727
- const { scriptPath } = await installHookAssetsForHost(normalizedClient, homeDir, sourceScriptPath);
728
- const markerPath = await writeHookMarker(homeDir, {
729
- host: normalizedClient,
730
- scriptPath,
731
- settingsPath: undefined,
732
- configured: false,
733
- assetsPrepared: true,
734
- installedAt,
735
- });
736
- return {
737
- supported: true,
738
- installed: true,
739
- configured: false,
740
- assetsPrepared: true,
741
- host: normalizedClient,
742
- scriptPath,
743
- markerPath,
744
- message: `Installed Dollhouse permission hook assets for ${normalizedClient}. Finish the client-specific hook registration manually.`,
745
- };
746
- }
747
- export async function installPermissionHook(client, options = {}) {
748
- const normalizedClient = normalizeHookHost(client);
749
- const homeDir = options.homeDir ?? homedir();
750
- const installedAt = (options.now ?? new Date()).toISOString();
751
- if (normalizedClient === 'claude-code') {
752
- return installClaudeCodePermissionHook(homeDir, installedAt, options.sourceScriptPath);
753
- }
754
- if (normalizedClient === 'vscode') {
755
- return installVsCodePermissionHook(homeDir, installedAt, options.sourceScriptPath);
756
- }
757
- if (normalizedClient === 'gemini-cli') {
758
- return installGeminiCliPermissionHook(homeDir, installedAt, options.sourceScriptPath);
759
- }
760
- if (normalizedClient === 'cursor') {
761
- return installCursorPermissionHook(homeDir, installedAt, options.sourceScriptPath);
762
- }
763
- if (normalizedClient === 'windsurf') {
764
- return installWindsurfPermissionHook(homeDir, installedAt, options.sourceScriptPath);
765
- }
766
- if (normalizedClient === 'codex') {
767
- return installCodexPermissionHook(homeDir, installedAt, options.sourceScriptPath);
768
- }
769
- if (getHookWrapperBasename(normalizedClient)) {
770
- return installManualPermissionHookAssets(normalizedClient, homeDir, installedAt, options.sourceScriptPath);
771
- }
772
- return {
773
- supported: false,
774
- installed: false,
775
- configured: false,
776
- host: normalizedClient,
777
- message: `Automatic permission hook wiring is not yet supported for ${normalizedClient}.`,
778
- };
779
- }
780
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvbkhvb2tzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3Blcm1pc3Npb25Ib29rcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRyxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMxQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzVDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxhQUFhLENBQUM7QUEwQ3JDLFNBQVMsa0JBQWtCO0lBQ3pCLE1BQU0sV0FBVyxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25ELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRCxTQUFTLGtCQUFrQixDQUFDLEtBQWM7SUFDeEMsT0FBTyxPQUFPLENBQ1osS0FBSztXQUNGLE9BQU8sS0FBSyxLQUFLLFFBQVE7V0FDekIsTUFBTSxJQUFJLEtBQUs7V0FDZCxLQUEyQixDQUFDLElBQUksS0FBSyxRQUFRLENBQ2xELENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsR0FBVztJQUMvQixLQUFLLE1BQU0sSUFBSSxJQUFJLEdBQUcs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Z0IsS0FBSyxZQUFZLEVBQUUsQ0FBQztRQUN0QyxPQUFPLDhCQUE4QixDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDeEYsQ0FBQztJQUVELElBQUksZ0JBQWdCLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDbEMsT0FBTywyQkFBMkIsQ0FBQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFFRCxJQUFJLGdCQUFnQixLQUFLLFVBQVUsRUFBRSxDQUFDO1FBQ3BDLE9BQU8sNkJBQTZCLENBQUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBRUQsSUFBSSxnQkFBZ0IsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUNqQyxPQUFPLDBCQUEwQixDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDcEYsQ0FBQztJQUVELElBQUksc0JBQXNCLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO1FBQzdDLE9BQU8saUNBQWlDLENBQUMsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUM3RyxDQUFDO0lBRUQsT0FBTztRQUNMLFNBQVMsRUFBRSxLQUFLO1FBQ2hCLFNBQVMsRUFBRSxLQUFLO1FBQ2hCLFVBQVUsRUFBRSxLQUFLO1FBQ2pCLElBQUksRUFBRSxnQkFBZ0I7UUFDdEIsT0FBTyxFQUFFLDZEQUE2RCxnQkFBZ0IsR0FBRztLQUMxRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4aXN0c1N5bmMsIHJlYWRGaWxlU3luYywgcmVhZGRpclN5bmMsIHN0YXRTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBhY2Nlc3MsIGNobW9kLCBjb3B5RmlsZSwgbWtkaXIsIHJlYWRGaWxlLCByZWFkZGlyLCB3cml0ZUZpbGUgfSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4gfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ25vZGU6dXJsJztcbmltcG9ydCB7IGhvbWVkaXIsIHBsYXRmb3JtIH0gZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQgeyBVbmljb2RlVmFsaWRhdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvdmFsaWRhdG9ycy91bmljb2RlVmFsaWRhdG9yLmpzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBQZXJtaXNzaW9uSG9va01hcmtlciB7XG4gIGhvc3Q6IHN0cmluZztcbiAgc2NyaXB0UGF0aDogc3RyaW5nO1xuICBzZXR0aW5nc1BhdGg/OiBzdHJpbmc7XG4gIGFkZGl0aW9uYWxQYXRocz86IHN0cmluZ1tdO1xuICBjb25maWd1cmVkPzogYm9vbGVhbjtcbiAgYXNzZXRzUHJlcGFyZWQ/OiBib29sZWFuO1xuICBpbnN0YWxsZWRBdDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBlcm1pc3Npb25Ib29rU3RhdHVzIHtcbiAgaW5zdGFsbGVkOiBib29sZWFuO1xuICBjb25maWd1cmVkPzogYm9vbGVhbjtcbiAgYXNzZXRzUHJlcGFyZWQ/OiBib29sZWFuO1xuICBob3N0Pzogc3RyaW5nO1xuICBzY3JpcHRQYXRoPzogc3RyaW5nO1xuICBzZXR0aW5nc1BhdGg/OiBzdHJpbmc7XG4gIGFkZGl0aW9uYWxQYXRocz86IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdCB7XG4gIHN1cHBvcnRlZDogYm9vbGVhbjtcbiAgaW5zdGFsbGVkOiBib29sZWFuO1xuICBjb25maWd1cmVkOiBib29sZWFuO1xuICBhc3NldHNQcmVwYXJlZD86IGJvb2xlYW47XG4gIGhvc3Q6IHN0cmluZztcbiAgc2NyaXB0UGF0aD86IHN0cmluZztcbiAgc2V0dGluZ3NQYXRoPzogc3RyaW5nO1xuICBhZGRpdGlvbmFsUGF0aHM/OiBzdHJpbmdbXTtcbiAgbWFya2VyUGF0aD86IHN0cmluZztcbiAgYmFja3VwUGF0aD86IHN0cmluZztcbiAgbWVzc2FnZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluc3RhbGxQZXJtaXNzaW9uSG9va09wdGlvbnMge1xuICBob21lRGlyPzogc3RyaW5nO1xuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nO1xuICBub3c/OiBEYXRlO1xufVxuXG5mdW5jdGlvbiByZXBvUm9vdEZyb21Nb2R1bGUoKTogc3RyaW5nIHtcbiAgY29uc3QgY3VycmVudEZpbGUgPSBmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCk7XG4gIHJldHVybiBkaXJuYW1lKGRpcm5hbWUoZGlybmFtZShjdXJyZW50RmlsZSkpKTtcbn1cblxuZnVuY3Rpb24gaXNNaXNzaW5nRmlsZUVycm9yKGVycm9yOiB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiBCb29sZWFuKFxuICAgIGVycm9yXG4gICAgJiYgdHlwZW9mIGVycm9yID09PSAnb2JqZWN0J1xuICAgICYmICdjb2RlJyBpbiBlcnJvclxuICAgICYmIChlcnJvciBhcyB7IGNvZGU/OiBzdHJpbmcgfSkuY29kZSA9PT0gJ0VOT0VOVCcsXG4gICk7XG59XG5cbmZ1bmN0aW9uIGRldGVjdEluZGVudChyYXc6IHN0cmluZyk6IG51bWJlciB8IHN0cmluZyB7XG4gIGZvciAoY29uc3QgbGluZSBvZiByYXcuc3BsaXQoJ1xcbicpKSB7XG4gICAgaWYgKGxpbmUubGVuZ3RoID09PSAwIHx8IGxpbmUuc3RhcnRzV2l0aCgneycpIHx8IGxpbmUuc3RhcnRzV2l0aCgnfScpKSBjb250aW51ZTtcbiAgICBpZiAobGluZS5zdGFydHNXaXRoKCdcXHQnKSkgcmV0dXJuICdcXHQnO1xuICAgIGlmIChsaW5lLnN0YXJ0c1dpdGgoJyAnKSkge1xuICAgICAgY29uc3Qgc3BhY2VzID0gbGluZS5sZW5ndGggLSBsaW5lLnRyaW1TdGFydCgpLmxlbmd0aDtcbiAgICAgIGlmIChzcGFjZXMgPj0gMikgcmV0dXJuIHNwYWNlcztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIDI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQZXJtaXNzaW9uSG9va1NjcmlwdFBhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuZG9sbGhvdXNlJywgJ2hvb2tzJywgJ3ByZXRvb2x1c2UtZG9sbGhvdXNlLnNoJyk7XG59XG5cbmZ1bmN0aW9uIGdldFBlcm1pc3Npb25Ib29rUnVuRGlyKGhvbWVEaXIgPSBob21lZGlyKCkpOiBzdHJpbmcge1xuICByZXR1cm4gam9pbihob21lRGlyLCAnLmRvbGxob3VzZScsICdydW4nKTtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplSG9va0hvc3QoaG9zdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIFVuaWNvZGVWYWxpZGF0b3Iubm9ybWFsaXplKGhvc3QpLm5vcm1hbGl6ZWRDb250ZW50LnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBpc0hvb2tNYXJrZXJGaWxlbmFtZShlbnRyeTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBlbnRyeS5zdGFydHNXaXRoKCdob29rLWluc3RhbGxlZC0nKSAmJiBlbnRyeS5lbmRzV2l0aCgnLmpzb24nKTtcbn1cblxuZnVuY3Rpb24gcmVhZEhvc3RTcGVjaWZpY0hvb2tTdGF0dXMoaG9tZURpcjogc3RyaW5nLCBob3N0OiBzdHJpbmcpOiBQZXJtaXNzaW9uSG9va1N0YXR1cyB7XG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVIb29rSG9zdChob3N0KTtcbiAgY29uc3Qgc3RhdHVzID0gcmVhZE1hcmtlclN0YXR1cyhnZXRQZXJtaXNzaW9uSG9va01hcmtlclBhdGgoaG9tZURpciwgbm9ybWFsaXplZCkpO1xuICBpZiAoc3RhdHVzLmluc3RhbGxlZCB8fCBzdGF0dXMuYXNzZXRzUHJlcGFyZWQpIHtcbiAgICByZXR1cm4gc3RhdHVzO1xuICB9XG4gIGlmIChub3JtYWxpemVkID09PSAnY2xhdWRlLWNvZGUnKSB7XG4gICAgcmV0dXJuIHJlYWRNYXJrZXJTdGF0dXMoZ2V0UGVybWlzc2lvbkhvb2tNYXJrZXJQYXRoKGhvbWVEaXIpKTtcbiAgfVxuICByZXR1cm4geyBpbnN0YWxsZWQ6IGZhbHNlIH07XG59XG5cbmZ1bmN0aW9uIGNvbGxlY3RIb29rTWFya2VyUGF0aHMoaG9tZURpcjogc3RyaW5nKTogU2V0PHN0cmluZz4ge1xuICBjb25zdCBtYXJrZXJQYXRocyA9IG5ldyBTZXQ8c3RyaW5nPihbZ2V0UGVybWlzc2lvbkhvb2tNYXJrZXJQYXRoKGhvbWVEaXIpXSk7XG4gIGNvbnN0IHJ1bkRpciA9IGdldFBlcm1pc3Npb25Ib29rUnVuRGlyKGhvbWVEaXIpO1xuICB0cnkge1xuICAgIGZvciAoY29uc3QgZW50cnkgb2YgcmVhZGRpclN5bmMocnVuRGlyKSkge1xuICAgICAgaWYgKGlzSG9va01hcmtlckZpbGVuYW1lKGVudHJ5KSkge1xuICAgICAgICBtYXJrZXJQYXRocy5hZGQoam9pbihydW5EaXIsIGVudHJ5KSk7XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBObyBydW4gZGlyIHlldCDigJQgZmFsbCB0aHJvdWdoIHRvIGRlZmF1bHQgZmFsc2UuXG4gIH1cbiAgcmV0dXJuIG1hcmtlclBhdGhzO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjb2xsZWN0SG9va01hcmtlclBhdGhzQXN5bmMoaG9tZURpcjogc3RyaW5nKTogUHJvbWlzZTxTZXQ8c3RyaW5nPj4ge1xuICBjb25zdCBtYXJrZXJQYXRocyA9IG5ldyBTZXQ8c3RyaW5nPihbZ2V0UGVybWlzc2lvbkhvb2tNYXJrZXJQYXRoKGhvbWVEaXIpXSk7XG4gIGNvbnN0IHJ1bkRpciA9IGdldFBlcm1pc3Npb25Ib29rUnVuRGlyKGhvbWVEaXIpO1xuICB0cnkge1xuICAgIGZvciAoY29uc3QgZW50cnkgb2YgYXdhaXQgcmVhZGRpcihydW5EaXIpKSB7XG4gICAgICBpZiAoaXNIb29rTWFya2VyRmlsZW5hbWUoZW50cnkpKSB7XG4gICAgICAgIG1hcmtlclBhdGhzLmFkZChqb2luKHJ1bkRpciwgZW50cnkpKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIE5vIHJ1biBkaXIgeWV0IOKAlCBmYWxsIHRocm91Z2ggdG8gZGVmYXVsdCBmYWxzZS5cbiAgfVxuICByZXR1cm4gbWFya2VyUGF0aHM7XG59XG5cbmZ1bmN0aW9uIHN1bW1hcml6ZU1hcmtlclN0YXR1c2VzKG1hcmtlclBhdGhzOiBJdGVyYWJsZTxzdHJpbmc+KTogUGVybWlzc2lvbkhvb2tTdGF0dXMge1xuICBsZXQgZmFsbGJhY2s6IFBlcm1pc3Npb25Ib29rU3RhdHVzID0geyBpbnN0YWxsZWQ6IGZhbHNlIH07XG4gIGZvciAoY29uc3QgbWFya2VyUGF0aCBvZiBtYXJrZXJQYXRocykge1xuICAgIGNvbnN0IHN0YXR1cyA9IHJlYWRNYXJrZXJTdGF0dXMobWFya2VyUGF0aCk7XG4gICAgaWYgKHN0YXR1cy5pbnN0YWxsZWQpIHJldHVybiBzdGF0dXM7XG4gICAgaWYgKCFmYWxsYmFjay5hc3NldHNQcmVwYXJlZCAmJiBzdGF0dXMuYXNzZXRzUHJlcGFyZWQpIGZhbGxiYWNrID0gc3RhdHVzO1xuICB9XG4gIHJldHVybiBmYWxsYmFjaztcbn1cblxuZnVuY3Rpb24gZ2V0SG9va1dyYXBwZXJCYXNlbmFtZShob3N0OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgc3dpdGNoIChub3JtYWxpemVIb29rSG9zdChob3N0KSkge1xuICAgIGNhc2UgJ3ZzY29kZSc6XG4gICAgICByZXR1cm4gJ3ByZXRvb2x1c2UtdnNjb2RlLnNoJztcbiAgICBjYXNlICdjdXJzb3InOlxuICAgICAgcmV0dXJuICdwcmV0b29sdXNlLWN1cnNvci5zaCc7XG4gICAgY2FzZSAnd2luZHN1cmYnOlxuICAgICAgcmV0dXJuICdwcmV0b29sdXNlLXdpbmRzdXJmLnNoJztcbiAgICBjYXNlICdnZW1pbmktY2xpJzpcbiAgICAgIHJldHVybiAncHJldG9vbHVzZS1nZW1pbmkuc2gnO1xuICAgIGNhc2UgJ2NvZGV4JzpcbiAgICAgIHJldHVybiAncHJldG9vbHVzZS1jb2RleC5zaCc7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldEhvb2tXcmFwcGVyUGF0aChob3N0OiBzdHJpbmcsIGhvbWVEaXIgPSBob21lZGlyKCkpOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgYmFzZW5hbWUgPSBnZXRIb29rV3JhcHBlckJhc2VuYW1lKGhvc3QpO1xuICByZXR1cm4gYmFzZW5hbWUgPyBqb2luKGhvbWVEaXIsICcuZG9sbGhvdXNlJywgJ2hvb2tzJywgYmFzZW5hbWUpIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gZ2V0SG9va1NvdXJjZVBhdGgoaG9zdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgcm9vdCA9IHJlcG9Sb290RnJvbU1vZHVsZSgpO1xuICBjb25zdCBiYXNlbmFtZSA9IGdldEhvb2tXcmFwcGVyQmFzZW5hbWUoaG9zdCk7XG4gIHJldHVybiBiYXNlbmFtZSA/IGpvaW4ocm9vdCwgJ3NjcmlwdHMnLCBiYXNlbmFtZSkgOiBqb2luKHJvb3QsICdzY3JpcHRzJywgJ3ByZXRvb2x1c2UtZG9sbGhvdXNlLnNoJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQZXJtaXNzaW9uSG9va01hcmtlclBhdGgoaG9tZURpciA9IGhvbWVkaXIoKSwgaG9zdD86IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghaG9zdCkge1xuICAgIHJldHVybiBqb2luKGdldFBlcm1pc3Npb25Ib29rUnVuRGlyKGhvbWVEaXIpLCAnaG9vay1pbnN0YWxsZWQuanNvbicpO1xuICB9XG4gIHJldHVybiBqb2luKGdldFBlcm1pc3Npb25Ib29rUnVuRGlyKGhvbWVEaXIpLCBgaG9vay1pbnN0YWxsZWQtJHtub3JtYWxpemVIb29rSG9zdChob3N0KX0uanNvbmApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q2xhdWRlSG9va1NldHRpbmdzUGF0aChob21lRGlyID0gaG9tZWRpcigpKTogc3RyaW5nIHtcbiAgcmV0dXJuIGpvaW4oaG9tZURpciwgJy5jbGF1ZGUnLCAnc2V0dGluZ3MuanNvbicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VnNDb2RlSG9va1NldHRpbmdzUGF0aChob21lRGlyID0gaG9tZWRpcigpKTogc3RyaW5nIHtcbiAgcmV0dXJuIGpvaW4oaG9tZURpciwgJy5jb3BpbG90JywgJ2hvb2tzJywgJ2RvbGxob3VzZS1wZXJtaXNzaW9ucy5qc29uJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRWc0NvZGVVc2VyU2V0dGluZ3NQYXRoKGhvbWVEaXIgPSBob21lZGlyKCkpOiBzdHJpbmcge1xuICBjb25zdCBjdXJyZW50UGxhdGZvcm0gPSBwbGF0Zm9ybSgpO1xuICBpZiAoY3VycmVudFBsYXRmb3JtID09PSAnZGFyd2luJykge1xuICAgIHJldHVybiBqb2luKGhvbWVEaXIsICdMaWJyYXJ5JywgJ0FwcGxpY2F0aW9uIFN1cHBvcnQnLCAnQ29kZScsICdVc2VyJywgJ3NldHRpbmdzLmpzb24nKTtcbiAgfVxuICBpZiAoY3VycmVudFBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgY29uc3QgYXBwRGF0YSA9IHByb2Nlc3MuZW52LkFQUERBVEEgfHwgam9pbihob21lRGlyLCAnQXBwRGF0YScsICdSb2FtaW5nJyk7XG4gICAgcmV0dXJuIGpvaW4oYXBwRGF0YSwgJ0NvZGUnLCAnVXNlcicsICdzZXR0aW5ncy5qc29uJyk7XG4gIH1cbiAgcmV0dXJuIGpvaW4oaG9tZURpciwgJy5jb25maWcnLCAnQ29kZScsICdVc2VyJywgJ3NldHRpbmdzLmpzb24nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEdlbWluaUhvb2tTZXR0aW5nc1BhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuZ2VtaW5pJywgJ3NldHRpbmdzLmpzb24nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEN1cnNvckhvb2tTZXR0aW5nc1BhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuY3Vyc29yJywgJ2hvb2tzLmpzb24nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFdpbmRzdXJmSG9va1NldHRpbmdzUGF0aChob21lRGlyID0gaG9tZWRpcigpKTogc3RyaW5nIHtcbiAgcmV0dXJuIGpvaW4oaG9tZURpciwgJy5jb2RlaXVtJywgJ3dpbmRzdXJmJywgJ2hvb2tzLmpzb24nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvZGV4SG9va1NldHRpbmdzUGF0aChob21lRGlyID0gaG9tZWRpcigpKTogc3RyaW5nIHtcbiAgcmV0dXJuIGpvaW4oaG9tZURpciwgJy5jb2RleCcsICdob29rcy5qc29uJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb2RleENvbmZpZ1BhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuY29kZXgnLCAnY29uZmlnLnRvbWwnKTtcbn1cblxuZnVuY3Rpb24gdG9QZXJtaXNzaW9uSG9va1N0YXR1cyhyYXc6IFBlcm1pc3Npb25Ib29rTWFya2VyKTogUGVybWlzc2lvbkhvb2tTdGF0dXMge1xuICBpZiAoXG4gICAgdHlwZW9mIHJhdy5ob3N0ICE9PSAnc3RyaW5nJyB8fFxuICAgIHR5cGVvZiByYXcuc2NyaXB0UGF0aCAhPT0gJ3N0cmluZydcbiAgKSB7XG4gICAgcmV0dXJuIHsgaW5zdGFsbGVkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3Qgc2NyaXB0UmVhZHkgPSBleGlzdHNTeW5jKHJhdy5zY3JpcHRQYXRoKTtcbiAgY29uc3Qgc2V0dGluZ3NSZWFkeSA9ICFyYXcuc2V0dGluZ3NQYXRoIHx8IGV4aXN0c1N5bmMocmF3LnNldHRpbmdzUGF0aCk7XG4gIGNvbnN0IGFkZGl0aW9uYWxQYXRoc1JlYWR5ID0gIXJhdy5hZGRpdGlvbmFsUGF0aHMgfHwgcmF3LmFkZGl0aW9uYWxQYXRocy5ldmVyeSgocGF0aCkgPT4gZXhpc3RzU3luYyhwYXRoKSk7XG4gIGNvbnN0IGFzc2V0c1ByZXBhcmVkID0gKHJhdy5hc3NldHNQcmVwYXJlZCA/PyByYXcuY29uZmlndXJlZCA/PyB0cnVlKSAmJiBzY3JpcHRSZWFkeTtcbiAgY29uc3QgY29uZmlndXJlZCA9IChyYXcuY29uZmlndXJlZCA/PyB0cnVlKSAmJiBzY3JpcHRSZWFkeSAmJiBzZXR0aW5nc1JlYWR5ICYmIGFkZGl0aW9uYWxQYXRoc1JlYWR5O1xuXG4gIHJldHVybiB7XG4gICAgaW5zdGFsbGVkOiBjb25maWd1cmVkLFxuICAgIGNvbmZpZ3VyZWQsXG4gICAgYXNzZXRzUHJlcGFyZWQsXG4gICAgaG9zdDogcmF3Lmhvc3QsXG4gICAgc2NyaXB0UGF0aDogcmF3LnNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoOiByYXcuc2V0dGluZ3NQYXRoLFxuICAgIGFkZGl0aW9uYWxQYXRoczogcmF3LmFkZGl0aW9uYWxQYXRocyxcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVhZE1hcmtlclN0YXR1cyhtYXJrZXJQYXRoOiBzdHJpbmcpOiBQZXJtaXNzaW9uSG9va1N0YXR1cyB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmF3ID0gcmVhZEZpbGVTeW5jKG1hcmtlclBhdGgsICd1dGYtOCcpO1xuICAgIHJldHVybiB0b1Blcm1pc3Npb25Ib29rU3RhdHVzKEpTT04ucGFyc2UocmF3KSBhcyBQZXJtaXNzaW9uSG9va01hcmtlcik7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKCFpc01pc3NpbmdGaWxlRXJyb3IoZXJyb3IpKSB7XG4gICAgICBsb2dnZXIud2FybihgW1Blcm1pc3Npb25zXSBGYWlsZWQgdG8gcmVhZCBob29rIG1hcmtlciBhdCAke21hcmtlclBhdGh9OiAke1N0cmluZyhlcnJvcil9YCk7XG4gICAgfVxuICAgIHJldHVybiB7IGluc3RhbGxlZDogZmFsc2UgfTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UGVybWlzc2lvbkhvb2tTdGF0dXMoaG9tZURpciA9IGhvbWVkaXIoKSwgaG9zdD86IHN0cmluZyk6IFBlcm1pc3Npb25Ib29rU3RhdHVzIHtcbiAgaWYgKGhvc3QpIHtcbiAgICByZXR1cm4gcmVhZEhvc3RTcGVjaWZpY0hvb2tTdGF0dXMoaG9tZURpciwgaG9zdCk7XG4gIH1cblxuICByZXR1cm4gc3VtbWFyaXplTWFya2VyU3RhdHVzZXMoY29sbGVjdEhvb2tNYXJrZXJQYXRocyhob21lRGlyKSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRQZXJtaXNzaW9uSG9va1N0YXR1c0FzeW5jKGhvbWVEaXIgPSBob21lZGlyKCksIGhvc3Q/OiBzdHJpbmcpOiBQcm9taXNlPFBlcm1pc3Npb25Ib29rU3RhdHVzPiB7XG4gIGlmIChob3N0KSB7XG4gICAgcmV0dXJuIHJlYWRIb3N0U3BlY2lmaWNIb29rU3RhdHVzKGhvbWVEaXIsIGhvc3QpO1xuICB9XG5cbiAgcmV0dXJuIHN1bW1hcml6ZU1hcmtlclN0YXR1c2VzKGF3YWl0IGNvbGxlY3RIb29rTWFya2VyUGF0aHNBc3luYyhob21lRGlyKSk7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZUhvb2tzUm9vdChwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogUmVjb3JkPHN0cmluZywgdW5rbm93bltdPiB7XG4gIGNvbnN0IGhvb2tzVmFsdWUgPSBwYXJzZWQuaG9va3M7XG4gIGlmICghaG9va3NWYWx1ZSB8fCB0eXBlb2YgaG9va3NWYWx1ZSAhPT0gJ29iamVjdCcgfHwgQXJyYXkuaXNBcnJheShob29rc1ZhbHVlKSkge1xuICAgIHBhcnNlZC5ob29rcyA9IHt9O1xuICB9XG4gIHJldHVybiBwYXJzZWQuaG9va3MgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bltdPjtcbn1cblxuZnVuY3Rpb24gZW5zdXJlQ29tbWFuZEhvb2soXG4gIHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGV2ZW50TmFtZTogc3RyaW5nLFxuICBjb21tYW5kOiBzdHJpbmcsXG4gIG1hdGNoZXI6IHN0cmluZyxcbiAgZXh0cmFIb29rRmllbGRzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9LFxuKTogeyBjaGFuZ2VkOiBib29sZWFuOyBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0ge1xuICBjb25zdCBob29rc1Jvb3QgPSBub3JtYWxpemVIb29rc1Jvb3QocGFyc2VkKTtcbiAgY29uc3QgZXhpc3RpbmdFbnRyaWVzOiBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gPSBBcnJheS5pc0FycmF5KGhvb2tzUm9vdFtldmVudE5hbWVdKVxuICAgID8gaG9va3NSb290W2V2ZW50TmFtZV0uZmlsdGVyKChlbnRyeSk6IGVudHJ5IGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+IHR5cGVvZiBlbnRyeSA9PT0gJ29iamVjdCcgJiYgZW50cnkgIT09IG51bGwpXG4gICAgOiBbXTtcbiAgaG9va3NSb290W2V2ZW50TmFtZV0gPSBleGlzdGluZ0VudHJpZXM7XG5cbiAgY29uc3QgY29tbWFuZEV4aXN0cyA9IGV4aXN0aW5nRW50cmllcy5zb21lKChlbnRyeSkgPT4ge1xuICAgIGNvbnN0IGhvb2tzID0gQXJyYXkuaXNBcnJheShlbnRyeT8uaG9va3MpID8gZW50cnkuaG9va3MgYXMgQXJyYXk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+IDogW107XG4gICAgcmV0dXJuIGhvb2tzLnNvbWUoKGhvb2spID0+IGhvb2s/LnR5cGUgPT09ICdjb21tYW5kJyAmJiBob29rPy5jb21tYW5kID09PSBjb21tYW5kKTtcbiAgfSk7XG4gIGlmIChjb21tYW5kRXhpc3RzKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UsIHBhcnNlZCB9O1xuICB9XG5cbiAgY29uc3Qgd2lsZGNhcmRFbnRyeSA9IGV4aXN0aW5nRW50cmllcy5maW5kKChlbnRyeSk6IGVudHJ5IGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+XG4gICAgKGVudHJ5Py5tYXRjaGVyID09PSBtYXRjaGVyIHx8IGVudHJ5Py5tYXRjaGVyID09PSB1bmRlZmluZWQpICYmIEFycmF5LmlzQXJyYXkoZW50cnk/Lmhvb2tzKSxcbiAgKTtcblxuICBpZiAod2lsZGNhcmRFbnRyeSkge1xuICAgIGNvbnN0IGhvb2tzID0gd2lsZGNhcmRFbnRyeS5ob29rcyBhcyBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG4gICAgaG9va3MucHVzaCh7XG4gICAgICB0eXBlOiAnY29tbWFuZCcsXG4gICAgICBjb21tYW5kLFxuICAgICAgLi4uZXh0cmFIb29rRmllbGRzLFxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGV4aXN0aW5nRW50cmllcy5wdXNoKHtcbiAgICAgIG1hdGNoZXIsXG4gICAgICBob29rczogW1xuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogJ2NvbW1hbmQnLFxuICAgICAgICAgIGNvbW1hbmQsXG4gICAgICAgICAgLi4uZXh0cmFIb29rRmllbGRzLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIHBhcnNlZCB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlQ2xhdWRlUHJlVG9vbFVzZUhvb2soXG4gIHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGNvbW1hbmQ6IHN0cmluZyxcbik6IHsgY2hhbmdlZDogYm9vbGVhbjsgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgcmV0dXJuIGVuc3VyZUNvbW1hbmRIb29rKHBhcnNlZCwgJ1ByZVRvb2xVc2UnLCBjb21tYW5kLCAnKicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlVnNDb2RlUHJlVG9vbFVzZUhvb2soXG4gIHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGNvbW1hbmQ6IHN0cmluZyxcbik6IHsgY2hhbmdlZDogYm9vbGVhbjsgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgcmV0dXJuIGVuc3VyZUNvbW1hbmRIb29rKHBhcnNlZCwgJ1ByZVRvb2xVc2UnLCBjb21tYW5kLCAnKicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlR2VtaW5pQmVmb3JlVG9vbEhvb2soXG4gIHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGNvbW1hbmQ6IHN0cmluZyxcbik6IHsgY2hhbmdlZDogYm9vbGVhbjsgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgcmV0dXJuIGVuc3VyZUNvbW1hbmRIb29rKHBhcnNlZCwgJ0JlZm9yZVRvb2wnLCBjb21tYW5kLCAnLionKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZUNvZGV4UHJlVG9vbFVzZUhvb2soXG4gIHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGNvbW1hbmQ6IHN0cmluZyxcbik6IHsgY2hhbmdlZDogYm9vbGVhbjsgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgcmV0dXJuIGVuc3VyZUNvbW1hbmRIb29rKHBhcnNlZCwgJ1ByZVRvb2xVc2UnLCBjb21tYW5kLCAnQmFzaCcsIHtcbiAgICBzdGF0dXNNZXNzYWdlOiAnQ2hlY2tpbmcgQmFzaCBwZXJtaXNzaW9ucycsXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlQ3Vyc29yUHJlVG9vbFVzZUhvb2soXG4gIHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGNvbW1hbmQ6IHN0cmluZyxcbik6IHsgY2hhbmdlZDogYm9vbGVhbjsgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgaWYgKHBhcnNlZC52ZXJzaW9uICE9PSAxKSB7XG4gICAgcGFyc2VkLnZlcnNpb24gPSAxO1xuICB9XG4gIGNvbnN0IGhvb2tzUm9vdCA9IG5vcm1hbGl6ZUhvb2tzUm9vdChwYXJzZWQpO1xuICBjb25zdCBleGlzdGluZ0VudHJpZXM6IEFycmF5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PiA9IEFycmF5LmlzQXJyYXkoaG9va3NSb290LnByZVRvb2xVc2UpXG4gICAgPyBob29rc1Jvb3QucHJlVG9vbFVzZS5maWx0ZXIoKGVudHJ5KTogZW50cnkgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPT4gdHlwZW9mIGVudHJ5ID09PSAnb2JqZWN0JyAmJiBlbnRyeSAhPT0gbnVsbClcbiAgICA6IFtdO1xuICBob29rc1Jvb3QucHJlVG9vbFVzZSA9IGV4aXN0aW5nRW50cmllcztcblxuICBjb25zdCBjb21tYW5kRXhpc3RzID0gZXhpc3RpbmdFbnRyaWVzLnNvbWUoKGVudHJ5KSA9PlxuICAgIGVudHJ5LmNvbW1hbmQgPT09IGNvbW1hbmRcbiAgICAmJiAoZW50cnkudHlwZSA9PT0gJ2NvbW1hbmQnIHx8IGVudHJ5LnR5cGUgPT09IHVuZGVmaW5lZCksXG4gICk7XG4gIGlmIChjb21tYW5kRXhpc3RzKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UsIHBhcnNlZCB9O1xuICB9XG5cbiAgZXhpc3RpbmdFbnRyaWVzLnB1c2goe1xuICAgIHR5cGU6ICdjb21tYW5kJyxcbiAgICBjb21tYW5kLFxuICAgIG1hdGNoZXI6ICcuKicsXG4gIH0pO1xuXG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIHBhcnNlZCB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlV2luZHN1cmZIb29rcyhcbiAgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgY29tbWFuZDogc3RyaW5nLFxuKTogeyBjaGFuZ2VkOiBib29sZWFuOyBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0ge1xuICBjb25zdCBob29rc1Jvb3QgPSBub3JtYWxpemVIb29rc1Jvb3QocGFyc2VkKTtcbiAgbGV0IGNoYW5nZWQgPSBmYWxzZTtcblxuICBjb25zdCBlbnN1cmVFdmVudEhvb2sgPSAoZXZlbnROYW1lOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCBleGlzdGluZ0VudHJpZXM6IEFycmF5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PiA9IEFycmF5LmlzQXJyYXkoaG9va3NSb290W2V2ZW50TmFtZV0pXG4gICAgICA/IGhvb2tzUm9vdFtldmVudE5hbWVdLmZpbHRlcigoZW50cnkpOiBlbnRyeSBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiB0eXBlb2YgZW50cnkgPT09ICdvYmplY3QnICYmIGVudHJ5ICE9PSBudWxsKVxuICAgICAgOiBbXTtcbiAgICBob29rc1Jvb3RbZXZlbnROYW1lXSA9IGV4aXN0aW5nRW50cmllcztcblxuICAgIGNvbnN0IGNvbW1hbmRFeGlzdHMgPSBleGlzdGluZ0VudHJpZXMuc29tZSgoZW50cnkpID0+XG4gICAgICBlbnRyeS5jb21tYW5kID09PSBjb21tYW5kICYmIChlbnRyeS50eXBlID09PSAnY29tbWFuZCcgfHwgZW50cnkudHlwZSA9PT0gdW5kZWZpbmVkKSxcbiAgICApO1xuICAgIGlmIChjb21tYW5kRXhpc3RzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZXhpc3RpbmdFbnRyaWVzLnB1c2goe1xuICAgICAgdHlwZTogJ2NvbW1hbmQnLFxuICAgICAgY29tbWFuZCxcbiAgICB9KTtcbiAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgfTtcblxuICBlbnN1cmVFdmVudEhvb2soJ3ByZV9ydW5fY29tbWFuZCcpO1xuICBlbnN1cmVFdmVudEhvb2soJ3ByZV9tY3BfdG9vbF91c2UnKTtcblxuICByZXR1cm4geyBjaGFuZ2VkLCBwYXJzZWQgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29weUhvb2tBc3NldChzb3VyY2VQYXRoOiBzdHJpbmcsIHRhcmdldFBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBhd2FpdCBta2RpcihkaXJuYW1lKHRhcmdldFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCBzb3VyY2VSYXcgPSBhd2FpdCByZWFkRmlsZShzb3VyY2VQYXRoLCAndXRmLTgnKTtcblxuICBsZXQgdGFyZ2V0UmF3OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHRyeSB7XG4gICAgdGFyZ2V0UmF3ID0gYXdhaXQgcmVhZEZpbGUodGFyZ2V0UGF0aCwgJ3V0Zi04Jyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKCFpc01pc3NpbmdGaWxlRXJyb3IoZXJyb3IpKSB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cbiAgY29uc3QgY2hhbmdlZCA9IHRhcmdldFJhdyA9PT0gdW5kZWZpbmVkIHx8IHNvdXJjZVJhdyAhPT0gdGFyZ2V0UmF3O1xuXG4gIGlmIChjaGFuZ2VkKSB7XG4gICAgYXdhaXQgY29weUZpbGUoc291cmNlUGF0aCwgdGFyZ2V0UGF0aCk7XG4gIH0gZWxzZSB7XG4gICAgYXdhaXQgYWNjZXNzKHRhcmdldFBhdGgpO1xuICB9XG5cbiAgYXdhaXQgY2htb2QodGFyZ2V0UGF0aCwgMG83NTUpO1xuICByZXR1cm4gY2hhbmdlZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVhZE9wdGlvbmFsVXRmOChmaWxlUGF0aDogc3RyaW5nLCBmYWxsYmFjazogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgcmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChpc01pc3NpbmdGaWxlRXJyb3IoZXJyb3IpKSB7XG4gICAgICByZXR1cm4gZmFsbGJhY2s7XG4gICAgfVxuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdyaXRlQmFja3VwSWZQcmVzZW50KGZpbGVQYXRoOiBzdHJpbmcsIHJhdzogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgaWYgKCFleGlzdHNTeW5jKGZpbGVQYXRoKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBiYWNrdXBQYXRoID0gYCR7ZmlsZVBhdGh9LmRvbGxob3VzZS5iYWtgO1xuICBhd2FpdCB3cml0ZUZpbGUoYmFja3VwUGF0aCwgcmF3LCAndXRmLTgnKTtcbiAgcmV0dXJuIGJhY2t1cFBhdGg7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lcmdlQ2xhdWRlU2V0dGluZ3Moc2V0dGluZ3NQYXRoOiBzdHJpbmcsIGNvbW1hbmQ6IHN0cmluZyk6IFByb21pc2U8eyBjaGFuZ2VkOiBib29sZWFuOyBiYWNrdXBQYXRoPzogc3RyaW5nIH0+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShzZXR0aW5nc1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCByYXcgPSBhd2FpdCByZWFkT3B0aW9uYWxVdGY4KHNldHRpbmdzUGF0aCwgJ3t9XFxuJyk7XG5cbiAgY29uc3QgaW5kZW50ID0gZGV0ZWN0SW5kZW50KHJhdyk7XG4gIGNvbnN0IHBhcnNlZCA9IHJhdy50cmltKCkubGVuZ3RoID09PSAwID8ge30gOiBKU09OLnBhcnNlKHJhdykgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHsgY2hhbmdlZCwgcGFyc2VkOiB1cGRhdGVkIH0gPSBlbnN1cmVDbGF1ZGVQcmVUb29sVXNlSG9vayhwYXJzZWQsIGNvbW1hbmQpO1xuICBpZiAoIWNoYW5nZWQpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IHdyaXRlQmFja3VwSWZQcmVzZW50KHNldHRpbmdzUGF0aCwgcmF3KTtcblxuICBhd2FpdCB3cml0ZUZpbGUoc2V0dGluZ3NQYXRoLCBKU09OLnN0cmluZ2lmeSh1cGRhdGVkLCBudWxsLCBpbmRlbnQpICsgJ1xcbicsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lcmdlVnNDb2RlSG9va1NldHRpbmdzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7fVxcbicpO1xuXG4gIGNvbnN0IGluZGVudCA9IGRldGVjdEluZGVudChyYXcpO1xuICBjb25zdCBwYXJzZWQgPSByYXcudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHt9IDogSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IGNoYW5nZWQsIHBhcnNlZDogdXBkYXRlZCB9ID0gZW5zdXJlVnNDb2RlUHJlVG9vbFVzZUhvb2socGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKHNldHRpbmdzUGF0aCwgSlNPTi5zdHJpbmdpZnkodXBkYXRlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZVZzQ29kZVVzZXJTZXR0aW5ncyhzZXR0aW5nc1BhdGg6IHN0cmluZyk6IFByb21pc2U8eyBjaGFuZ2VkOiBib29sZWFuOyBiYWNrdXBQYXRoPzogc3RyaW5nIH0+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShzZXR0aW5nc1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCByYXcgPSBhd2FpdCByZWFkT3B0aW9uYWxVdGY4KHNldHRpbmdzUGF0aCwgJ3t9XFxuJyk7XG4gIGNvbnN0IGluZGVudCA9IGRldGVjdEluZGVudChyYXcpO1xuICBjb25zdCBwYXJzZWQgPSByYXcudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHt9IDogSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCBjdXJyZW50ID0gcGFyc2VkWydjaGF0Lmhvb2tGaWxlc0xvY2F0aW9ucyddO1xuICBjb25zdCBsb2NhdGlvbnMgPSAoY3VycmVudCAmJiB0eXBlb2YgY3VycmVudCA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoY3VycmVudCkpXG4gICAgPyB7IC4uLihjdXJyZW50IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB9XG4gICAgOiB7fTtcblxuICBpZiAobG9jYXRpb25zWyd+Ly5jb3BpbG90L2hvb2tzJ10gPT09IHRydWUpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSB9O1xuICB9XG5cbiAgbG9jYXRpb25zWyd+Ly5jb3BpbG90L2hvb2tzJ10gPSB0cnVlO1xuICBwYXJzZWRbJ2NoYXQuaG9va0ZpbGVzTG9jYXRpb25zJ10gPSBsb2NhdGlvbnM7XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IHdyaXRlQmFja3VwSWZQcmVzZW50KHNldHRpbmdzUGF0aCwgcmF3KTtcbiAgYXdhaXQgd3JpdGVGaWxlKHNldHRpbmdzUGF0aCwgSlNPTi5zdHJpbmdpZnkocGFyc2VkLCBudWxsLCBpbmRlbnQpICsgJ1xcbicsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lcmdlR2VtaW5pU2V0dGluZ3Moc2V0dGluZ3NQYXRoOiBzdHJpbmcsIGNvbW1hbmQ6IHN0cmluZyk6IFByb21pc2U8eyBjaGFuZ2VkOiBib29sZWFuOyBiYWNrdXBQYXRoPzogc3RyaW5nIH0+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShzZXR0aW5nc1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCByYXcgPSBhd2FpdCByZWFkT3B0aW9uYWxVdGY4KHNldHRpbmdzUGF0aCwgJ3t9XFxuJyk7XG5cbiAgY29uc3QgaW5kZW50ID0gZGV0ZWN0SW5kZW50KHJhdyk7XG4gIGNvbnN0IHBhcnNlZCA9IHJhdy50cmltKCkubGVuZ3RoID09PSAwID8ge30gOiBKU09OLnBhcnNlKHJhdykgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHsgY2hhbmdlZCwgcGFyc2VkOiB1cGRhdGVkIH0gPSBlbnN1cmVHZW1pbmlCZWZvcmVUb29sSG9vayhwYXJzZWQsIGNvbW1hbmQpO1xuICBpZiAoIWNoYW5nZWQpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IHdyaXRlQmFja3VwSWZQcmVzZW50KHNldHRpbmdzUGF0aCwgcmF3KTtcblxuICBhd2FpdCB3cml0ZUZpbGUoc2V0dGluZ3NQYXRoLCBKU09OLnN0cmluZ2lmeSh1cGRhdGVkLCBudWxsLCBpbmRlbnQpICsgJ1xcbicsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lcmdlQ3Vyc29ySG9va3Moc2V0dGluZ3NQYXRoOiBzdHJpbmcsIGNvbW1hbmQ6IHN0cmluZyk6IFByb21pc2U8eyBjaGFuZ2VkOiBib29sZWFuOyBiYWNrdXBQYXRoPzogc3RyaW5nIH0+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShzZXR0aW5nc1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCByYXcgPSBhd2FpdCByZWFkT3B0aW9uYWxVdGY4KHNldHRpbmdzUGF0aCwgJ3tcXG4gIFwidmVyc2lvblwiOiAxLFxcbiAgXCJob29rc1wiOiB7fVxcbn1cXG4nKTtcblxuICBjb25zdCBpbmRlbnQgPSBkZXRlY3RJbmRlbnQocmF3KTtcbiAgY29uc3QgcGFyc2VkID0gcmF3LnRyaW0oKS5sZW5ndGggPT09IDAgPyB7fSA6IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgeyBjaGFuZ2VkLCBwYXJzZWQ6IHVwZGF0ZWQgfSA9IGVuc3VyZUN1cnNvclByZVRvb2xVc2VIb29rKHBhcnNlZCwgY29tbWFuZCk7XG4gIGlmICghY2hhbmdlZCkge1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBiYWNrdXBQYXRoID0gYXdhaXQgd3JpdGVCYWNrdXBJZlByZXNlbnQoc2V0dGluZ3NQYXRoLCByYXcpO1xuXG4gIGF3YWl0IHdyaXRlRmlsZShzZXR0aW5nc1BhdGgsIEpTT04uc3RyaW5naWZ5KHVwZGF0ZWQsIG51bGwsIGluZGVudCkgKyAnXFxuJywgJ3V0Zi04Jyk7XG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIGJhY2t1cFBhdGggfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWVyZ2VXaW5kc3VyZkhvb2tzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7XFxuICBcImhvb2tzXCI6IHt9XFxufVxcbicpO1xuXG4gIGNvbnN0IGluZGVudCA9IGRldGVjdEluZGVudChyYXcpO1xuICBjb25zdCBwYXJzZWQgPSByYXcudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHt9IDogSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IGNoYW5nZWQsIHBhcnNlZDogdXBkYXRlZCB9ID0gZW5zdXJlV2luZHN1cmZIb29rcyhwYXJzZWQsIGNvbW1hbmQpO1xuICBpZiAoIWNoYW5nZWQpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IHdyaXRlQmFja3VwSWZQcmVzZW50KHNldHRpbmdzUGF0aCwgcmF3KTtcblxuICBhd2FpdCB3cml0ZUZpbGUoc2V0dGluZ3NQYXRoLCBKU09OLnN0cmluZ2lmeSh1cGRhdGVkLCBudWxsLCBpbmRlbnQpICsgJ1xcbicsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lcmdlQ29kZXhIb29rcyhob29rc1BhdGg6IHN0cmluZywgY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTx7IGNoYW5nZWQ6IGJvb2xlYW47IGJhY2t1cFBhdGg/OiBzdHJpbmcgfT4ge1xuICBhd2FpdCBta2RpcihkaXJuYW1lKGhvb2tzUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IHJhdyA9IGF3YWl0IHJlYWRPcHRpb25hbFV0ZjgoaG9va3NQYXRoLCAne31cXG4nKTtcblxuICBjb25zdCBpbmRlbnQgPSBkZXRlY3RJbmRlbnQocmF3KTtcbiAgY29uc3QgcGFyc2VkID0gcmF3LnRyaW0oKS5sZW5ndGggPT09IDAgPyB7fSA6IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgeyBjaGFuZ2VkLCBwYXJzZWQ6IHVwZGF0ZWQgfSA9IGVuc3VyZUNvZGV4UHJlVG9vbFVzZUhvb2socGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChob29rc1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKGhvb2tzUGF0aCwgSlNPTi5zdHJpbmdpZnkodXBkYXRlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5mdW5jdGlvbiBnZXRUb21sTGluZUNvbnRlbnQobGluZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgY29tbWVudEluZGV4ID0gbGluZS5pbmRleE9mKCcjJyk7XG4gIHJldHVybiAoY29tbWVudEluZGV4ID49IDAgPyBsaW5lLnNsaWNlKDAsIGNvbW1lbnRJbmRleCkgOiBsaW5lKS50cmltKCk7XG59XG5cbmZ1bmN0aW9uIGlzVG9tbFNlY3Rpb25MaW5lKGxpbmU6IHN0cmluZywgc2VjdGlvbjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBnZXRUb21sTGluZUNvbnRlbnQobGluZSkgPT09IGBbJHtzZWN0aW9ufV1gO1xufVxuXG5mdW5jdGlvbiBwYXJzZVRvbWxCb29sZWFuQXNzaWdubWVudChsaW5lOiBzdHJpbmcsIGtleTogc3RyaW5nKTogYm9vbGVhbiB8IG51bGwge1xuICBjb25zdCBjb250ZW50ID0gZ2V0VG9tbExpbmVDb250ZW50KGxpbmUpO1xuICBpZiAoIWNvbnRlbnQuc3RhcnRzV2l0aChgJHtrZXl9ID0gYCkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCB2YWx1ZSA9IGNvbnRlbnQuc2xpY2UoYCR7a2V5fSA9IGAubGVuZ3RoKS50cmltKCk7XG4gIGlmICh2YWx1ZSA9PT0gJ3RydWUnKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKHZhbHVlID09PSAnZmFsc2UnKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVUb21sQm9vbGVhbkFzc2lnbm1lbnQobGluZTogc3RyaW5nLCBrZXk6IHN0cmluZywgbmV4dFZhbHVlOiBib29sZWFuKTogc3RyaW5nIHtcbiAgY29uc3QgY29tbWVudEluZGV4ID0gbGluZS5pbmRleE9mKCcjJyk7XG4gIGNvbnN0IGNvbW1lbnRTdWZmaXggPSBjb21tZW50SW5kZXggPj0gMCA/IGxpbmUuc2xpY2UoY29tbWVudEluZGV4KSA6ICcnO1xuICBsZXQgcHJlZml4TGVuZ3RoID0gMDtcbiAgd2hpbGUgKHByZWZpeExlbmd0aCA8IGxpbmUubGVuZ3RoICYmIC9cXHMvLnRlc3QobGluZS5jaGFyQXQocHJlZml4TGVuZ3RoKSkpIHtcbiAgICBwcmVmaXhMZW5ndGggKz0gMTtcbiAgfVxuICBjb25zdCBwcmVmaXggPSBsaW5lLnNsaWNlKDAsIHByZWZpeExlbmd0aCk7XG4gIGNvbnN0IGFzc2lnbm1lbnQgPSBgJHtwcmVmaXh9JHtrZXl9ID0gJHtuZXh0VmFsdWUgPyAndHJ1ZScgOiAnZmFsc2UnfWA7XG4gIGNvbnN0IHRyaW1tZWRDb21tZW50U3VmZml4ID0gY29tbWVudFN1ZmZpeC50cmltU3RhcnQoKTtcbiAgY29uc3Qgc3VmZml4ID0gdHJpbW1lZENvbW1lbnRTdWZmaXgubGVuZ3RoID4gMCA/IGAgJHt0cmltbWVkQ29tbWVudFN1ZmZpeH1gIDogJyc7XG4gIHJldHVybiBgJHthc3NpZ25tZW50fSR7c3VmZml4fWAudHJpbUVuZCgpO1xufVxuXG5mdW5jdGlvbiBzdHJpcFRyYWlsaW5nTmV3bGluZXModmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGxldCBlbmQgPSB2YWx1ZS5sZW5ndGg7XG4gIHdoaWxlIChlbmQgPiAwICYmIHZhbHVlLmNoYXJBdChlbmQgLSAxKSA9PT0gJ1xcbicpIHtcbiAgICBlbmQgLT0gMTtcbiAgfVxuICByZXR1cm4gdmFsdWUuc2xpY2UoMCwgZW5kKTtcbn1cblxuZnVuY3Rpb24gZW5zdXJlQ29kZXhIb29rc0VuYWJsZWQocmF3OiBzdHJpbmcpOiB7IGNoYW5nZWQ6IGJvb2xlYW47IGNvbnRlbnQ6IHN0cmluZyB9IHtcbiAgY29uc3QgbGluZXMgPSByYXcubGVuZ3RoID4gMCA/IHJhdy5zcGxpdCgnXFxuJykgOiBbXTtcbiAgY29uc3QgZG90dGVkSW5kZXggPSBsaW5lcy5maW5kSW5kZXgoKGxpbmUpID0+IHBhcnNlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KGxpbmUsICdmZWF0dXJlcy5jb2RleF9ob29rcycpICE9PSBudWxsKTtcbiAgaWYgKGRvdHRlZEluZGV4ID49IDApIHtcbiAgICBpZiAocGFyc2VUb21sQm9vbGVhbkFzc2lnbm1lbnQobGluZXNbZG90dGVkSW5kZXhdLCAnZmVhdHVyZXMuY29kZXhfaG9va3MnKSA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UsIGNvbnRlbnQ6IHJhdyB9O1xuICAgIH1cbiAgICBjb25zdCB1cGRhdGVkTGluZXMgPSBbLi4ubGluZXNdO1xuICAgIHVwZGF0ZWRMaW5lc1tkb3R0ZWRJbmRleF0gPSB1cGRhdGVUb21sQm9vbGVhbkFzc2lnbm1lbnQodXBkYXRlZExpbmVzW2RvdHRlZEluZGV4XSwgJ2ZlYXR1cmVzLmNvZGV4X2hvb2tzJywgdHJ1ZSk7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgY29udGVudDogYCR7c3RyaXBUcmFpbGluZ05ld2xpbmVzKHVwZGF0ZWRMaW5lcy5qb2luKCdcXG4nKSl9XFxuYCB9O1xuICB9XG5cbiAgY29uc3Qgc2VjdGlvbkluZGV4ID0gbGluZXMuZmluZEluZGV4KChsaW5lKSA9PiBpc1RvbWxTZWN0aW9uTGluZShsaW5lLCAnZmVhdHVyZXMnKSk7XG4gIGlmIChzZWN0aW9uSW5kZXggPj0gMCkge1xuICAgIGNvbnN0IG5leHRTZWN0aW9uSW5kZXggPSBsaW5lcy5maW5kSW5kZXgoKGxpbmUsIGluZGV4KSA9PiBpbmRleCA+IHNlY3Rpb25JbmRleCAmJiBnZXRUb21sTGluZUNvbnRlbnQobGluZSkuc3RhcnRzV2l0aCgnWycpICYmIGdldFRvbWxMaW5lQ29udGVudChsaW5lKS5lbmRzV2l0aCgnXScpKTtcbiAgICBjb25zdCBzZWN0aW9uRW5kID0gbmV4dFNlY3Rpb25JbmRleCA+PSAwID8gbmV4dFNlY3Rpb25JbmRleCA6IGxpbmVzLmxlbmd0aDtcbiAgICBjb25zdCBrZXlJbmRleCA9IGxpbmVzLmZpbmRJbmRleCgobGluZSwgaW5kZXgpID0+IGluZGV4ID4gc2VjdGlvbkluZGV4ICYmIGluZGV4IDwgc2VjdGlvbkVuZCAmJiBwYXJzZVRvbWxCb29sZWFuQXNzaWdubWVudChsaW5lLCAnY29kZXhfaG9va3MnKSAhPT0gbnVsbCk7XG5cbiAgICBpZiAoa2V5SW5kZXggPj0gMCkge1xuICAgICAgaWYgKHBhcnNlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KGxpbmVzW2tleUluZGV4XSwgJ2NvZGV4X2hvb2tzJykgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UsIGNvbnRlbnQ6IHJhdyB9O1xuICAgICAgfVxuICAgICAgY29uc3QgdXBkYXRlZExpbmVzID0gWy4uLmxpbmVzXTtcbiAgICAgIHVwZGF0ZWRMaW5lc1trZXlJbmRleF0gPSB1cGRhdGVUb21sQm9vbGVhbkFzc2lnbm1lbnQodXBkYXRlZExpbmVzW2tleUluZGV4XSwgJ2NvZGV4X2hvb2tzJywgdHJ1ZSk7XG4gICAgICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBjb250ZW50OiBgJHtzdHJpcFRyYWlsaW5nTmV3bGluZXModXBkYXRlZExpbmVzLmpvaW4oJ1xcbicpKX1cXG5gIH07XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlZExpbmVzID0gWy4uLmxpbmVzXTtcbiAgICB1cGRhdGVkTGluZXMuc3BsaWNlKHNlY3Rpb25JbmRleCArIDEsIDAsICdjb2RleF9ob29rcyA9IHRydWUnKTtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBjb250ZW50OiBgJHtzdHJpcFRyYWlsaW5nTmV3bGluZXModXBkYXRlZExpbmVzLmpvaW4oJ1xcbicpKX1cXG5gIH07XG4gIH1cblxuICBjb25zdCBwcmVmaXggPSByYXcudHJpbSgpLmxlbmd0aCA+IDAgPyBgJHtzdHJpcFRyYWlsaW5nTmV3bGluZXMocmF3KX1cXG5cXG5gIDogJyc7XG4gIHJldHVybiB7XG4gICAgY2hhbmdlZDogdHJ1ZSxcbiAgICBjb250ZW50OiBgJHtwcmVmaXh9W2ZlYXR1cmVzXVxcbmNvZGV4X2hvb2tzID0gdHJ1ZVxcbmAsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lcmdlQ29kZXhDb25maWcoY29uZmlnUGF0aDogc3RyaW5nKTogUHJvbWlzZTx7IGNoYW5nZWQ6IGJvb2xlYW47IGJhY2t1cFBhdGg/OiBzdHJpbmcgfT4ge1xuICBhd2FpdCBta2RpcihkaXJuYW1lKGNvbmZpZ1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCByYXcgPSBhd2FpdCByZWFkT3B0aW9uYWxVdGY4KGNvbmZpZ1BhdGgsICcnKTtcblxuICBjb25zdCB7IGNoYW5nZWQsIGNvbnRlbnQgfSA9IGVuc3VyZUNvZGV4SG9va3NFbmFibGVkKHJhdyk7XG4gIGlmICghY2hhbmdlZCkge1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBiYWNrdXBQYXRoID0gYXdhaXQgd3JpdGVCYWNrdXBJZlByZXNlbnQoY29uZmlnUGF0aCwgcmF3KTtcblxuICBhd2FpdCB3cml0ZUZpbGUoY29uZmlnUGF0aCwgY29udGVudCwgJ3V0Zi04Jyk7XG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIGJhY2t1cFBhdGggfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gd3JpdGVIb29rTWFya2VyKFxuICBob21lRGlyOiBzdHJpbmcsXG4gIG1hcmtlcjogUGVybWlzc2lvbkhvb2tNYXJrZXIsXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBtYXJrZXJQYXRoID0gZ2V0UGVybWlzc2lvbkhvb2tNYXJrZXJQYXRoKGhvbWVEaXIsIG1hcmtlci5ob3N0KTtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShtYXJrZXJQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIGF3YWl0IHdyaXRlRmlsZShtYXJrZXJQYXRoLCBKU09OLnN0cmluZ2lmeShtYXJrZXIsIG51bGwsIDIpICsgJ1xcbicsICd1dGYtOCcpO1xuICByZXR1cm4gbWFya2VyUGF0aDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0KFxuICBjbGllbnQ6IHN0cmluZyxcbiAgaG9tZURpcjogc3RyaW5nLFxuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nLFxuKTogUHJvbWlzZTx7IHNjcmlwdFBhdGg6IHN0cmluZyB9PiB7XG4gIGNvbnN0IG5vcm1hbGl6ZWRDbGllbnQgPSBub3JtYWxpemVIb29rSG9zdChjbGllbnQpO1xuICBjb25zdCBob29rc0RpciA9IGRpcm5hbWUoZ2V0UGVybWlzc2lvbkhvb2tTY3JpcHRQYXRoKGhvbWVEaXIpKTtcbiAgY29uc3Qgc2hhcmVkVGFyZ2V0UGF0aCA9IGdldFBlcm1pc3Npb25Ib29rU2NyaXB0UGF0aChob21lRGlyKTtcbiAgY29uc3Qgc2hhcmVkU291cmNlUGF0aCA9IHNvdXJjZVNjcmlwdFBhdGggPz8gam9pbihyZXBvUm9vdEZyb21Nb2R1bGUoKSwgJ3NjcmlwdHMnLCAncHJldG9vbHVzZS1kb2xsaG91c2Uuc2gnKTtcbiAgY29uc3QgcG9ydEhlbHBlclNvdXJjZVBhdGggPSBqb2luKHJlcG9Sb290RnJvbU1vZHVsZSgpLCAnc2NyaXB0cycsICdwZXJtaXNzaW9uLXBvcnQtZGlzY292ZXJ5LnNoJyk7XG4gIGNvbnN0IHBvcnRIZWxwZXJUYXJnZXRQYXRoID0gam9pbihob29rc0RpciwgJ3Blcm1pc3Npb24tcG9ydC1kaXNjb3Zlcnkuc2gnKTtcblxuICBjb25zdCBzaGFyZWRTdGF0ID0gc3RhdFN5bmMoc2hhcmVkU291cmNlUGF0aCk7XG4gIGlmICghc2hhcmVkU3RhdC5pc0ZpbGUoKSkge1xuICAgIGxvZ2dlci53YXJuKGBbUGVybWlzc2lvbkhvb2tzXSBTaGFyZWQgaG9vayBicmlkZ2UgbWlzc2luZyBmb3IgJHtub3JtYWxpemVkQ2xpZW50fTogJHtzaGFyZWRTb3VyY2VQYXRofWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgUGVybWlzc2lvbiBob29rIHNvdXJjZSBzY3JpcHQgbm90IGZvdW5kOiAke3NoYXJlZFNvdXJjZVBhdGh9YCk7XG4gIH1cbiAgYXdhaXQgY29weUhvb2tBc3NldChzaGFyZWRTb3VyY2VQYXRoLCBzaGFyZWRUYXJnZXRQYXRoKTtcblxuICBjb25zdCBwb3J0SGVscGVyU3RhdCA9IHN0YXRTeW5jKHBvcnRIZWxwZXJTb3VyY2VQYXRoKTtcbiAgaWYgKCFwb3J0SGVscGVyU3RhdC5pc0ZpbGUoKSkge1xuICAgIGxvZ2dlci53YXJuKGBbUGVybWlzc2lvbkhvb2tzXSBQb3J0IGRpc2NvdmVyeSBoZWxwZXIgbWlzc2luZyBmb3IgJHtub3JtYWxpemVkQ2xpZW50fTogJHtwb3J0SGVscGVyU291cmNlUGF0aH1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFBlcm1pc3Npb24gaG9vayBoZWxwZXIgc2NyaXB0IG5vdCBmb3VuZDogJHtwb3J0SGVscGVyU291cmNlUGF0aH1gKTtcbiAgfVxuICBhd2FpdCBjb3B5SG9va0Fzc2V0KHBvcnRIZWxwZXJTb3VyY2VQYXRoLCBwb3J0SGVscGVyVGFyZ2V0UGF0aCk7XG5cbiAgY29uc3Qgd3JhcHBlclRhcmdldFBhdGggPSBnZXRIb29rV3JhcHBlclBhdGgobm9ybWFsaXplZENsaWVudCwgaG9tZURpcik7XG4gIGlmICghd3JhcHBlclRhcmdldFBhdGgpIHtcbiAgICByZXR1cm4geyBzY3JpcHRQYXRoOiBzaGFyZWRUYXJnZXRQYXRoIH07XG4gIH1cblxuICBjb25zdCB3cmFwcGVyU291cmNlUGF0aCA9IGdldEhvb2tTb3VyY2VQYXRoKG5vcm1hbGl6ZWRDbGllbnQpO1xuICBjb25zdCB3cmFwcGVyU3RhdCA9IHN0YXRTeW5jKHdyYXBwZXJTb3VyY2VQYXRoKTtcbiAgaWYgKCF3cmFwcGVyU3RhdC5pc0ZpbGUoKSkge1xuICAgIGxvZ2dlci53YXJuKGBbUGVybWlzc2lvbkhvb2tzXSBXcmFwcGVyIGhvb2sgc2NyaXB0IG1pc3NpbmcgZm9yICR7bm9ybWFsaXplZENsaWVudH06ICR7d3JhcHBlclNvdXJjZVBhdGh9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBQZXJtaXNzaW9uIGhvb2sgd3JhcHBlciBzY3JpcHQgbm90IGZvdW5kOiAke3dyYXBwZXJTb3VyY2VQYXRofWApO1xuICB9XG4gIGF3YWl0IGNvcHlIb29rQXNzZXQod3JhcHBlclNvdXJjZVBhdGgsIHdyYXBwZXJUYXJnZXRQYXRoKTtcbiAgcmV0dXJuIHsgc2NyaXB0UGF0aDogd3JhcHBlclRhcmdldFBhdGggfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbENsYXVkZUNvZGVQZXJtaXNzaW9uSG9vayhcbiAgaG9tZURpcjogc3RyaW5nLFxuICBpbnN0YWxsZWRBdDogc3RyaW5nLFxuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nLFxuKTogUHJvbWlzZTxJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQ+IHtcbiAgY29uc3QgaG9zdCA9ICdjbGF1ZGUtY29kZSc7XG4gIGNvbnN0IHsgc2NyaXB0UGF0aCB9ID0gYXdhaXQgaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0KGhvc3QsIGhvbWVEaXIsIHNvdXJjZVNjcmlwdFBhdGgpO1xuICBjb25zdCBzZXR0aW5nc1BhdGggPSBnZXRDbGF1ZGVIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIpO1xuICBjb25zdCBzZXR0aW5nc1Jlc3VsdCA9IGF3YWl0IG1lcmdlQ2xhdWRlU2V0dGluZ3Moc2V0dGluZ3NQYXRoLCBgYmFzaCAke3NjcmlwdFBhdGh9YCk7XG4gIGNvbnN0IG1hcmtlclBhdGggPSBhd2FpdCB3cml0ZUhvb2tNYXJrZXIoaG9tZURpciwge1xuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWRBdCxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdXBwb3J0ZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkOiB0cnVlLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBtYXJrZXJQYXRoLFxuICAgIGJhY2t1cFBhdGg6IHNldHRpbmdzUmVzdWx0LmJhY2t1cFBhdGgsXG4gICAgbWVzc2FnZTogJ0luc3RhbGxlZCBDbGF1ZGUgQ29kZSBwZXJtaXNzaW9uIGhvb2sgYW5kIHVwZGF0ZWQgc2V0dGluZ3MuanNvbi4nLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsVnNDb2RlUGVybWlzc2lvbkhvb2soXG4gIGhvbWVEaXI6IHN0cmluZyxcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZyxcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8SW5zdGFsbFBlcm1pc3Npb25Ib29rUmVzdWx0PiB7XG4gIGNvbnN0IGhvc3QgPSAndnNjb2RlJztcbiAgY29uc3QgeyBzY3JpcHRQYXRoIH0gPSBhd2FpdCBpbnN0YWxsSG9va0Fzc2V0c0Zvckhvc3QoaG9zdCwgaG9tZURpciwgc291cmNlU2NyaXB0UGF0aCk7XG4gIGNvbnN0IHNldHRpbmdzUGF0aCA9IGdldFZzQ29kZUhvb2tTZXR0aW5nc1BhdGgoaG9tZURpcik7XG4gIGNvbnN0IHVzZXJTZXR0aW5nc1BhdGggPSBnZXRWc0NvZGVVc2VyU2V0dGluZ3NQYXRoKGhvbWVEaXIpO1xuICBjb25zdCBob29rUmVzdWx0ID0gYXdhaXQgbWVyZ2VWc0NvZGVIb29rU2V0dGluZ3Moc2V0dGluZ3NQYXRoLCBgYmFzaCAke3NjcmlwdFBhdGh9YCk7XG4gIGNvbnN0IHVzZXJTZXR0aW5nc1Jlc3VsdCA9IGF3YWl0IG1lcmdlVnNDb2RlVXNlclNldHRpbmdzKHVzZXJTZXR0aW5nc1BhdGgpO1xuICBjb25zdCBtYXJrZXJQYXRoID0gYXdhaXQgd3JpdGVIb29rTWFya2VyKGhvbWVEaXIsIHtcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGFkZGl0aW9uYWxQYXRoczogW3VzZXJTZXR0aW5nc1BhdGhdLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkQXQsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgc3VwcG9ydGVkOiB0cnVlLFxuICAgIGluc3RhbGxlZDogdHJ1ZSxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgYWRkaXRpb25hbFBhdGhzOiBbdXNlclNldHRpbmdzUGF0aF0sXG4gICAgbWFya2VyUGF0aCxcbiAgICBiYWNrdXBQYXRoOiBob29rUmVzdWx0LmJhY2t1cFBhdGggPz8gdXNlclNldHRpbmdzUmVzdWx0LmJhY2t1cFBhdGgsXG4gICAgbWVzc2FnZTogJ0luc3RhbGxlZCBWUyBDb2RlIHBlcm1pc3Npb24gaG9vayBhbmQgZW5hYmxlZCBjaGF0Lmhvb2tGaWxlc0xvY2F0aW9ucyBmb3Igfi8uY29waWxvdC9ob29rcy4nLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsR2VtaW5pQ2xpUGVybWlzc2lvbkhvb2soXG4gIGhvbWVEaXI6IHN0cmluZyxcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZyxcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8SW5zdGFsbFBlcm1pc3Npb25Ib29rUmVzdWx0PiB7XG4gIGNvbnN0IGhvc3QgPSAnZ2VtaW5pLWNsaSc7XG4gIGNvbnN0IHsgc2NyaXB0UGF0aCB9ID0gYXdhaXQgaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0KGhvc3QsIGhvbWVEaXIsIHNvdXJjZVNjcmlwdFBhdGgpO1xuICBjb25zdCBzZXR0aW5nc1BhdGggPSBnZXRHZW1pbmlIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIpO1xuICBjb25zdCBzZXR0aW5nc1Jlc3VsdCA9IGF3YWl0IG1lcmdlR2VtaW5pU2V0dGluZ3Moc2V0dGluZ3NQYXRoLCBgYmFzaCAke3NjcmlwdFBhdGh9YCk7XG4gIGNvbnN0IG1hcmtlclBhdGggPSBhd2FpdCB3cml0ZUhvb2tNYXJrZXIoaG9tZURpciwge1xuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWRBdCxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdXBwb3J0ZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkOiB0cnVlLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBtYXJrZXJQYXRoLFxuICAgIGJhY2t1cFBhdGg6IHNldHRpbmdzUmVzdWx0LmJhY2t1cFBhdGgsXG4gICAgbWVzc2FnZTogJ0luc3RhbGxlZCBHZW1pbmkgQ0xJIHBlcm1pc3Npb24gaG9vayBhbmQgdXBkYXRlZCBzZXR0aW5ncy5qc29uLicsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxDdXJzb3JQZXJtaXNzaW9uSG9vayhcbiAgaG9tZURpcjogc3RyaW5nLFxuICBpbnN0YWxsZWRBdDogc3RyaW5nLFxuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nLFxuKTogUHJvbWlzZTxJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQ+IHtcbiAgY29uc3QgaG9zdCA9ICdjdXJzb3InO1xuICBjb25zdCB7IHNjcmlwdFBhdGggfSA9IGF3YWl0IGluc3RhbGxIb29rQXNzZXRzRm9ySG9zdChob3N0LCBob21lRGlyLCBzb3VyY2VTY3JpcHRQYXRoKTtcbiAgY29uc3Qgc2V0dGluZ3NQYXRoID0gZ2V0Q3Vyc29ySG9va1NldHRpbmdzUGF0aChob21lRGlyKTtcbiAgY29uc3Qgc2V0dGluZ3NSZXN1bHQgPSBhd2FpdCBtZXJnZUN1cnNvckhvb2tzKHNldHRpbmdzUGF0aCwgYGJhc2ggJHtzY3JpcHRQYXRofWApO1xuICBjb25zdCBtYXJrZXJQYXRoID0gYXdhaXQgd3JpdGVIb29rTWFya2VyKGhvbWVEaXIsIHtcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkQXQsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgc3VwcG9ydGVkOiB0cnVlLFxuICAgIGluc3RhbGxlZDogdHJ1ZSxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgbWFya2VyUGF0aCxcbiAgICBiYWNrdXBQYXRoOiBzZXR0aW5nc1Jlc3VsdC5iYWNrdXBQYXRoLFxuICAgIG1lc3NhZ2U6ICdJbnN0YWxsZWQgQ3Vyc29yIHBlcm1pc3Npb24gaG9vayBhbmQgdXBkYXRlZCBob29rcy5qc29uLicsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxXaW5kc3VyZlBlcm1pc3Npb25Ib29rKFxuICBob21lRGlyOiBzdHJpbmcsXG4gIGluc3RhbGxlZEF0OiBzdHJpbmcsXG4gIHNvdXJjZVNjcmlwdFBhdGg/OiBzdHJpbmcsXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCBob3N0ID0gJ3dpbmRzdXJmJztcbiAgY29uc3QgeyBzY3JpcHRQYXRoIH0gPSBhd2FpdCBpbnN0YWxsSG9va0Fzc2V0c0Zvckhvc3QoaG9zdCwgaG9tZURpciwgc291cmNlU2NyaXB0UGF0aCk7XG4gIGNvbnN0IHNldHRpbmdzUGF0aCA9IGdldFdpbmRzdXJmSG9va1NldHRpbmdzUGF0aChob21lRGlyKTtcbiAgY29uc3Qgc2V0dGluZ3NSZXN1bHQgPSBhd2FpdCBtZXJnZVdpbmRzdXJmSG9va3Moc2V0dGluZ3NQYXRoLCBgYmFzaCAke3NjcmlwdFBhdGh9YCk7XG4gIGNvbnN0IG1hcmtlclBhdGggPSBhd2FpdCB3cml0ZUhvb2tNYXJrZXIoaG9tZURpciwge1xuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWRBdCxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdXBwb3J0ZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkOiB0cnVlLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBtYXJrZXJQYXRoLFxuICAgIGJhY2t1cFBhdGg6IHNldHRpbmdzUmVzdWx0LmJhY2t1cFBhdGgsXG4gICAgbWVzc2FnZTogJ0luc3RhbGxlZCBXaW5kc3VyZiBwZXJtaXNzaW9uIGhvb2tzIGFuZCB1cGRhdGVkIGhvb2tzLmpzb24uJyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbENvZGV4UGVybWlzc2lvbkhvb2soXG4gIGhvbWVEaXI6IHN0cmluZyxcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZyxcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8SW5zdGFsbFBlcm1pc3Npb25Ib29rUmVzdWx0PiB7XG4gIGNvbnN0IGhvc3QgPSAnY29kZXgnO1xuICBjb25zdCB7IHNjcmlwdFBhdGggfSA9IGF3YWl0IGluc3RhbGxIb29rQXNzZXRzRm9ySG9zdChob3N0LCBob21lRGlyLCBzb3VyY2VTY3JpcHRQYXRoKTtcbiAgY29uc3Qgc2V0dGluZ3NQYXRoID0gZ2V0Q29kZXhIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIpO1xuICBjb25zdCBjb25maWdQYXRoID0gZ2V0Q29kZXhDb25maWdQYXRoKGhvbWVEaXIpO1xuICBjb25zdCBob29rc1Jlc3VsdCA9IGF3YWl0IG1lcmdlQ29kZXhIb29rcyhzZXR0aW5nc1BhdGgsIGBiYXNoICR7c2NyaXB0UGF0aH1gKTtcbiAgY29uc3QgY29uZmlnUmVzdWx0ID0gYXdhaXQgbWVyZ2VDb2RleENvbmZpZyhjb25maWdQYXRoKTtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGF3YWl0IHdyaXRlSG9va01hcmtlcihob21lRGlyLCB7XG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBhZGRpdGlvbmFsUGF0aHM6IFtjb25maWdQYXRoXSxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGluc3RhbGxlZEF0LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGFkZGl0aW9uYWxQYXRoczogW2NvbmZpZ1BhdGhdLFxuICAgIG1hcmtlclBhdGgsXG4gICAgYmFja3VwUGF0aDogaG9va3NSZXN1bHQuYmFja3VwUGF0aCA/PyBjb25maWdSZXN1bHQuYmFja3VwUGF0aCxcbiAgICBtZXNzYWdlOiAnSW5zdGFsbGVkIENvZGV4IEJhc2ggcGVybWlzc2lvbiBob29rLCBjcmVhdGVkIGhvb2tzLmpzb24sIGFuZCBlbmFibGVkIGZlYXR1cmVzLmNvZGV4X2hvb2tzIGluIGNvbmZpZy50b21sLicsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxNYW51YWxQZXJtaXNzaW9uSG9va0Fzc2V0cyhcbiAgbm9ybWFsaXplZENsaWVudDogc3RyaW5nLFxuICBob21lRGlyOiBzdHJpbmcsXG4gIGluc3RhbGxlZEF0OiBzdHJpbmcsXG4gIHNvdXJjZVNjcmlwdFBhdGg/OiBzdHJpbmcsXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCB7IHNjcmlwdFBhdGggfSA9IGF3YWl0IGluc3RhbGxIb29rQXNzZXRzRm9ySG9zdChub3JtYWxpemVkQ2xpZW50LCBob21lRGlyLCBzb3VyY2VTY3JpcHRQYXRoKTtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGF3YWl0IHdyaXRlSG9va01hcmtlcihob21lRGlyLCB7XG4gICAgaG9zdDogbm9ybWFsaXplZENsaWVudCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aDogdW5kZWZpbmVkLFxuICAgIGNvbmZpZ3VyZWQ6IGZhbHNlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGluc3RhbGxlZEF0LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgY29uZmlndXJlZDogZmFsc2UsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaG9zdDogbm9ybWFsaXplZENsaWVudCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIG1hcmtlclBhdGgsXG4gICAgbWVzc2FnZTogYEluc3RhbGxlZCBEb2xsaG91c2UgcGVybWlzc2lvbiBob29rIGFzc2V0cyBmb3IgJHtub3JtYWxpemVkQ2xpZW50fS4gRmluaXNoIHRoZSBjbGllbnQtc3BlY2lmaWMgaG9vayByZWdpc3RyYXRpb24gbWFudWFsbHkuYCxcbiAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxQZXJtaXNzaW9uSG9vayhcbiAgY2xpZW50OiBzdHJpbmcsXG4gIG9wdGlvbnM6IEluc3RhbGxQZXJtaXNzaW9uSG9va09wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8SW5zdGFsbFBlcm1pc3Npb25Ib29rUmVzdWx0PiB7XG4gIGNvbnN0IG5vcm1hbGl6ZWRDbGllbnQgPSBub3JtYWxpemVIb29rSG9zdChjbGllbnQpO1xuICBjb25zdCBob21lRGlyID0gb3B0aW9ucy5ob21lRGlyID8/IGhvbWVkaXIoKTtcbiAgY29uc3QgaW5zdGFsbGVkQXQgPSAob3B0aW9ucy5ub3cgPz8gbmV3IERhdGUoKSkudG9JU09TdHJpbmcoKTtcblxuICBpZiAobm9ybWFsaXplZENsaWVudCA9PT0gJ2NsYXVkZS1jb2RlJykge1xuICAgIHJldHVybiBpbnN0YWxsQ2xhdWRlQ29kZVBlcm1pc3Npb25Ib29rKGhvbWVEaXIsIGluc3RhbGxlZEF0LCBvcHRpb25zLnNvdXJjZVNjcmlwdFBhdGgpO1xuICB9XG5cbiAgaWYgKG5vcm1hbGl6ZWRDbGllbnQgPT09ICd2c2NvZGUnKSB7XG4gICAgcmV0dXJuIGluc3RhbGxWc0NvZGVQZXJtaXNzaW9uSG9vayhob21lRGlyLCBpbnN0YWxsZWRBdCwgb3B0aW9ucy5zb3VyY2VTY3JpcHRQYXRoKTtcbiAgfVxuXG4gIGlmIChub3JtYWxpemVkQ2xpZW50ID09PSAnZ2VtaW5pLWNsaScpIHtcbiAgICByZXR1cm4gaW5zdGFsbEdlbWluaUNsaVBlcm1pc3Npb25Ib29rKGhvbWVEaXIsIGluc3RhbGxlZEF0LCBvcHRpb25zLnNvdXJjZVNjcmlwdFBhdGgpO1xuICB9XG5cbiAgaWYgKG5vcm1hbGl6ZWRDbGllbnQgPT09ICdjdXJzb3InKSB7XG4gICAgcmV0dXJuIGluc3RhbGxDdXJzb3JQZXJtaXNzaW9uSG9vayhob21lRGlyLCBpbnN0YWxsZWRBdCwgb3B0aW9ucy5zb3VyY2VTY3JpcHRQYXRoKTtcbiAgfVxuXG4gIGlmIChub3JtYWxpemVkQ2xpZW50ID09PSAnd2luZHN1cmYnKSB7XG4gICAgcmV0dXJuIGluc3RhbGxXaW5kc3VyZlBlcm1pc3Npb25Ib29rKGhvbWVEaXIsIGluc3RhbGxlZEF0LCBvcHRpb25zLnNvdXJjZVNjcmlwdFBhdGgpO1xuICB9XG5cbiAgaWYgKG5vcm1hbGl6ZWRDbGllbnQgPT09ICdjb2RleCcpIHtcbiAgICByZXR1cm4gaW5zdGFsbENvZGV4UGVybWlzc2lvbkhvb2soaG9tZURpciwgaW5zdGFsbGVkQXQsIG9wdGlvbnMuc291cmNlU2NyaXB0UGF0aCk7XG4gIH1cblxuICBpZiAoZ2V0SG9va1dyYXBwZXJCYXNlbmFtZShub3JtYWxpemVkQ2xpZW50KSkge1xuICAgIHJldHVybiBpbnN0YWxsTWFudWFsUGVybWlzc2lvbkhvb2tBc3NldHMobm9ybWFsaXplZENsaWVudCwgaG9tZURpciwgaW5zdGFsbGVkQXQsIG9wdGlvbnMuc291cmNlU2NyaXB0UGF0aCk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogZmFsc2UsXG4gICAgaW5zdGFsbGVkOiBmYWxzZSxcbiAgICBjb25maWd1cmVkOiBmYWxzZSxcbiAgICBob3N0OiBub3JtYWxpemVkQ2xpZW50LFxuICAgIG1lc3NhZ2U6IGBBdXRvbWF0aWMgcGVybWlzc2lvbiBob29rIHdpcmluZyBpcyBub3QgeWV0IHN1cHBvcnRlZCBmb3IgJHtub3JtYWxpemVkQ2xpZW50fS5gLFxuICB9O1xufVxuIl19
1
+ export { AUTO_REPAIRABLE_HOOK_HOSTS, MANAGED_HOOK_WRAPPER_BASENAMES, WRAPPER_HOOK_HOSTS, detectIndent, getClaudeHookSettingsPath, getCodexConfigPath, getCodexHookSettingsPath, getCursorHookSettingsPath, getGeminiHookSettingsPath, getHookSourcePath, getHookWrapperBasename, getHookWrapperPath, getManagedHookAssets, getPermissionHookMarkerPath, getPermissionHookScriptPath, getPrimaryHookScriptPath, getVsCodeHookSettingsPath, getVsCodeUserSettingsPath, getWindsurfHookSettingsPath, installHookAssetsForHost, isMissingFileError, normalizeHookHost, readOptionalUtf8, supportsManagedHookAssets, writeBackupIfPresent, } from './permissionHookShared.js';
2
+ export { ensureClaudePreToolUseHook, ensureCodexPreToolUseHook, ensureCursorPreToolUseHook, ensureGeminiBeforeToolHook, ensureVsCodePreToolUseHook, ensureWindsurfHooks, installPermissionHook, } from './permissionHookInstallers.js';
3
+ export { _resetPermissionHookStartupRepairSummaryForTests, getLastPermissionHookStartupRepairSummary, getPermissionHookAuditSummary, getPermissionHookStatus, getPermissionHookStatusAsync, reconcilePermissionHookStatus, repairPermissionHooksOnStartup, summarizePermissionHookHealth, } from './permissionHookStatus.js';
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvbkhvb2tzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3Blcm1pc3Npb25Ib29rcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsMEJBQTBCLEVBQzFCLDhCQUE4QixFQUM5QixrQkFBa0IsRUFZbEIsWUFBWSxFQUNaLHlCQUF5QixFQUN6QixrQkFBa0IsRUFDbEIsd0JBQXdCLEVBQ3hCLHlCQUF5QixFQUN6Qix5QkFBeUIsRUFDekIsaUJBQWlCLEVBQ2pCLHNCQUFzQixFQUN0QixrQkFBa0IsRUFDbEIsb0JBQW9CLEVBQ3BCLDJCQUEyQixFQUMzQiwyQkFBMkIsRUFDM0Isd0JBQXdCLEVBQ3hCLHlCQUF5QixFQUN6Qix5QkFBeUIsRUFDekIsMkJBQTJCLEVBQzNCLHdCQUF3QixFQUN4QixrQkFBa0IsRUFDbEIsaUJBQWlCLEVBQ2pCLGdCQUFnQixFQUNoQix5QkFBeUIsRUFDekIsb0JBQW9CLEdBQ3JCLE1BQU0sMkJBQTJCLENBQUM7QUFFbkMsT0FBTyxFQUNMLDBCQUEwQixFQUMxQix5QkFBeUIsRUFDekIsMEJBQTBCLEVBQzFCLDBCQUEwQixFQUMxQiwwQkFBMEIsRUFDMUIsbUJBQW1CLEVBQ25CLHFCQUFxQixHQUN0QixNQUFNLCtCQUErQixDQUFDO0FBRXZDLE9BQU8sRUFDTCxnREFBZ0QsRUFDaEQseUNBQXlDLEVBQ3pDLDZCQUE2QixFQUM3Qix1QkFBdUIsRUFDdkIsNEJBQTRCLEVBQzVCLDZCQUE2QixFQUM3Qiw4QkFBOEIsRUFDOUIsNkJBQTZCLEdBQzlCLE1BQU0sMkJBQTJCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQge1xuICBBVVRPX1JFUEFJUkFCTEVfSE9PS19IT1NUUyxcbiAgTUFOQUdFRF9IT09LX1dSQVBQRVJfQkFTRU5BTUVTLFxuICBXUkFQUEVSX0hPT0tfSE9TVFMsXG4gIHR5cGUgSG9va0Fzc2V0QXVkaXRSZXN1bHQsXG4gIHR5cGUgSG9va0Fzc2V0RGVzY3JpcHRvcixcbiAgdHlwZSBJbnN0YWxsUGVybWlzc2lvbkhvb2tPcHRpb25zLFxuICB0eXBlIEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdCxcbiAgdHlwZSBQZXJtaXNzaW9uSG9va0F1ZGl0U3VtbWFyeSxcbiAgdHlwZSBQZXJtaXNzaW9uSG9va0hlYWx0aFN1bW1hcnksXG4gIHR5cGUgUGVybWlzc2lvbkhvb2tNYXJrZXIsXG4gIHR5cGUgUGVybWlzc2lvbkhvb2tTdGFydHVwUmVwYWlySG9zdFJlc3VsdCxcbiAgdHlwZSBQZXJtaXNzaW9uSG9va1N0YXJ0dXBSZXBhaXJTdW1tYXJ5LFxuICB0eXBlIFBlcm1pc3Npb25Ib29rU3RhdHVzLFxuICB0eXBlIFJlY29uY2lsZVBlcm1pc3Npb25Ib29rT3B0aW9ucyxcbiAgZGV0ZWN0SW5kZW50LFxuICBnZXRDbGF1ZGVIb29rU2V0dGluZ3NQYXRoLFxuICBnZXRDb2RleENvbmZpZ1BhdGgsXG4gIGdldENvZGV4SG9va1NldHRpbmdzUGF0aCxcbiAgZ2V0Q3Vyc29ySG9va1NldHRpbmdzUGF0aCxcbiAgZ2V0R2VtaW5pSG9va1NldHRpbmdzUGF0aCxcbiAgZ2V0SG9va1NvdXJjZVBhdGgsXG4gIGdldEhvb2tXcmFwcGVyQmFzZW5hbWUsXG4gIGdldEhvb2tXcmFwcGVyUGF0aCxcbiAgZ2V0TWFuYWdlZEhvb2tBc3NldHMsXG4gIGdldFBlcm1pc3Npb25Ib29rTWFya2VyUGF0aCxcbiAgZ2V0UGVybWlzc2lvbkhvb2tTY3JpcHRQYXRoLFxuICBnZXRQcmltYXJ5SG9va1NjcmlwdFBhdGgsXG4gIGdldFZzQ29kZUhvb2tTZXR0aW5nc1BhdGgsXG4gIGdldFZzQ29kZVVzZXJTZXR0aW5nc1BhdGgsXG4gIGdldFdpbmRzdXJmSG9va1NldHRpbmdzUGF0aCxcbiAgaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0LFxuICBpc01pc3NpbmdGaWxlRXJyb3IsXG4gIG5vcm1hbGl6ZUhvb2tIb3N0LFxuICByZWFkT3B0aW9uYWxVdGY4LFxuICBzdXBwb3J0c01hbmFnZWRIb29rQXNzZXRzLFxuICB3cml0ZUJhY2t1cElmUHJlc2VudCxcbn0gZnJvbSAnLi9wZXJtaXNzaW9uSG9va1NoYXJlZC5qcyc7XG5cbmV4cG9ydCB7XG4gIGVuc3VyZUNsYXVkZVByZVRvb2xVc2VIb29rLFxuICBlbnN1cmVDb2RleFByZVRvb2xVc2VIb29rLFxuICBlbnN1cmVDdXJzb3JQcmVUb29sVXNlSG9vayxcbiAgZW5zdXJlR2VtaW5pQmVmb3JlVG9vbEhvb2ssXG4gIGVuc3VyZVZzQ29kZVByZVRvb2xVc2VIb29rLFxuICBlbnN1cmVXaW5kc3VyZkhvb2tzLFxuICBpbnN0YWxsUGVybWlzc2lvbkhvb2ssXG59IGZyb20gJy4vcGVybWlzc2lvbkhvb2tJbnN0YWxsZXJzLmpzJztcblxuZXhwb3J0IHtcbiAgX3Jlc2V0UGVybWlzc2lvbkhvb2tTdGFydHVwUmVwYWlyU3VtbWFyeUZvclRlc3RzLFxuICBnZXRMYXN0UGVybWlzc2lvbkhvb2tTdGFydHVwUmVwYWlyU3VtbWFyeSxcbiAgZ2V0UGVybWlzc2lvbkhvb2tBdWRpdFN1bW1hcnksXG4gIGdldFBlcm1pc3Npb25Ib29rU3RhdHVzLFxuICBnZXRQZXJtaXNzaW9uSG9va1N0YXR1c0FzeW5jLFxuICByZWNvbmNpbGVQZXJtaXNzaW9uSG9va1N0YXR1cyxcbiAgcmVwYWlyUGVybWlzc2lvbkhvb2tzT25TdGFydHVwLFxuICBzdW1tYXJpemVQZXJtaXNzaW9uSG9va0hlYWx0aCxcbn0gZnJvbSAnLi9wZXJtaXNzaW9uSG9va1N0YXR1cy5qcyc7XG4iXX0=