@dollhousemcp/mcp-server 2.0.16 → 2.0.17

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 (40) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md.backup +18 -0
  3. package/dist/elements/base/BaseElementManager.d.ts.map +1 -1
  4. package/dist/elements/base/BaseElementManager.js +17 -1
  5. package/dist/elements/memories/MemoryManager.d.ts.map +1 -1
  6. package/dist/elements/memories/MemoryManager.js +13 -2
  7. package/dist/generated/version.d.ts +2 -2
  8. package/dist/generated/version.js +3 -3
  9. package/dist/handlers/element-crud/createElement.d.ts.map +1 -1
  10. package/dist/handlers/element-crud/createElement.js +6 -2
  11. package/dist/handlers/element-crud/editElement.d.ts.map +1 -1
  12. package/dist/handlers/element-crud/editElement.js +6 -2
  13. package/dist/handlers/element-crud/helpers.d.ts +2 -0
  14. package/dist/handlers/element-crud/helpers.d.ts.map +1 -1
  15. package/dist/handlers/element-crud/helpers.js +21 -2
  16. package/dist/handlers/mcp-aql/IntrospectionResolver.d.ts.map +1 -1
  17. package/dist/handlers/mcp-aql/IntrospectionResolver.js +34 -7
  18. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
  19. package/dist/handlers/mcp-aql/MCPAQLHandler.js +19 -4
  20. package/dist/handlers/mcp-aql/OperationSchema.d.ts.map +1 -1
  21. package/dist/handlers/mcp-aql/OperationSchema.js +3 -2
  22. package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -1
  23. package/dist/handlers/mcp-aql/evaluatePermission.js +2 -1
  24. package/dist/handlers/mcp-aql/policies/ElementPolicies.d.ts +8 -0
  25. package/dist/handlers/mcp-aql/policies/ElementPolicies.d.ts.map +1 -1
  26. package/dist/handlers/mcp-aql/policies/ElementPolicies.js +26 -1
  27. package/dist/utils/permissionHooks.d.ts +39 -3
  28. package/dist/utils/permissionHooks.d.ts.map +1 -1
  29. package/dist/utils/permissionHooks.js +651 -74
  30. package/dist/web/public/permissions.js +38 -26
  31. package/dist/web/public/setup.js +367 -94
  32. package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
  33. package/dist/web/routes/permissionRoutes.js +32 -13
  34. package/dist/web/routes/setupRoutes.d.ts +1 -0
  35. package/dist/web/routes/setupRoutes.d.ts.map +1 -1
  36. package/dist/web/routes/setupRoutes.js +113 -41
  37. package/package.json +3 -1
  38. package/scripts/pretooluse-vscode.sh +163 -0
  39. package/scripts/pretooluse-windsurf.sh +166 -4
  40. package/server.json +2 -2
@@ -1,8 +1,10 @@
1
- import { accessSync, constants as fsConstants, copyFileSync, existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
2
- import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
1
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
2
+ import { access, chmod, copyFile, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
3
3
  import { dirname, join } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { homedir } from 'node:os';
5
+ import { homedir, platform } from 'node:os';
6
+ import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
7
+ import { logger } from './logger.js';
6
8
  function repoRootFromModule() {
7
9
  const currentFile = fileURLToPath(import.meta.url);
8
10
  return dirname(dirname(dirname(currentFile)));
@@ -30,36 +32,174 @@ function detectIndent(raw) {
30
32
  export function getPermissionHookScriptPath(homeDir = homedir()) {
31
33
  return join(homeDir, '.dollhouse', 'hooks', 'pretooluse-dollhouse.sh');
32
34
  }
33
- export function getPermissionHookMarkerPath(homeDir = homedir()) {
34
- return join(homeDir, '.dollhouse', 'run', 'hook-installed.json');
35
+ function getPermissionHookRunDir(homeDir = homedir()) {
36
+ return join(homeDir, '.dollhouse', 'run');
35
37
  }
36
- export function getClaudeHookSettingsPath(homeDir = homedir()) {
37
- return join(homeDir, '.claude', 'settings.json');
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 };
38
54
  }
39
- export function getPermissionHookStatus(homeDir = homedir()) {
40
- const markerPath = getPermissionHookMarkerPath(homeDir);
55
+ function collectHookMarkerPaths(homeDir) {
56
+ const markerPaths = new Set([getPermissionHookMarkerPath(homeDir)]);
57
+ const runDir = getPermissionHookRunDir(homeDir);
41
58
  try {
42
- const raw = readFileSync(markerPath, 'utf-8');
43
- const parsed = JSON.parse(raw);
44
- if (typeof parsed.host !== 'string' ||
45
- typeof parsed.scriptPath !== 'string' ||
46
- typeof parsed.settingsPath !== 'string') {
47
- return { installed: false };
59
+ for (const entry of readdirSync(runDir)) {
60
+ if (isHookMarkerFilename(entry)) {
61
+ markerPaths.add(join(runDir, entry));
62
+ }
48
63
  }
49
- if (!existsSync(parsed.scriptPath) || !existsSync(parsed.settingsPath)) {
50
- return { installed: false };
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
+ }
51
78
  }
52
- return {
53
- installed: true,
54
- host: parsed.host,
55
- scriptPath: parsed.scriptPath,
56
- settingsPath: parsed.settingsPath,
57
- };
58
79
  }
59
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
+ }
60
188
  return { installed: false };
61
189
  }
62
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
+ }
63
203
  function normalizeHooksRoot(parsed) {
64
204
  const hooksValue = parsed.hooks;
65
205
  if (!hooksValue || typeof hooksValue !== 'object' || Array.isArray(hooksValue)) {
@@ -67,12 +207,12 @@ function normalizeHooksRoot(parsed) {
67
207
  }
68
208
  return parsed.hooks;
69
209
  }
70
- export function ensureClaudePreToolUseHook(parsed, command) {
210
+ function ensureCommandHook(parsed, eventName, command, matcher, extraHookFields = {}) {
71
211
  const hooksRoot = normalizeHooksRoot(parsed);
72
- const existingEntries = Array.isArray(hooksRoot.PreToolUse)
73
- ? hooksRoot.PreToolUse.filter((entry) => typeof entry === 'object' && entry !== null)
212
+ const existingEntries = Array.isArray(hooksRoot[eventName])
213
+ ? hooksRoot[eventName].filter((entry) => typeof entry === 'object' && entry !== null)
74
214
  : [];
75
- hooksRoot.PreToolUse = existingEntries;
215
+ hooksRoot[eventName] = existingEntries;
76
216
  const commandExists = existingEntries.some((entry) => {
77
217
  const hooks = Array.isArray(entry?.hooks) ? entry.hooks : [];
78
218
  return hooks.some((hook) => hook?.type === 'command' && hook?.command === command);
@@ -80,28 +220,87 @@ export function ensureClaudePreToolUseHook(parsed, command) {
80
220
  if (commandExists) {
81
221
  return { changed: false, parsed };
82
222
  }
83
- const wildcardEntry = existingEntries.find((entry) => (entry?.matcher === '*' || entry?.matcher === undefined) && Array.isArray(entry?.hooks));
223
+ const wildcardEntry = existingEntries.find((entry) => (entry?.matcher === matcher || entry?.matcher === undefined) && Array.isArray(entry?.hooks));
84
224
  if (wildcardEntry) {
85
225
  const hooks = wildcardEntry.hooks;
86
226
  hooks.push({
87
227
  type: 'command',
88
228
  command,
229
+ ...extraHookFields,
89
230
  });
90
231
  }
91
232
  else {
92
233
  existingEntries.push({
93
- matcher: '*',
234
+ matcher,
94
235
  hooks: [
95
236
  {
96
237
  type: 'command',
97
238
  command,
239
+ ...extraHookFields,
98
240
  },
99
241
  ],
100
242
  });
101
243
  }
102
244
  return { changed: true, parsed };
103
245
  }
104
- async function copyHookScript(sourcePath, targetPath) {
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) {
105
304
  await mkdir(dirname(targetPath), { recursive: true });
106
305
  const sourceRaw = await readFile(sourcePath, 'utf-8');
107
306
  let targetRaw;
@@ -115,80 +314,458 @@ async function copyHookScript(sourcePath, targetPath) {
115
314
  }
116
315
  const changed = targetRaw === undefined || sourceRaw !== targetRaw;
117
316
  if (changed) {
118
- copyFileSync(sourcePath, targetPath);
317
+ await copyFile(sourcePath, targetPath);
119
318
  }
120
319
  else {
121
- accessSync(targetPath, fsConstants.F_OK);
320
+ await access(targetPath);
122
321
  }
123
322
  await chmod(targetPath, 0o755);
124
323
  return changed;
125
324
  }
126
- async function mergeClaudeSettings(settingsPath, command) {
127
- await mkdir(dirname(settingsPath), { recursive: true });
128
- let raw = '{}\n';
325
+ async function readOptionalUtf8(filePath, fallback) {
129
326
  try {
130
- raw = await readFile(settingsPath, 'utf-8');
327
+ return await readFile(filePath, 'utf-8');
131
328
  }
132
- catch {
133
- raw = '{}\n';
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;
134
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');
135
347
  const indent = detectIndent(raw);
136
348
  const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
137
349
  const { changed, parsed: updated } = ensureClaudePreToolUseHook(parsed, command);
138
350
  if (!changed) {
139
351
  return { changed: false };
140
352
  }
141
- let backupPath;
142
- if (existsSync(settingsPath)) {
143
- backupPath = `${settingsPath}.dollhouse.bak`;
144
- writeFileSync(backupPath, raw, 'utf-8');
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 };
145
365
  }
366
+ const backupPath = await writeBackupIfPresent(settingsPath, raw);
146
367
  await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
147
368
  return { changed: true, backupPath };
148
369
  }
149
- export async function installPermissionHook(client, options = {}) {
150
- const normalizedClient = client.normalize('NFC').trim().toLowerCase();
151
- if (normalizedClient !== 'claude-code') {
152
- return {
153
- supported: false,
154
- installed: false,
155
- configured: false,
156
- host: normalizedClient,
157
- message: `Automatic permission hook wiring is not yet supported for ${normalizedClient}.`,
158
- };
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 };
159
381
  }
160
- const homeDir = options.homeDir ?? homedir();
161
- const sourceScriptPath = options.sourceScriptPath
162
- ?? join(repoRootFromModule(), 'scripts', 'pretooluse-dollhouse.sh');
163
- const targetScriptPath = getPermissionHookScriptPath(homeDir);
164
- const settingsPath = getClaudeHookSettingsPath(homeDir);
165
- const markerPath = getPermissionHookMarkerPath(homeDir);
166
- const command = `bash ${targetScriptPath}`;
167
- const sourceStat = statSync(sourceScriptPath);
168
- if (!sourceStat.isFile()) {
169
- throw new Error(`Permission hook source script not found: ${sourceScriptPath}`);
170
- }
171
- await copyHookScript(sourceScriptPath, targetScriptPath);
172
- const settingsResult = await mergeClaudeSettings(settingsPath, command);
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);
173
526
  await mkdir(dirname(markerPath), { recursive: true });
174
- const installedAt = (options.now ?? new Date()).toISOString();
175
- const marker = {
176
- host: normalizedClient,
177
- scriptPath: targetScriptPath,
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 sharedTargetPath = getPermissionHookScriptPath(homeDir);
533
+ const sharedSourcePath = sourceScriptPath ?? join(repoRootFromModule(), 'scripts', 'pretooluse-dollhouse.sh');
534
+ const sharedStat = statSync(sharedSourcePath);
535
+ if (!sharedStat.isFile()) {
536
+ logger.warn(`[PermissionHooks] Shared hook bridge missing for ${normalizedClient}: ${sharedSourcePath}`);
537
+ throw new Error(`Permission hook source script not found: ${sharedSourcePath}`);
538
+ }
539
+ await copyHookAsset(sharedSourcePath, sharedTargetPath);
540
+ const wrapperTargetPath = getHookWrapperPath(normalizedClient, homeDir);
541
+ if (!wrapperTargetPath) {
542
+ return { scriptPath: sharedTargetPath };
543
+ }
544
+ const wrapperSourcePath = getHookSourcePath(normalizedClient);
545
+ const wrapperStat = statSync(wrapperSourcePath);
546
+ if (!wrapperStat.isFile()) {
547
+ logger.warn(`[PermissionHooks] Wrapper hook script missing for ${normalizedClient}: ${wrapperSourcePath}`);
548
+ throw new Error(`Permission hook wrapper script not found: ${wrapperSourcePath}`);
549
+ }
550
+ await copyHookAsset(wrapperSourcePath, wrapperTargetPath);
551
+ return { scriptPath: wrapperTargetPath };
552
+ }
553
+ async function installClaudeCodePermissionHook(homeDir, installedAt, sourceScriptPath) {
554
+ const host = 'claude-code';
555
+ const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
556
+ const settingsPath = getClaudeHookSettingsPath(homeDir);
557
+ const settingsResult = await mergeClaudeSettings(settingsPath, `bash ${scriptPath}`);
558
+ const markerPath = await writeHookMarker(homeDir, {
559
+ host,
560
+ scriptPath,
178
561
  settingsPath,
562
+ configured: true,
563
+ assetsPrepared: true,
179
564
  installedAt,
180
- };
181
- await writeFile(markerPath, JSON.stringify(marker, null, 2) + '\n', 'utf-8');
565
+ });
182
566
  return {
183
567
  supported: true,
184
568
  installed: true,
185
569
  configured: true,
186
- host: normalizedClient,
187
- scriptPath: targetScriptPath,
570
+ assetsPrepared: true,
571
+ host,
572
+ scriptPath,
188
573
  settingsPath,
189
574
  markerPath,
190
575
  backupPath: settingsResult.backupPath,
191
576
  message: 'Installed Claude Code permission hook and updated settings.json.',
192
577
  };
193
578
  }
194
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvbkhvb2tzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3Blcm1pc3Npb25Ib29rcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsSUFBSSxXQUFXLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNoSSxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDckUsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDMUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBa0NsQyxTQUFTLGtCQUFrQjtJQUN6QixNQUFNLFdBQVcsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuRCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBRUQsU0FBUyxrQkFBa0IsQ0FBQyxLQUFjO0lBQ3hDLE9BQU8sT0FBTyxDQUNaLEtBQUs7V0FDRixPQUFPLEtBQUssS0FBSyxRQUFRO1dBQ3pCLE1BQU0sSUFBSSxLQUFLO1dBQ2QsS0FBMkIsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUNsRCxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLEdBQVc7SUFDL0IsS0FBSyxNQUFNLElBQUksSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDbkMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDO1lBQUUsU0FBUztRQUNoRixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDdkMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDekIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsTUFBTSxDQUFDO1lBQ3JELElBQUksTUFBTSxJQUFJLENBQUM7Z0JBQUUsT0FBTyxNQUFNLENBQUM7UUFDakMsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFRCxNQUFNLFVBQVUsMkJBQTJCLENBQUMsT0FBTyxHQUFHLE9BQU8sRUFBRTtJQUM3RCxPQUFPLElBQUksQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSx5QkFBeUIsQ0FBQyxDQUFDO0FBQ3pFLENBQUM7QUFFRCxNQUFNLFVBQVUsMkJBQTJCLENBQUMsT0FBTyxHQUFHLE9BQU8sRUFBRTtJQUM3RCxPQUFPLElBQUksQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO0FBQ25FLENBQUM7QUFFRCxNQUFNLFVBQVUseUJBQXlCLENBQUMsT0FBTyxHQUFHLE9BQU8sRUFBRTtJQUMzRCxPQUFPLElBQUksQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFFRCxNQUFNLFVBQVUsdUJBQXVCLENBQUMsT0FBTyxHQUFHLE9BQU8sRUFBRTtJQUN6RCxNQUFNLFVBQVUsR0FBRywyQkFBMkIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4RCxJQUFJLENBQUM7UUFDSCxNQUFNLEdBQUcsR0FBRyxZQUFZLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzlDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUF5QixDQUFDO1FBQ3ZELElBQ0UsT0FBTyxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVE7WUFDL0IsT0FBTyxNQUFNLENBQUMsVUFBVSxLQUFLLFFBQVE7WUFDckMsT0FBTyxNQUFNLENBQUMsWUFBWSxLQUFLLFFBQVEsRUFDdkMsQ0FBQztZQUNELE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDOUIsQ0FBQztRQUVELElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQ3ZFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDOUIsQ0FBQztRQUVELE9BQU87WUFDTCxTQUFTLEVBQUUsSUFBSTtZQUNmLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtZQUNqQixVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVU7WUFDN0IsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFZO1NBQ2xDLENBQUM7SUFDSixDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUM5QixDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsa0JBQWtCLENBQUMsTUFBK0I7SUFDekQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQztJQUNoQyxJQUFJLENBQUMsVUFBVSxJQUFJLE9BQU8sVUFBVSxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDL0UsTUFBTSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLEtBQWtDLENBQUM7QUFDbkQsQ0FBQztBQUVELE1BQU0sVUFBVSwwQkFBMEIsQ0FDeEMsTUFBK0IsRUFDL0IsT0FBZTtJQUVmLE1BQU0sU0FBUyxHQUFHLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdDLE1BQU0sZUFBZSxHQUFtQyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUM7UUFDekYsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFvQyxFQUFFLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxJQUFJLENBQUM7UUFDdkgsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNQLFNBQVMsQ0FBQyxVQUFVLEdBQUcsZUFBZSxDQUFDO0lBRXZDLE1BQU0sYUFBYSxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtRQUNuRCxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQXVDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMvRixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksRUFBRSxJQUFJLEtBQUssU0FBUyxJQUFJLElBQUksRUFBRSxPQUFPLEtBQUssT0FBTyxDQUFDLENBQUM7SUFDckYsQ0FBQyxDQUFDLENBQUM7SUFDSCxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQ2xCLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLGFBQWEsR0FBRyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFvQyxFQUFFLENBQ3JGLENBQUMsS0FBSyxFQUFFLE9BQU8sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLE9BQU8sS0FBSyxTQUFTLENBQUMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FDeEYsQ0FBQztJQUVGLElBQUksYUFBYSxFQUFFLENBQUM7UUFDbEIsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLEtBQXVDLENBQUM7UUFDcEUsS0FBSyxDQUFDLElBQUksQ0FBQztZQUNULElBQUksRUFBRSxTQUFTO1lBQ2YsT0FBTztTQUNSLENBQUMsQ0FBQztJQUNMLENBQUM7U0FBTSxDQUFDO1FBQ04sZUFBZSxDQUFDLElBQUksQ0FBQztZQUNuQixPQUFPLEVBQUUsR0FBRztZQUNaLEtBQUssRUFBRTtnQkFDTDtvQkFDRSxJQUFJLEVBQUUsU0FBUztvQkFDZixPQUFPO2lCQUNSO2FBQ0Y7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7QUFDbkMsQ0FBQztBQUVELEtBQUssVUFBVSxjQUFjLENBQUMsVUFBa0IsRUFBRSxVQUFrQjtJQUNsRSxNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUV0RCxNQUFNLFNBQVMsR0FBRyxNQUFNLFFBQVEsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFFdEQsSUFBSSxTQUE2QixDQUFDO0lBQ2xDLElBQUksQ0FBQztRQUNILFNBQVMsR0FBRyxNQUFNLFFBQVEsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixJQUFJLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUMvQixNQUFNLEtBQUssQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDO0lBQ0QsTUFBTSxPQUFPLEdBQUcsU0FBUyxLQUFLLFNBQVMsSUFBSSxTQUFTLEtBQUssU0FBUyxDQUFDO0lBRW5FLElBQUksT0FBTyxFQUFFLENBQUM7UUFDWixZQUFZLENBQUMsVUFBVSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7U0FBTSxDQUFDO1FBQ04sVUFBVSxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELE1BQU0sS0FBSyxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvQixPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQsS0FBSyxVQUFVLG1CQUFtQixDQUFDLFlBQW9CLEVBQUUsT0FBZTtJQUN0RSxNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUV4RCxJQUFJLEdBQUcsR0FBRyxNQUFNLENBQUM7SUFDakIsSUFBSSxDQUFDO1FBQ0gsR0FBRyxHQUFHLE1BQU0sUUFBUSxDQUFDLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsR0FBRyxHQUFHLE1BQU0sQ0FBQztJQUNmLENBQUM7SUFFRCxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQTRCLENBQUM7SUFDekYsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsMEJBQTBCLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ2pGLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVELElBQUksVUFBOEIsQ0FBQztJQUNuQyxJQUFJLFVBQVUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1FBQzdCLFVBQVUsR0FBRyxHQUFHLFlBQVksZ0JBQWdCLENBQUM7UUFDN0MsYUFBYSxDQUFDLFVBQVUsRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVELE1BQU0sU0FBUyxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLEdBQUcsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3JGLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxDQUFDO0FBQ3ZDLENBQUM7QUFFRCxNQUFNLENBQUMsS0FBSyxVQUFVLHFCQUFxQixDQUN6QyxNQUFjLEVBQ2QsVUFBd0MsRUFBRTtJQUUxQyxNQUFNLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDdEUsSUFBSSxnQkFBZ0IsS0FBSyxhQUFhLEVBQUUsQ0FBQztRQUN2QyxPQUFPO1lBQ0wsU0FBUyxFQUFFLEtBQUs7WUFDaEIsU0FBUyxFQUFFLEtBQUs7WUFDaEIsVUFBVSxFQUFFLEtBQUs7WUFDakIsSUFBSSxFQUFFLGdCQUFnQjtZQUN0QixPQUFPLEVBQUUsNkRBQTZELGdCQUFnQixHQUFHO1NBQzFGLENBQUM7SUFDSixDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sSUFBSSxPQUFPLEVBQUUsQ0FBQztJQUM3QyxNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxnQkFBZ0I7V0FDNUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLEVBQUUsU0FBUyxFQUFFLHlCQUF5QixDQUFDLENBQUM7SUFDdEUsTUFBTSxnQkFBZ0IsR0FBRywyQkFBMkIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM5RCxNQUFNLFlBQVksR0FBRyx5QkFBeUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4RCxNQUFNLFVBQVUsR0FBRywyQkFBMkIsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4RCxNQUFNLE9BQU8sR0FBRyxRQUFRLGdCQUFnQixFQUFFLENBQUM7SUFFM0MsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDOUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sSUFBSSxLQUFLLENBQUMsNENBQTRDLGdCQUFnQixFQUFFLENBQUMsQ0FBQztJQUNsRixDQUFDO0lBRUQsTUFBTSxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUN6RCxNQUFNLGNBQWMsR0FBRyxNQUFNLG1CQUFtQixDQUFDLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUV4RSxNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0RCxNQUFNLFdBQVcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLElBQUksSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzlELE1BQU0sTUFBTSxHQUF5QjtRQUNuQyxJQUFJLEVBQUUsZ0JBQWdCO1FBQ3RCLFVBQVUsRUFBRSxnQkFBZ0I7UUFDNUIsWUFBWTtRQUNaLFdBQVc7S0FDWixDQUFDO0lBQ0YsTUFBTSxTQUFTLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFFN0UsT0FBTztRQUNMLFNBQVMsRUFBRSxJQUFJO1FBQ2YsU0FBUyxFQUFFLElBQUk7UUFDZixVQUFVLEVBQUUsSUFBSTtRQUNoQixJQUFJLEVBQUUsZ0JBQWdCO1FBQ3RCLFVBQVUsRUFBRSxnQkFBZ0I7UUFDNUIsWUFBWTtRQUNaLFVBQVU7UUFDVixVQUFVLEVBQUUsY0FBYyxDQUFDLFVBQVU7UUFDckMsT0FBTyxFQUFFLGtFQUFrRTtLQUM1RSxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGFjY2Vzc1N5bmMsIGNvbnN0YW50cyBhcyBmc0NvbnN0YW50cywgY29weUZpbGVTeW5jLCBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMsIHN0YXRTeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBjaG1vZCwgbWtkaXIsIHJlYWRGaWxlLCB3cml0ZUZpbGUgfSBmcm9tICdub2RlOmZzL3Byb21pc2VzJztcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4gfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ25vZGU6dXJsJztcbmltcG9ydCB7IGhvbWVkaXIgfSBmcm9tICdub2RlOm9zJztcblxuZXhwb3J0IGludGVyZmFjZSBQZXJtaXNzaW9uSG9va01hcmtlciB7XG4gIGhvc3Q6IHN0cmluZztcbiAgc2NyaXB0UGF0aDogc3RyaW5nO1xuICBzZXR0aW5nc1BhdGg6IHN0cmluZztcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQZXJtaXNzaW9uSG9va1N0YXR1cyB7XG4gIGluc3RhbGxlZDogYm9vbGVhbjtcbiAgaG9zdD86IHN0cmluZztcbiAgc2NyaXB0UGF0aD86IHN0cmluZztcbiAgc2V0dGluZ3NQYXRoPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdCB7XG4gIHN1cHBvcnRlZDogYm9vbGVhbjtcbiAgaW5zdGFsbGVkOiBib29sZWFuO1xuICBjb25maWd1cmVkOiBib29sZWFuO1xuICBob3N0OiBzdHJpbmc7XG4gIHNjcmlwdFBhdGg/OiBzdHJpbmc7XG4gIHNldHRpbmdzUGF0aD86IHN0cmluZztcbiAgbWFya2VyUGF0aD86IHN0cmluZztcbiAgYmFja3VwUGF0aD86IHN0cmluZztcbiAgbWVzc2FnZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEluc3RhbGxQZXJtaXNzaW9uSG9va09wdGlvbnMge1xuICBob21lRGlyPzogc3RyaW5nO1xuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nO1xuICBub3c/OiBEYXRlO1xufVxuXG5mdW5jdGlvbiByZXBvUm9vdEZyb21Nb2R1bGUoKTogc3RyaW5nIHtcbiAgY29uc3QgY3VycmVudEZpbGUgPSBmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCk7XG4gIHJldHVybiBkaXJuYW1lKGRpcm5hbWUoZGlybmFtZShjdXJyZW50RmlsZSkpKTtcbn1cblxuZnVuY3Rpb24gaXNNaXNzaW5nRmlsZUVycm9yKGVycm9yOiB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiBCb29sZWFuKFxuICAgIGVycm9yXG4gICAgJiYgdHlwZW9mIGVycm9yID09PSAnb2JqZWN0J1xuICAgICYmICdjb2RlJyBpbiBlcnJvclxuICAgICYmIChlcnJvciBhcyB7IGNvZGU/OiBzdHJpbmcgfSkuY29kZSA9PT0gJ0VOT0VOVCcsXG4gICk7XG59XG5cbmZ1bmN0aW9uIGRldGVjdEluZGVudChyYXc6IHN0cmluZyk6IG51bWJlciB8IHN0cmluZyB7XG4gIGZvciAoY29uc3QgbGluZSBvZiByYXcuc3BsaXQoJ1xcbicpKSB7XG4gICAgaWYgKGxpbmUubGVuZ3RoID09PSAwIHx8IGxpbmUuc3RhcnRzV2l0aCgneycpIHx8IGxpbmUuc3RhcnRzV2l0aCgnfScpKSBjb250aW51ZTtcbiAgICBpZiAobGluZS5zdGFydHNXaXRoKCdcXHQnKSkgcmV0dXJuICdcXHQnO1xuICAgIGlmIChsaW5lLnN0YXJ0c1dpdGgoJyAnKSkge1xuICAgICAgY29uc3Qgc3BhY2VzID0gbGluZS5sZW5ndGggLSBsaW5lLnRyaW1TdGFydCgpLmxlbmd0aDtcbiAgICAgIGlmIChzcGFjZXMgPj0gMikgcmV0dXJuIHNwYWNlcztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIDI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQZXJtaXNzaW9uSG9va1NjcmlwdFBhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuZG9sbGhvdXNlJywgJ2hvb2tzJywgJ3ByZXRvb2x1c2UtZG9sbGhvdXNlLnNoJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQZXJtaXNzaW9uSG9va01hcmtlclBhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuZG9sbGhvdXNlJywgJ3J1bicsICdob29rLWluc3RhbGxlZC5qc29uJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDbGF1ZGVIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIgPSBob21lZGlyKCkpOiBzdHJpbmcge1xuICByZXR1cm4gam9pbihob21lRGlyLCAnLmNsYXVkZScsICdzZXR0aW5ncy5qc29uJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQZXJtaXNzaW9uSG9va1N0YXR1cyhob21lRGlyID0gaG9tZWRpcigpKTogUGVybWlzc2lvbkhvb2tTdGF0dXMge1xuICBjb25zdCBtYXJrZXJQYXRoID0gZ2V0UGVybWlzc2lvbkhvb2tNYXJrZXJQYXRoKGhvbWVEaXIpO1xuICB0cnkge1xuICAgIGNvbnN0IHJhdyA9IHJlYWRGaWxlU3luYyhtYXJrZXJQYXRoLCAndXRmLTgnKTtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHJhdykgYXMgUGVybWlzc2lvbkhvb2tNYXJrZXI7XG4gICAgaWYgKFxuICAgICAgdHlwZW9mIHBhcnNlZC5ob3N0ICE9PSAnc3RyaW5nJyB8fFxuICAgICAgdHlwZW9mIHBhcnNlZC5zY3JpcHRQYXRoICE9PSAnc3RyaW5nJyB8fFxuICAgICAgdHlwZW9mIHBhcnNlZC5zZXR0aW5nc1BhdGggIT09ICdzdHJpbmcnXG4gICAgKSB7XG4gICAgICByZXR1cm4geyBpbnN0YWxsZWQ6IGZhbHNlIH07XG4gICAgfVxuXG4gICAgaWYgKCFleGlzdHNTeW5jKHBhcnNlZC5zY3JpcHRQYXRoKSB8fCAhZXhpc3RzU3luYyhwYXJzZWQuc2V0dGluZ3NQYXRoKSkge1xuICAgICAgcmV0dXJuIHsgaW5zdGFsbGVkOiBmYWxzZSB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgICBob3N0OiBwYXJzZWQuaG9zdCxcbiAgICAgIHNjcmlwdFBhdGg6IHBhcnNlZC5zY3JpcHRQYXRoLFxuICAgICAgc2V0dGluZ3NQYXRoOiBwYXJzZWQuc2V0dGluZ3NQYXRoLFxuICAgIH07XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB7IGluc3RhbGxlZDogZmFsc2UgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVIb29rc1Jvb3QocGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFJlY29yZDxzdHJpbmcsIHVua25vd25bXT4ge1xuICBjb25zdCBob29rc1ZhbHVlID0gcGFyc2VkLmhvb2tzO1xuICBpZiAoIWhvb2tzVmFsdWUgfHwgdHlwZW9mIGhvb2tzVmFsdWUgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkoaG9va3NWYWx1ZSkpIHtcbiAgICBwYXJzZWQuaG9va3MgPSB7fTtcbiAgfVxuICByZXR1cm4gcGFyc2VkLmhvb2tzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd25bXT47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVDbGF1ZGVQcmVUb29sVXNlSG9vayhcbiAgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgY29tbWFuZDogc3RyaW5nLFxuKTogeyBjaGFuZ2VkOiBib29sZWFuOyBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0ge1xuICBjb25zdCBob29rc1Jvb3QgPSBub3JtYWxpemVIb29rc1Jvb3QocGFyc2VkKTtcbiAgY29uc3QgZXhpc3RpbmdFbnRyaWVzOiBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gPSBBcnJheS5pc0FycmF5KGhvb2tzUm9vdC5QcmVUb29sVXNlKVxuICAgID8gaG9va3NSb290LlByZVRvb2xVc2UuZmlsdGVyKChlbnRyeSk6IGVudHJ5IGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+IHR5cGVvZiBlbnRyeSA9PT0gJ29iamVjdCcgJiYgZW50cnkgIT09IG51bGwpXG4gICAgOiBbXTtcbiAgaG9va3NSb290LlByZVRvb2xVc2UgPSBleGlzdGluZ0VudHJpZXM7XG5cbiAgY29uc3QgY29tbWFuZEV4aXN0cyA9IGV4aXN0aW5nRW50cmllcy5zb21lKChlbnRyeSkgPT4ge1xuICAgIGNvbnN0IGhvb2tzID0gQXJyYXkuaXNBcnJheShlbnRyeT8uaG9va3MpID8gZW50cnkuaG9va3MgYXMgQXJyYXk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+IDogW107XG4gICAgcmV0dXJuIGhvb2tzLnNvbWUoKGhvb2spID0+IGhvb2s/LnR5cGUgPT09ICdjb21tYW5kJyAmJiBob29rPy5jb21tYW5kID09PSBjb21tYW5kKTtcbiAgfSk7XG4gIGlmIChjb21tYW5kRXhpc3RzKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UsIHBhcnNlZCB9O1xuICB9XG5cbiAgY29uc3Qgd2lsZGNhcmRFbnRyeSA9IGV4aXN0aW5nRW50cmllcy5maW5kKChlbnRyeSk6IGVudHJ5IGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+XG4gICAgKGVudHJ5Py5tYXRjaGVyID09PSAnKicgfHwgZW50cnk/Lm1hdGNoZXIgPT09IHVuZGVmaW5lZCkgJiYgQXJyYXkuaXNBcnJheShlbnRyeT8uaG9va3MpLFxuICApO1xuXG4gIGlmICh3aWxkY2FyZEVudHJ5KSB7XG4gICAgY29uc3QgaG9va3MgPSB3aWxkY2FyZEVudHJ5Lmhvb2tzIGFzIEFycmF5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PjtcbiAgICBob29rcy5wdXNoKHtcbiAgICAgIHR5cGU6ICdjb21tYW5kJyxcbiAgICAgIGNvbW1hbmQsXG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgZXhpc3RpbmdFbnRyaWVzLnB1c2goe1xuICAgICAgbWF0Y2hlcjogJyonLFxuICAgICAgaG9va3M6IFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6ICdjb21tYW5kJyxcbiAgICAgICAgICBjb21tYW5kLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIHBhcnNlZCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBjb3B5SG9va1NjcmlwdChzb3VyY2VQYXRoOiBzdHJpbmcsIHRhcmdldFBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBhd2FpdCBta2RpcihkaXJuYW1lKHRhcmdldFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCBzb3VyY2VSYXcgPSBhd2FpdCByZWFkRmlsZShzb3VyY2VQYXRoLCAndXRmLTgnKTtcblxuICBsZXQgdGFyZ2V0UmF3OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHRyeSB7XG4gICAgdGFyZ2V0UmF3ID0gYXdhaXQgcmVhZEZpbGUodGFyZ2V0UGF0aCwgJ3V0Zi04Jyk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKCFpc01pc3NpbmdGaWxlRXJyb3IoZXJyb3IpKSB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cbiAgY29uc3QgY2hhbmdlZCA9IHRhcmdldFJhdyA9PT0gdW5kZWZpbmVkIHx8IHNvdXJjZVJhdyAhPT0gdGFyZ2V0UmF3O1xuXG4gIGlmIChjaGFuZ2VkKSB7XG4gICAgY29weUZpbGVTeW5jKHNvdXJjZVBhdGgsIHRhcmdldFBhdGgpO1xuICB9IGVsc2Uge1xuICAgIGFjY2Vzc1N5bmModGFyZ2V0UGF0aCwgZnNDb25zdGFudHMuRl9PSyk7XG4gIH1cblxuICBhd2FpdCBjaG1vZCh0YXJnZXRQYXRoLCAwbzc1NSk7XG4gIHJldHVybiBjaGFuZ2VkO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUNsYXVkZVNldHRpbmdzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgbGV0IHJhdyA9ICd7fVxcbic7XG4gIHRyeSB7XG4gICAgcmF3ID0gYXdhaXQgcmVhZEZpbGUoc2V0dGluZ3NQYXRoLCAndXRmLTgnKTtcbiAgfSBjYXRjaCB7XG4gICAgcmF3ID0gJ3t9XFxuJztcbiAgfVxuXG4gIGNvbnN0IGluZGVudCA9IGRldGVjdEluZGVudChyYXcpO1xuICBjb25zdCBwYXJzZWQgPSByYXcudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHt9IDogSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IGNoYW5nZWQsIHBhcnNlZDogdXBkYXRlZCB9ID0gZW5zdXJlQ2xhdWRlUHJlVG9vbFVzZUhvb2socGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGxldCBiYWNrdXBQYXRoOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGlmIChleGlzdHNTeW5jKHNldHRpbmdzUGF0aCkpIHtcbiAgICBiYWNrdXBQYXRoID0gYCR7c2V0dGluZ3NQYXRofS5kb2xsaG91c2UuYmFrYDtcbiAgICB3cml0ZUZpbGVTeW5jKGJhY2t1cFBhdGgsIHJhdywgJ3V0Zi04Jyk7XG4gIH1cblxuICBhd2FpdCB3cml0ZUZpbGUoc2V0dGluZ3NQYXRoLCBKU09OLnN0cmluZ2lmeSh1cGRhdGVkLCBudWxsLCBpbmRlbnQpICsgJ1xcbicsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsUGVybWlzc2lvbkhvb2soXG4gIGNsaWVudDogc3RyaW5nLFxuICBvcHRpb25zOiBJbnN0YWxsUGVybWlzc2lvbkhvb2tPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCBub3JtYWxpemVkQ2xpZW50ID0gY2xpZW50Lm5vcm1hbGl6ZSgnTkZDJykudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gIGlmIChub3JtYWxpemVkQ2xpZW50ICE9PSAnY2xhdWRlLWNvZGUnKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1cHBvcnRlZDogZmFsc2UsXG4gICAgICBpbnN0YWxsZWQ6IGZhbHNlLFxuICAgICAgY29uZmlndXJlZDogZmFsc2UsXG4gICAgICBob3N0OiBub3JtYWxpemVkQ2xpZW50LFxuICAgICAgbWVzc2FnZTogYEF1dG9tYXRpYyBwZXJtaXNzaW9uIGhvb2sgd2lyaW5nIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciAke25vcm1hbGl6ZWRDbGllbnR9LmAsXG4gICAgfTtcbiAgfVxuXG4gIGNvbnN0IGhvbWVEaXIgPSBvcHRpb25zLmhvbWVEaXIgPz8gaG9tZWRpcigpO1xuICBjb25zdCBzb3VyY2VTY3JpcHRQYXRoID0gb3B0aW9ucy5zb3VyY2VTY3JpcHRQYXRoXG4gICAgPz8gam9pbihyZXBvUm9vdEZyb21Nb2R1bGUoKSwgJ3NjcmlwdHMnLCAncHJldG9vbHVzZS1kb2xsaG91c2Uuc2gnKTtcbiAgY29uc3QgdGFyZ2V0U2NyaXB0UGF0aCA9IGdldFBlcm1pc3Npb25Ib29rU2NyaXB0UGF0aChob21lRGlyKTtcbiAgY29uc3Qgc2V0dGluZ3NQYXRoID0gZ2V0Q2xhdWRlSG9va1NldHRpbmdzUGF0aChob21lRGlyKTtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGdldFBlcm1pc3Npb25Ib29rTWFya2VyUGF0aChob21lRGlyKTtcbiAgY29uc3QgY29tbWFuZCA9IGBiYXNoICR7dGFyZ2V0U2NyaXB0UGF0aH1gO1xuXG4gIGNvbnN0IHNvdXJjZVN0YXQgPSBzdGF0U3luYyhzb3VyY2VTY3JpcHRQYXRoKTtcbiAgaWYgKCFzb3VyY2VTdGF0LmlzRmlsZSgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBQZXJtaXNzaW9uIGhvb2sgc291cmNlIHNjcmlwdCBub3QgZm91bmQ6ICR7c291cmNlU2NyaXB0UGF0aH1gKTtcbiAgfVxuXG4gIGF3YWl0IGNvcHlIb29rU2NyaXB0KHNvdXJjZVNjcmlwdFBhdGgsIHRhcmdldFNjcmlwdFBhdGgpO1xuICBjb25zdCBzZXR0aW5nc1Jlc3VsdCA9IGF3YWl0IG1lcmdlQ2xhdWRlU2V0dGluZ3Moc2V0dGluZ3NQYXRoLCBjb21tYW5kKTtcblxuICBhd2FpdCBta2RpcihkaXJuYW1lKG1hcmtlclBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgY29uc3QgaW5zdGFsbGVkQXQgPSAob3B0aW9ucy5ub3cgPz8gbmV3IERhdGUoKSkudG9JU09TdHJpbmcoKTtcbiAgY29uc3QgbWFya2VyOiBQZXJtaXNzaW9uSG9va01hcmtlciA9IHtcbiAgICBob3N0OiBub3JtYWxpemVkQ2xpZW50LFxuICAgIHNjcmlwdFBhdGg6IHRhcmdldFNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGluc3RhbGxlZEF0LFxuICB9O1xuICBhd2FpdCB3cml0ZUZpbGUobWFya2VyUGF0aCwgSlNPTi5zdHJpbmdpZnkobWFya2VyLCBudWxsLCAyKSArICdcXG4nLCAndXRmLTgnKTtcblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBob3N0OiBub3JtYWxpemVkQ2xpZW50LFxuICAgIHNjcmlwdFBhdGg6IHRhcmdldFNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIG1hcmtlclBhdGgsXG4gICAgYmFja3VwUGF0aDogc2V0dGluZ3NSZXN1bHQuYmFja3VwUGF0aCxcbiAgICBtZXNzYWdlOiAnSW5zdGFsbGVkIENsYXVkZSBDb2RlIHBlcm1pc3Npb24gaG9vayBhbmQgdXBkYXRlZCBzZXR0aW5ncy5qc29uLicsXG4gIH07XG59XG4iXX0=
579
+ async function installVsCodePermissionHook(homeDir, installedAt, sourceScriptPath) {
580
+ const host = 'vscode';
581
+ const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
582
+ const settingsPath = getVsCodeHookSettingsPath(homeDir);
583
+ const userSettingsPath = getVsCodeUserSettingsPath(homeDir);
584
+ const hookResult = await mergeVsCodeHookSettings(settingsPath, `bash ${scriptPath}`);
585
+ const userSettingsResult = await mergeVsCodeUserSettings(userSettingsPath);
586
+ const markerPath = await writeHookMarker(homeDir, {
587
+ host,
588
+ scriptPath,
589
+ settingsPath,
590
+ additionalPaths: [userSettingsPath],
591
+ configured: true,
592
+ assetsPrepared: true,
593
+ installedAt,
594
+ });
595
+ return {
596
+ supported: true,
597
+ installed: true,
598
+ configured: true,
599
+ assetsPrepared: true,
600
+ host,
601
+ scriptPath,
602
+ settingsPath,
603
+ additionalPaths: [userSettingsPath],
604
+ markerPath,
605
+ backupPath: hookResult.backupPath ?? userSettingsResult.backupPath,
606
+ message: 'Installed VS Code permission hook and enabled chat.hookFilesLocations for ~/.copilot/hooks.',
607
+ };
608
+ }
609
+ async function installGeminiCliPermissionHook(homeDir, installedAt, sourceScriptPath) {
610
+ const host = 'gemini-cli';
611
+ const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
612
+ const settingsPath = getGeminiHookSettingsPath(homeDir);
613
+ const settingsResult = await mergeGeminiSettings(settingsPath, `bash ${scriptPath}`);
614
+ const markerPath = await writeHookMarker(homeDir, {
615
+ host,
616
+ scriptPath,
617
+ settingsPath,
618
+ configured: true,
619
+ assetsPrepared: true,
620
+ installedAt,
621
+ });
622
+ return {
623
+ supported: true,
624
+ installed: true,
625
+ configured: true,
626
+ assetsPrepared: true,
627
+ host,
628
+ scriptPath,
629
+ settingsPath,
630
+ markerPath,
631
+ backupPath: settingsResult.backupPath,
632
+ message: 'Installed Gemini CLI permission hook and updated settings.json.',
633
+ };
634
+ }
635
+ async function installCursorPermissionHook(homeDir, installedAt, sourceScriptPath) {
636
+ const host = 'cursor';
637
+ const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
638
+ const settingsPath = getCursorHookSettingsPath(homeDir);
639
+ const settingsResult = await mergeCursorHooks(settingsPath, `bash ${scriptPath}`);
640
+ const markerPath = await writeHookMarker(homeDir, {
641
+ host,
642
+ scriptPath,
643
+ settingsPath,
644
+ configured: true,
645
+ assetsPrepared: true,
646
+ installedAt,
647
+ });
648
+ return {
649
+ supported: true,
650
+ installed: true,
651
+ configured: true,
652
+ assetsPrepared: true,
653
+ host,
654
+ scriptPath,
655
+ settingsPath,
656
+ markerPath,
657
+ backupPath: settingsResult.backupPath,
658
+ message: 'Installed Cursor permission hook and updated hooks.json.',
659
+ };
660
+ }
661
+ async function installWindsurfPermissionHook(homeDir, installedAt, sourceScriptPath) {
662
+ const host = 'windsurf';
663
+ const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
664
+ const settingsPath = getWindsurfHookSettingsPath(homeDir);
665
+ const settingsResult = await mergeWindsurfHooks(settingsPath, `bash ${scriptPath}`);
666
+ const markerPath = await writeHookMarker(homeDir, {
667
+ host,
668
+ scriptPath,
669
+ settingsPath,
670
+ configured: true,
671
+ assetsPrepared: true,
672
+ installedAt,
673
+ });
674
+ return {
675
+ supported: true,
676
+ installed: true,
677
+ configured: true,
678
+ assetsPrepared: true,
679
+ host,
680
+ scriptPath,
681
+ settingsPath,
682
+ markerPath,
683
+ backupPath: settingsResult.backupPath,
684
+ message: 'Installed Windsurf permission hooks and updated hooks.json.',
685
+ };
686
+ }
687
+ async function installCodexPermissionHook(homeDir, installedAt, sourceScriptPath) {
688
+ const host = 'codex';
689
+ const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
690
+ const settingsPath = getCodexHookSettingsPath(homeDir);
691
+ const configPath = getCodexConfigPath(homeDir);
692
+ const hooksResult = await mergeCodexHooks(settingsPath, `bash ${scriptPath}`);
693
+ const configResult = await mergeCodexConfig(configPath);
694
+ const markerPath = await writeHookMarker(homeDir, {
695
+ host,
696
+ scriptPath,
697
+ settingsPath,
698
+ additionalPaths: [configPath],
699
+ configured: true,
700
+ assetsPrepared: true,
701
+ installedAt,
702
+ });
703
+ return {
704
+ supported: true,
705
+ installed: true,
706
+ configured: true,
707
+ assetsPrepared: true,
708
+ host,
709
+ scriptPath,
710
+ settingsPath,
711
+ additionalPaths: [configPath],
712
+ markerPath,
713
+ backupPath: hooksResult.backupPath ?? configResult.backupPath,
714
+ message: 'Installed Codex Bash permission hook, created hooks.json, and enabled features.codex_hooks in config.toml.',
715
+ };
716
+ }
717
+ async function installManualPermissionHookAssets(normalizedClient, homeDir, installedAt, sourceScriptPath) {
718
+ const { scriptPath } = await installHookAssetsForHost(normalizedClient, homeDir, sourceScriptPath);
719
+ const markerPath = await writeHookMarker(homeDir, {
720
+ host: normalizedClient,
721
+ scriptPath,
722
+ settingsPath: undefined,
723
+ configured: false,
724
+ assetsPrepared: true,
725
+ installedAt,
726
+ });
727
+ return {
728
+ supported: true,
729
+ installed: true,
730
+ configured: false,
731
+ assetsPrepared: true,
732
+ host: normalizedClient,
733
+ scriptPath,
734
+ markerPath,
735
+ message: `Installed Dollhouse permission hook assets for ${normalizedClient}. Finish the client-specific hook registration manually.`,
736
+ };
737
+ }
738
+ export async function installPermissionHook(client, options = {}) {
739
+ const normalizedClient = normalizeHookHost(client);
740
+ const homeDir = options.homeDir ?? homedir();
741
+ const installedAt = (options.now ?? new Date()).toISOString();
742
+ if (normalizedClient === 'claude-code') {
743
+ return installClaudeCodePermissionHook(homeDir, installedAt, options.sourceScriptPath);
744
+ }
745
+ if (normalizedClient === 'vscode') {
746
+ return installVsCodePermissionHook(homeDir, installedAt, options.sourceScriptPath);
747
+ }
748
+ if (normalizedClient === 'gemini-cli') {
749
+ return installGeminiCliPermissionHook(homeDir, installedAt, options.sourceScriptPath);
750
+ }
751
+ if (normalizedClient === 'cursor') {
752
+ return installCursorPermissionHook(homeDir, installedAt, options.sourceScriptPath);
753
+ }
754
+ if (normalizedClient === 'windsurf') {
755
+ return installWindsurfPermissionHook(homeDir, installedAt, options.sourceScriptPath);
756
+ }
757
+ if (normalizedClient === 'codex') {
758
+ return installCodexPermissionHook(homeDir, installedAt, options.sourceScriptPath);
759
+ }
760
+ if (getHookWrapperBasename(normalizedClient)) {
761
+ return installManualPermissionHookAssets(normalizedClient, homeDir, installedAt, options.sourceScriptPath);
762
+ }
763
+ return {
764
+ supported: false,
765
+ installed: false,
766
+ configured: false,
767
+ host: normalizedClient,
768
+ message: `Automatic permission hook wiring is not yet supported for ${normalizedClient}.`,
769
+ };
770
+ }
771
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvbkhvb2tzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3Blcm1pc3Npb25Ib29rcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRyxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMxQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzVDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxhQUFhLENBQUM7QUEwQ3JDLFNBQVMsa0JBQWtCO0lBQ3pCLE1BQU0sV0FBVyxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25ELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRCxTQUFTLGtCQUFrQixDQUFDLEtBQWM7SUFDeEMsT0FBTyxPQUFPLENBQ1osS0FBSztXQUNGLE9BQU8sS0FBSyxLQUFLLFFBQVE7V0FDekIsTUFBTSxJQUFJLEtBQUs7V0FDZCxLQUEyQixDQUFDLElBQUksS0FBSyxRQUFRLENBQ2xELENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsR0FBVztJQUMvQixLQUFLLE1BQU0sSUFBSSxJQUFJLEdBQUcs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QUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztRQUM3QyxPQUFPLGlDQUFpQyxDQUFDLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDN0csQ0FBQztJQUVELE9BQU87UUFDTCxTQUFTLEVBQUUsS0FBSztRQUNoQixTQUFTLEVBQUUsS0FBSztRQUNoQixVQUFVLEVBQUUsS0FBSztRQUNqQixJQUFJLEVBQUUsZ0JBQWdCO1FBQ3RCLE9BQU8sRUFBRSw2REFBNkQsZ0JBQWdCLEdBQUc7S0FDMUYsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMsIHJlYWRkaXJTeW5jLCBzdGF0U3luYyB9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHsgYWNjZXNzLCBjaG1vZCwgY29weUZpbGUsIG1rZGlyLCByZWFkRmlsZSwgcmVhZGRpciwgd3JpdGVGaWxlIH0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcyc7XG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCc7XG5pbXBvcnQgeyBob21lZGlyLCBwbGF0Zm9ybSB9IGZyb20gJ25vZGU6b3MnO1xuaW1wb3J0IHsgVW5pY29kZVZhbGlkYXRvciB9IGZyb20gJy4uL3NlY3VyaXR5L3ZhbGlkYXRvcnMvdW5pY29kZVZhbGlkYXRvci5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuL2xvZ2dlci5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGVybWlzc2lvbkhvb2tNYXJrZXIge1xuICBob3N0OiBzdHJpbmc7XG4gIHNjcmlwdFBhdGg6IHN0cmluZztcbiAgc2V0dGluZ3NQYXRoPzogc3RyaW5nO1xuICBhZGRpdGlvbmFsUGF0aHM/OiBzdHJpbmdbXTtcbiAgY29uZmlndXJlZD86IGJvb2xlYW47XG4gIGFzc2V0c1ByZXBhcmVkPzogYm9vbGVhbjtcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQZXJtaXNzaW9uSG9va1N0YXR1cyB7XG4gIGluc3RhbGxlZDogYm9vbGVhbjtcbiAgY29uZmlndXJlZD86IGJvb2xlYW47XG4gIGFzc2V0c1ByZXBhcmVkPzogYm9vbGVhbjtcbiAgaG9zdD86IHN0cmluZztcbiAgc2NyaXB0UGF0aD86IHN0cmluZztcbiAgc2V0dGluZ3NQYXRoPzogc3RyaW5nO1xuICBhZGRpdGlvbmFsUGF0aHM/OiBzdHJpbmdbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQge1xuICBzdXBwb3J0ZWQ6IGJvb2xlYW47XG4gIGluc3RhbGxlZDogYm9vbGVhbjtcbiAgY29uZmlndXJlZDogYm9vbGVhbjtcbiAgYXNzZXRzUHJlcGFyZWQ/OiBib29sZWFuO1xuICBob3N0OiBzdHJpbmc7XG4gIHNjcmlwdFBhdGg/OiBzdHJpbmc7XG4gIHNldHRpbmdzUGF0aD86IHN0cmluZztcbiAgYWRkaXRpb25hbFBhdGhzPzogc3RyaW5nW107XG4gIG1hcmtlclBhdGg/OiBzdHJpbmc7XG4gIGJhY2t1cFBhdGg/OiBzdHJpbmc7XG4gIG1lc3NhZ2U6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbnN0YWxsUGVybWlzc2lvbkhvb2tPcHRpb25zIHtcbiAgaG9tZURpcj86IHN0cmluZztcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZztcbiAgbm93PzogRGF0ZTtcbn1cblxuZnVuY3Rpb24gcmVwb1Jvb3RGcm9tTW9kdWxlKCk6IHN0cmluZyB7XG4gIGNvbnN0IGN1cnJlbnRGaWxlID0gZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpO1xuICByZXR1cm4gZGlybmFtZShkaXJuYW1lKGRpcm5hbWUoY3VycmVudEZpbGUpKSk7XG59XG5cbmZ1bmN0aW9uIGlzTWlzc2luZ0ZpbGVFcnJvcihlcnJvcjogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gQm9vbGVhbihcbiAgICBlcnJvclxuICAgICYmIHR5cGVvZiBlcnJvciA9PT0gJ29iamVjdCdcbiAgICAmJiAnY29kZScgaW4gZXJyb3JcbiAgICAmJiAoZXJyb3IgYXMgeyBjb2RlPzogc3RyaW5nIH0pLmNvZGUgPT09ICdFTk9FTlQnLFxuICApO1xufVxuXG5mdW5jdGlvbiBkZXRlY3RJbmRlbnQocmF3OiBzdHJpbmcpOiBudW1iZXIgfCBzdHJpbmcge1xuICBmb3IgKGNvbnN0IGxpbmUgb2YgcmF3LnNwbGl0KCdcXG4nKSkge1xuICAgIGlmIChsaW5lLmxlbmd0aCA9PT0gMCB8fCBsaW5lLnN0YXJ0c1dpdGgoJ3snKSB8fCBsaW5lLnN0YXJ0c1dpdGgoJ30nKSkgY29udGludWU7XG4gICAgaWYgKGxpbmUuc3RhcnRzV2l0aCgnXFx0JykpIHJldHVybiAnXFx0JztcbiAgICBpZiAobGluZS5zdGFydHNXaXRoKCcgJykpIHtcbiAgICAgIGNvbnN0IHNwYWNlcyA9IGxpbmUubGVuZ3RoIC0gbGluZS50cmltU3RhcnQoKS5sZW5ndGg7XG4gICAgICBpZiAoc3BhY2VzID49IDIpIHJldHVybiBzcGFjZXM7XG4gICAgfVxuICB9XG4gIHJldHVybiAyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UGVybWlzc2lvbkhvb2tTY3JpcHRQYXRoKGhvbWVEaXIgPSBob21lZGlyKCkpOiBzdHJpbmcge1xuICByZXR1cm4gam9pbihob21lRGlyLCAnLmRvbGxob3VzZScsICdob29rcycsICdwcmV0b29sdXNlLWRvbGxob3VzZS5zaCcpO1xufVxuXG5mdW5jdGlvbiBnZXRQZXJtaXNzaW9uSG9va1J1bkRpcihob21lRGlyID0gaG9tZWRpcigpKTogc3RyaW5nIHtcbiAgcmV0dXJuIGpvaW4oaG9tZURpciwgJy5kb2xsaG91c2UnLCAncnVuJyk7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZUhvb2tIb3N0KGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBVbmljb2RlVmFsaWRhdG9yLm5vcm1hbGl6ZShob3N0KS5ub3JtYWxpemVkQ29udGVudC50cmltKCkudG9Mb3dlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gaXNIb29rTWFya2VyRmlsZW5hbWUoZW50cnk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gZW50cnkuc3RhcnRzV2l0aCgnaG9vay1pbnN0YWxsZWQtJykgJiYgZW50cnkuZW5kc1dpdGgoJy5qc29uJyk7XG59XG5cbmZ1bmN0aW9uIHJlYWRIb3N0U3BlY2lmaWNIb29rU3RhdHVzKGhvbWVEaXI6IHN0cmluZywgaG9zdDogc3RyaW5nKTogUGVybWlzc2lvbkhvb2tTdGF0dXMge1xuICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplSG9va0hvc3QoaG9zdCk7XG4gIGNvbnN0IHN0YXR1cyA9IHJlYWRNYXJrZXJTdGF0dXMoZ2V0UGVybWlzc2lvbkhvb2tNYXJrZXJQYXRoKGhvbWVEaXIsIG5vcm1hbGl6ZWQpKTtcbiAgaWYgKHN0YXR1cy5pbnN0YWxsZWQgfHwgc3RhdHVzLmFzc2V0c1ByZXBhcmVkKSB7XG4gICAgcmV0dXJuIHN0YXR1cztcbiAgfVxuICBpZiAobm9ybWFsaXplZCA9PT0gJ2NsYXVkZS1jb2RlJykge1xuICAgIHJldHVybiByZWFkTWFya2VyU3RhdHVzKGdldFBlcm1pc3Npb25Ib29rTWFya2VyUGF0aChob21lRGlyKSk7XG4gIH1cbiAgcmV0dXJuIHsgaW5zdGFsbGVkOiBmYWxzZSB9O1xufVxuXG5mdW5jdGlvbiBjb2xsZWN0SG9va01hcmtlclBhdGhzKGhvbWVEaXI6IHN0cmluZyk6IFNldDxzdHJpbmc+IHtcbiAgY29uc3QgbWFya2VyUGF0aHMgPSBuZXcgU2V0PHN0cmluZz4oW2dldFBlcm1pc3Npb25Ib29rTWFya2VyUGF0aChob21lRGlyKV0pO1xuICBjb25zdCBydW5EaXIgPSBnZXRQZXJtaXNzaW9uSG9va1J1bkRpcihob21lRGlyKTtcbiAgdHJ5IHtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHJlYWRkaXJTeW5jKHJ1bkRpcikpIHtcbiAgICAgIGlmIChpc0hvb2tNYXJrZXJGaWxlbmFtZShlbnRyeSkpIHtcbiAgICAgICAgbWFya2VyUGF0aHMuYWRkKGpvaW4ocnVuRGlyLCBlbnRyeSkpO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCB7XG4gICAgLy8gTm8gcnVuIGRpciB5ZXQg4oCUIGZhbGwgdGhyb3VnaCB0byBkZWZhdWx0IGZhbHNlLlxuICB9XG4gIHJldHVybiBtYXJrZXJQYXRocztcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29sbGVjdEhvb2tNYXJrZXJQYXRoc0FzeW5jKGhvbWVEaXI6IHN0cmluZyk6IFByb21pc2U8U2V0PHN0cmluZz4+IHtcbiAgY29uc3QgbWFya2VyUGF0aHMgPSBuZXcgU2V0PHN0cmluZz4oW2dldFBlcm1pc3Npb25Ib29rTWFya2VyUGF0aChob21lRGlyKV0pO1xuICBjb25zdCBydW5EaXIgPSBnZXRQZXJtaXNzaW9uSG9va1J1bkRpcihob21lRGlyKTtcbiAgdHJ5IHtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGF3YWl0IHJlYWRkaXIocnVuRGlyKSkge1xuICAgICAgaWYgKGlzSG9va01hcmtlckZpbGVuYW1lKGVudHJ5KSkge1xuICAgICAgICBtYXJrZXJQYXRocy5hZGQoam9pbihydW5EaXIsIGVudHJ5KSk7XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIHtcbiAgICAvLyBObyBydW4gZGlyIHlldCDigJQgZmFsbCB0aHJvdWdoIHRvIGRlZmF1bHQgZmFsc2UuXG4gIH1cbiAgcmV0dXJuIG1hcmtlclBhdGhzO1xufVxuXG5mdW5jdGlvbiBzdW1tYXJpemVNYXJrZXJTdGF0dXNlcyhtYXJrZXJQYXRoczogSXRlcmFibGU8c3RyaW5nPik6IFBlcm1pc3Npb25Ib29rU3RhdHVzIHtcbiAgbGV0IGZhbGxiYWNrOiBQZXJtaXNzaW9uSG9va1N0YXR1cyA9IHsgaW5zdGFsbGVkOiBmYWxzZSB9O1xuICBmb3IgKGNvbnN0IG1hcmtlclBhdGggb2YgbWFya2VyUGF0aHMpIHtcbiAgICBjb25zdCBzdGF0dXMgPSByZWFkTWFya2VyU3RhdHVzKG1hcmtlclBhdGgpO1xuICAgIGlmIChzdGF0dXMuaW5zdGFsbGVkKSByZXR1cm4gc3RhdHVzO1xuICAgIGlmICghZmFsbGJhY2suYXNzZXRzUHJlcGFyZWQgJiYgc3RhdHVzLmFzc2V0c1ByZXBhcmVkKSBmYWxsYmFjayA9IHN0YXR1cztcbiAgfVxuICByZXR1cm4gZmFsbGJhY2s7XG59XG5cbmZ1bmN0aW9uIGdldEhvb2tXcmFwcGVyQmFzZW5hbWUoaG9zdDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIHN3aXRjaCAobm9ybWFsaXplSG9va0hvc3QoaG9zdCkpIHtcbiAgICBjYXNlICd2c2NvZGUnOlxuICAgICAgcmV0dXJuICdwcmV0b29sdXNlLXZzY29kZS5zaCc7XG4gICAgY2FzZSAnY3Vyc29yJzpcbiAgICAgIHJldHVybiAncHJldG9vbHVzZS1jdXJzb3Iuc2gnO1xuICAgIGNhc2UgJ3dpbmRzdXJmJzpcbiAgICAgIHJldHVybiAncHJldG9vbHVzZS13aW5kc3VyZi5zaCc7XG4gICAgY2FzZSAnZ2VtaW5pLWNsaSc6XG4gICAgICByZXR1cm4gJ3ByZXRvb2x1c2UtZ2VtaW5pLnNoJztcbiAgICBjYXNlICdjb2RleCc6XG4gICAgICByZXR1cm4gJ3ByZXRvb2x1c2UtY29kZXguc2gnO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRIb29rV3JhcHBlclBhdGgoaG9zdDogc3RyaW5nLCBob21lRGlyID0gaG9tZWRpcigpKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IGJhc2VuYW1lID0gZ2V0SG9va1dyYXBwZXJCYXNlbmFtZShob3N0KTtcbiAgcmV0dXJuIGJhc2VuYW1lID8gam9pbihob21lRGlyLCAnLmRvbGxob3VzZScsICdob29rcycsIGJhc2VuYW1lKSA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIGdldEhvb2tTb3VyY2VQYXRoKGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHJvb3QgPSByZXBvUm9vdEZyb21Nb2R1bGUoKTtcbiAgY29uc3QgYmFzZW5hbWUgPSBnZXRIb29rV3JhcHBlckJhc2VuYW1lKGhvc3QpO1xuICByZXR1cm4gYmFzZW5hbWUgPyBqb2luKHJvb3QsICdzY3JpcHRzJywgYmFzZW5hbWUpIDogam9pbihyb290LCAnc2NyaXB0cycsICdwcmV0b29sdXNlLWRvbGxob3VzZS5zaCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UGVybWlzc2lvbkhvb2tNYXJrZXJQYXRoKGhvbWVEaXIgPSBob21lZGlyKCksIGhvc3Q/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIWhvc3QpIHtcbiAgICByZXR1cm4gam9pbihnZXRQZXJtaXNzaW9uSG9va1J1bkRpcihob21lRGlyKSwgJ2hvb2staW5zdGFsbGVkLmpzb24nKTtcbiAgfVxuICByZXR1cm4gam9pbihnZXRQZXJtaXNzaW9uSG9va1J1bkRpcihob21lRGlyKSwgYGhvb2staW5zdGFsbGVkLSR7bm9ybWFsaXplSG9va0hvc3QoaG9zdCl9Lmpzb25gKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENsYXVkZUhvb2tTZXR0aW5nc1BhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuY2xhdWRlJywgJ3NldHRpbmdzLmpzb24nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFZzQ29kZUhvb2tTZXR0aW5nc1BhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuY29waWxvdCcsICdob29rcycsICdkb2xsaG91c2UtcGVybWlzc2lvbnMuanNvbicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VnNDb2RlVXNlclNldHRpbmdzUGF0aChob21lRGlyID0gaG9tZWRpcigpKTogc3RyaW5nIHtcbiAgY29uc3QgY3VycmVudFBsYXRmb3JtID0gcGxhdGZvcm0oKTtcbiAgaWYgKGN1cnJlbnRQbGF0Zm9ybSA9PT0gJ2RhcndpbicpIHtcbiAgICByZXR1cm4gam9pbihob21lRGlyLCAnTGlicmFyeScsICdBcHBsaWNhdGlvbiBTdXBwb3J0JywgJ0NvZGUnLCAnVXNlcicsICdzZXR0aW5ncy5qc29uJyk7XG4gIH1cbiAgaWYgKGN1cnJlbnRQbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgIGNvbnN0IGFwcERhdGEgPSBwcm9jZXNzLmVudi5BUFBEQVRBIHx8IGpvaW4oaG9tZURpciwgJ0FwcERhdGEnLCAnUm9hbWluZycpO1xuICAgIHJldHVybiBqb2luKGFwcERhdGEsICdDb2RlJywgJ1VzZXInLCAnc2V0dGluZ3MuanNvbicpO1xuICB9XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuY29uZmlnJywgJ0NvZGUnLCAnVXNlcicsICdzZXR0aW5ncy5qc29uJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRHZW1pbmlIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIgPSBob21lZGlyKCkpOiBzdHJpbmcge1xuICByZXR1cm4gam9pbihob21lRGlyLCAnLmdlbWluaScsICdzZXR0aW5ncy5qc29uJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDdXJzb3JIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIgPSBob21lZGlyKCkpOiBzdHJpbmcge1xuICByZXR1cm4gam9pbihob21lRGlyLCAnLmN1cnNvcicsICdob29rcy5qc29uJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRXaW5kc3VyZkhvb2tTZXR0aW5nc1BhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuY29kZWl1bScsICd3aW5kc3VyZicsICdob29rcy5qc29uJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb2RleEhvb2tTZXR0aW5nc1BhdGgoaG9tZURpciA9IGhvbWVkaXIoKSk6IHN0cmluZyB7XG4gIHJldHVybiBqb2luKGhvbWVEaXIsICcuY29kZXgnLCAnaG9va3MuanNvbicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29kZXhDb25maWdQYXRoKGhvbWVEaXIgPSBob21lZGlyKCkpOiBzdHJpbmcge1xuICByZXR1cm4gam9pbihob21lRGlyLCAnLmNvZGV4JywgJ2NvbmZpZy50b21sJyk7XG59XG5cbmZ1bmN0aW9uIHRvUGVybWlzc2lvbkhvb2tTdGF0dXMocmF3OiBQZXJtaXNzaW9uSG9va01hcmtlcik6IFBlcm1pc3Npb25Ib29rU3RhdHVzIHtcbiAgaWYgKFxuICAgIHR5cGVvZiByYXcuaG9zdCAhPT0gJ3N0cmluZycgfHxcbiAgICB0eXBlb2YgcmF3LnNjcmlwdFBhdGggIT09ICdzdHJpbmcnXG4gICkge1xuICAgIHJldHVybiB7IGluc3RhbGxlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IHNjcmlwdFJlYWR5ID0gZXhpc3RzU3luYyhyYXcuc2NyaXB0UGF0aCk7XG4gIGNvbnN0IHNldHRpbmdzUmVhZHkgPSAhcmF3LnNldHRpbmdzUGF0aCB8fCBleGlzdHNTeW5jKHJhdy5zZXR0aW5nc1BhdGgpO1xuICBjb25zdCBhZGRpdGlvbmFsUGF0aHNSZWFkeSA9ICFyYXcuYWRkaXRpb25hbFBhdGhzIHx8IHJhdy5hZGRpdGlvbmFsUGF0aHMuZXZlcnkoKHBhdGgpID0+IGV4aXN0c1N5bmMocGF0aCkpO1xuICBjb25zdCBhc3NldHNQcmVwYXJlZCA9IChyYXcuYXNzZXRzUHJlcGFyZWQgPz8gcmF3LmNvbmZpZ3VyZWQgPz8gdHJ1ZSkgJiYgc2NyaXB0UmVhZHk7XG4gIGNvbnN0IGNvbmZpZ3VyZWQgPSAocmF3LmNvbmZpZ3VyZWQgPz8gdHJ1ZSkgJiYgc2NyaXB0UmVhZHkgJiYgc2V0dGluZ3NSZWFkeSAmJiBhZGRpdGlvbmFsUGF0aHNSZWFkeTtcblxuICByZXR1cm4ge1xuICAgIGluc3RhbGxlZDogY29uZmlndXJlZCxcbiAgICBjb25maWd1cmVkLFxuICAgIGFzc2V0c1ByZXBhcmVkLFxuICAgIGhvc3Q6IHJhdy5ob3N0LFxuICAgIHNjcmlwdFBhdGg6IHJhdy5zY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aDogcmF3LnNldHRpbmdzUGF0aCxcbiAgICBhZGRpdGlvbmFsUGF0aHM6IHJhdy5hZGRpdGlvbmFsUGF0aHMsXG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlYWRNYXJrZXJTdGF0dXMobWFya2VyUGF0aDogc3RyaW5nKTogUGVybWlzc2lvbkhvb2tTdGF0dXMge1xuICB0cnkge1xuICAgIGNvbnN0IHJhdyA9IHJlYWRGaWxlU3luYyhtYXJrZXJQYXRoLCAndXRmLTgnKTtcbiAgICByZXR1cm4gdG9QZXJtaXNzaW9uSG9va1N0YXR1cyhKU09OLnBhcnNlKHJhdykgYXMgUGVybWlzc2lvbkhvb2tNYXJrZXIpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmICghaXNNaXNzaW5nRmlsZUVycm9yKGVycm9yKSkge1xuICAgICAgbG9nZ2VyLndhcm4oYFtQZXJtaXNzaW9uc10gRmFpbGVkIHRvIHJlYWQgaG9vayBtYXJrZXIgYXQgJHttYXJrZXJQYXRofTogJHtTdHJpbmcoZXJyb3IpfWApO1xuICAgIH1cbiAgICByZXR1cm4geyBpbnN0YWxsZWQ6IGZhbHNlIH07XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFBlcm1pc3Npb25Ib29rU3RhdHVzKGhvbWVEaXIgPSBob21lZGlyKCksIGhvc3Q/OiBzdHJpbmcpOiBQZXJtaXNzaW9uSG9va1N0YXR1cyB7XG4gIGlmIChob3N0KSB7XG4gICAgcmV0dXJuIHJlYWRIb3N0U3BlY2lmaWNIb29rU3RhdHVzKGhvbWVEaXIsIGhvc3QpO1xuICB9XG5cbiAgcmV0dXJuIHN1bW1hcml6ZU1hcmtlclN0YXR1c2VzKGNvbGxlY3RIb29rTWFya2VyUGF0aHMoaG9tZURpcikpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UGVybWlzc2lvbkhvb2tTdGF0dXNBc3luYyhob21lRGlyID0gaG9tZWRpcigpLCBob3N0Pzogc3RyaW5nKTogUHJvbWlzZTxQZXJtaXNzaW9uSG9va1N0YXR1cz4ge1xuICBpZiAoaG9zdCkge1xuICAgIHJldHVybiByZWFkSG9zdFNwZWNpZmljSG9va1N0YXR1cyhob21lRGlyLCBob3N0KTtcbiAgfVxuXG4gIHJldHVybiBzdW1tYXJpemVNYXJrZXJTdGF0dXNlcyhhd2FpdCBjb2xsZWN0SG9va01hcmtlclBhdGhzQXN5bmMoaG9tZURpcikpO1xufVxuXG5mdW5jdGlvbiBub3JtYWxpemVIb29rc1Jvb3QocGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFJlY29yZDxzdHJpbmcsIHVua25vd25bXT4ge1xuICBjb25zdCBob29rc1ZhbHVlID0gcGFyc2VkLmhvb2tzO1xuICBpZiAoIWhvb2tzVmFsdWUgfHwgdHlwZW9mIGhvb2tzVmFsdWUgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkoaG9va3NWYWx1ZSkpIHtcbiAgICBwYXJzZWQuaG9va3MgPSB7fTtcbiAgfVxuICByZXR1cm4gcGFyc2VkLmhvb2tzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd25bXT47XG59XG5cbmZ1bmN0aW9uIGVuc3VyZUNvbW1hbmRIb29rKFxuICBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBldmVudE5hbWU6IHN0cmluZyxcbiAgY29tbWFuZDogc3RyaW5nLFxuICBtYXRjaGVyOiBzdHJpbmcsXG4gIGV4dHJhSG9va0ZpZWxkczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fSxcbik6IHsgY2hhbmdlZDogYm9vbGVhbjsgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgY29uc3QgaG9va3NSb290ID0gbm9ybWFsaXplSG9va3NSb290KHBhcnNlZCk7XG4gIGNvbnN0IGV4aXN0aW5nRW50cmllczogQXJyYXk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+ID0gQXJyYXkuaXNBcnJheShob29rc1Jvb3RbZXZlbnROYW1lXSlcbiAgICA/IGhvb2tzUm9vdFtldmVudE5hbWVdLmZpbHRlcigoZW50cnkpOiBlbnRyeSBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiB0eXBlb2YgZW50cnkgPT09ICdvYmplY3QnICYmIGVudHJ5ICE9PSBudWxsKVxuICAgIDogW107XG4gIGhvb2tzUm9vdFtldmVudE5hbWVdID0gZXhpc3RpbmdFbnRyaWVzO1xuXG4gIGNvbnN0IGNvbW1hbmRFeGlzdHMgPSBleGlzdGluZ0VudHJpZXMuc29tZSgoZW50cnkpID0+IHtcbiAgICBjb25zdCBob29rcyA9IEFycmF5LmlzQXJyYXkoZW50cnk/Lmhvb2tzKSA/IGVudHJ5Lmhvb2tzIGFzIEFycmF5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PiA6IFtdO1xuICAgIHJldHVybiBob29rcy5zb21lKChob29rKSA9PiBob29rPy50eXBlID09PSAnY29tbWFuZCcgJiYgaG9vaz8uY29tbWFuZCA9PT0gY29tbWFuZCk7XG4gIH0pO1xuICBpZiAoY29tbWFuZEV4aXN0cykge1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlLCBwYXJzZWQgfTtcbiAgfVxuXG4gIGNvbnN0IHdpbGRjYXJkRW50cnkgPSBleGlzdGluZ0VudHJpZXMuZmluZCgoZW50cnkpOiBlbnRyeSBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PlxuICAgIChlbnRyeT8ubWF0Y2hlciA9PT0gbWF0Y2hlciB8fCBlbnRyeT8ubWF0Y2hlciA9PT0gdW5kZWZpbmVkKSAmJiBBcnJheS5pc0FycmF5KGVudHJ5Py5ob29rcyksXG4gICk7XG5cbiAgaWYgKHdpbGRjYXJkRW50cnkpIHtcbiAgICBjb25zdCBob29rcyA9IHdpbGRjYXJkRW50cnkuaG9va3MgYXMgQXJyYXk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+O1xuICAgIGhvb2tzLnB1c2goe1xuICAgICAgdHlwZTogJ2NvbW1hbmQnLFxuICAgICAgY29tbWFuZCxcbiAgICAgIC4uLmV4dHJhSG9va0ZpZWxkcyxcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBleGlzdGluZ0VudHJpZXMucHVzaCh7XG4gICAgICBtYXRjaGVyLFxuICAgICAgaG9va3M6IFtcbiAgICAgICAge1xuICAgICAgICAgIHR5cGU6ICdjb21tYW5kJyxcbiAgICAgICAgICBjb21tYW5kLFxuICAgICAgICAgIC4uLmV4dHJhSG9va0ZpZWxkcyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBwYXJzZWQgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZUNsYXVkZVByZVRvb2xVc2VIb29rKFxuICBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBjb21tYW5kOiBzdHJpbmcsXG4pOiB7IGNoYW5nZWQ6IGJvb2xlYW47IHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfSB7XG4gIHJldHVybiBlbnN1cmVDb21tYW5kSG9vayhwYXJzZWQsICdQcmVUb29sVXNlJywgY29tbWFuZCwgJyonKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZVZzQ29kZVByZVRvb2xVc2VIb29rKFxuICBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBjb21tYW5kOiBzdHJpbmcsXG4pOiB7IGNoYW5nZWQ6IGJvb2xlYW47IHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfSB7XG4gIHJldHVybiBlbnN1cmVDb21tYW5kSG9vayhwYXJzZWQsICdQcmVUb29sVXNlJywgY29tbWFuZCwgJyonKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZUdlbWluaUJlZm9yZVRvb2xIb29rKFxuICBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBjb21tYW5kOiBzdHJpbmcsXG4pOiB7IGNoYW5nZWQ6IGJvb2xlYW47IHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfSB7XG4gIHJldHVybiBlbnN1cmVDb21tYW5kSG9vayhwYXJzZWQsICdCZWZvcmVUb29sJywgY29tbWFuZCwgJy4qJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVDb2RleFByZVRvb2xVc2VIb29rKFxuICBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBjb21tYW5kOiBzdHJpbmcsXG4pOiB7IGNoYW5nZWQ6IGJvb2xlYW47IHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfSB7XG4gIHJldHVybiBlbnN1cmVDb21tYW5kSG9vayhwYXJzZWQsICdQcmVUb29sVXNlJywgY29tbWFuZCwgJ0Jhc2gnLCB7XG4gICAgc3RhdHVzTWVzc2FnZTogJ0NoZWNraW5nIEJhc2ggcGVybWlzc2lvbnMnLFxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZUN1cnNvclByZVRvb2xVc2VIb29rKFxuICBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBjb21tYW5kOiBzdHJpbmcsXG4pOiB7IGNoYW5nZWQ6IGJvb2xlYW47IHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfSB7XG4gIGlmIChwYXJzZWQudmVyc2lvbiAhPT0gMSkge1xuICAgIHBhcnNlZC52ZXJzaW9uID0gMTtcbiAgfVxuICBjb25zdCBob29rc1Jvb3QgPSBub3JtYWxpemVIb29rc1Jvb3QocGFyc2VkKTtcbiAgY29uc3QgZXhpc3RpbmdFbnRyaWVzOiBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gPSBBcnJheS5pc0FycmF5KGhvb2tzUm9vdC5wcmVUb29sVXNlKVxuICAgID8gaG9va3NSb290LnByZVRvb2xVc2UuZmlsdGVyKChlbnRyeSk6IGVudHJ5IGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+IHR5cGVvZiBlbnRyeSA9PT0gJ29iamVjdCcgJiYgZW50cnkgIT09IG51bGwpXG4gICAgOiBbXTtcbiAgaG9va3NSb290LnByZVRvb2xVc2UgPSBleGlzdGluZ0VudHJpZXM7XG5cbiAgY29uc3QgY29tbWFuZEV4aXN0cyA9IGV4aXN0aW5nRW50cmllcy5zb21lKChlbnRyeSkgPT5cbiAgICBlbnRyeS5jb21tYW5kID09PSBjb21tYW5kXG4gICAgJiYgKGVudHJ5LnR5cGUgPT09ICdjb21tYW5kJyB8fCBlbnRyeS50eXBlID09PSB1bmRlZmluZWQpLFxuICApO1xuICBpZiAoY29tbWFuZEV4aXN0cykge1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlLCBwYXJzZWQgfTtcbiAgfVxuXG4gIGV4aXN0aW5nRW50cmllcy5wdXNoKHtcbiAgICB0eXBlOiAnY29tbWFuZCcsXG4gICAgY29tbWFuZCxcbiAgICBtYXRjaGVyOiAnLionLFxuICB9KTtcblxuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBwYXJzZWQgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZVdpbmRzdXJmSG9va3MoXG4gIHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGNvbW1hbmQ6IHN0cmluZyxcbik6IHsgY2hhbmdlZDogYm9vbGVhbjsgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9IHtcbiAgY29uc3QgaG9va3NSb290ID0gbm9ybWFsaXplSG9va3NSb290KHBhcnNlZCk7XG4gIGxldCBjaGFuZ2VkID0gZmFsc2U7XG5cbiAgY29uc3QgZW5zdXJlRXZlbnRIb29rID0gKGV2ZW50TmFtZTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgZXhpc3RpbmdFbnRyaWVzOiBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gPSBBcnJheS5pc0FycmF5KGhvb2tzUm9vdFtldmVudE5hbWVdKVxuICAgICAgPyBob29rc1Jvb3RbZXZlbnROYW1lXS5maWx0ZXIoKGVudHJ5KTogZW50cnkgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPT4gdHlwZW9mIGVudHJ5ID09PSAnb2JqZWN0JyAmJiBlbnRyeSAhPT0gbnVsbClcbiAgICAgIDogW107XG4gICAgaG9va3NSb290W2V2ZW50TmFtZV0gPSBleGlzdGluZ0VudHJpZXM7XG5cbiAgICBjb25zdCBjb21tYW5kRXhpc3RzID0gZXhpc3RpbmdFbnRyaWVzLnNvbWUoKGVudHJ5KSA9PlxuICAgICAgZW50cnkuY29tbWFuZCA9PT0gY29tbWFuZCAmJiAoZW50cnkudHlwZSA9PT0gJ2NvbW1hbmQnIHx8IGVudHJ5LnR5cGUgPT09IHVuZGVmaW5lZCksXG4gICAgKTtcbiAgICBpZiAoY29tbWFuZEV4aXN0cykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGV4aXN0aW5nRW50cmllcy5wdXNoKHtcbiAgICAgIHR5cGU6ICdjb21tYW5kJyxcbiAgICAgIGNvbW1hbmQsXG4gICAgfSk7XG4gICAgY2hhbmdlZCA9IHRydWU7XG4gIH07XG5cbiAgZW5zdXJlRXZlbnRIb29rKCdwcmVfcnVuX2NvbW1hbmQnKTtcbiAgZW5zdXJlRXZlbnRIb29rKCdwcmVfbWNwX3Rvb2xfdXNlJyk7XG5cbiAgcmV0dXJuIHsgY2hhbmdlZCwgcGFyc2VkIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNvcHlIb29rQXNzZXQoc291cmNlUGF0aDogc3RyaW5nLCB0YXJnZXRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZSh0YXJnZXRQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3Qgc291cmNlUmF3ID0gYXdhaXQgcmVhZEZpbGUoc291cmNlUGF0aCwgJ3V0Zi04Jyk7XG5cbiAgbGV0IHRhcmdldFJhdzogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICB0cnkge1xuICAgIHRhcmdldFJhdyA9IGF3YWl0IHJlYWRGaWxlKHRhcmdldFBhdGgsICd1dGYtOCcpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmICghaXNNaXNzaW5nRmlsZUVycm9yKGVycm9yKSkge1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG4gIGNvbnN0IGNoYW5nZWQgPSB0YXJnZXRSYXcgPT09IHVuZGVmaW5lZCB8fCBzb3VyY2VSYXcgIT09IHRhcmdldFJhdztcblxuICBpZiAoY2hhbmdlZCkge1xuICAgIGF3YWl0IGNvcHlGaWxlKHNvdXJjZVBhdGgsIHRhcmdldFBhdGgpO1xuICB9IGVsc2Uge1xuICAgIGF3YWl0IGFjY2Vzcyh0YXJnZXRQYXRoKTtcbiAgfVxuXG4gIGF3YWl0IGNobW9kKHRhcmdldFBhdGgsIDBvNzU1KTtcbiAgcmV0dXJuIGNoYW5nZWQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRPcHRpb25hbFV0ZjgoZmlsZVBhdGg6IHN0cmluZywgZmFsbGJhY2s6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoaXNNaXNzaW5nRmlsZUVycm9yKGVycm9yKSkge1xuICAgICAgcmV0dXJuIGZhbGxiYWNrO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiB3cml0ZUJhY2t1cElmUHJlc2VudChmaWxlUGF0aDogc3RyaW5nLCByYXc6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIGlmICghZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGAke2ZpbGVQYXRofS5kb2xsaG91c2UuYmFrYDtcbiAgYXdhaXQgd3JpdGVGaWxlKGJhY2t1cFBhdGgsIHJhdywgJ3V0Zi04Jyk7XG4gIHJldHVybiBiYWNrdXBQYXRoO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUNsYXVkZVNldHRpbmdzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7fVxcbicpO1xuXG4gIGNvbnN0IGluZGVudCA9IGRldGVjdEluZGVudChyYXcpO1xuICBjb25zdCBwYXJzZWQgPSByYXcudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHt9IDogSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IGNoYW5nZWQsIHBhcnNlZDogdXBkYXRlZCB9ID0gZW5zdXJlQ2xhdWRlUHJlVG9vbFVzZUhvb2socGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKHNldHRpbmdzUGF0aCwgSlNPTi5zdHJpbmdpZnkodXBkYXRlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZVZzQ29kZUhvb2tTZXR0aW5ncyhzZXR0aW5nc1BhdGg6IHN0cmluZywgY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTx7IGNoYW5nZWQ6IGJvb2xlYW47IGJhY2t1cFBhdGg/OiBzdHJpbmcgfT4ge1xuICBhd2FpdCBta2RpcihkaXJuYW1lKHNldHRpbmdzUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IHJhdyA9IGF3YWl0IHJlYWRPcHRpb25hbFV0Zjgoc2V0dGluZ3NQYXRoLCAne31cXG4nKTtcblxuICBjb25zdCBpbmRlbnQgPSBkZXRlY3RJbmRlbnQocmF3KTtcbiAgY29uc3QgcGFyc2VkID0gcmF3LnRyaW0oKS5sZW5ndGggPT09IDAgPyB7fSA6IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgeyBjaGFuZ2VkLCBwYXJzZWQ6IHVwZGF0ZWQgfSA9IGVuc3VyZVZzQ29kZVByZVRvb2xVc2VIb29rKHBhcnNlZCwgY29tbWFuZCk7XG4gIGlmICghY2hhbmdlZCkge1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBiYWNrdXBQYXRoID0gYXdhaXQgd3JpdGVCYWNrdXBJZlByZXNlbnQoc2V0dGluZ3NQYXRoLCByYXcpO1xuXG4gIGF3YWl0IHdyaXRlRmlsZShzZXR0aW5nc1BhdGgsIEpTT04uc3RyaW5naWZ5KHVwZGF0ZWQsIG51bGwsIGluZGVudCkgKyAnXFxuJywgJ3V0Zi04Jyk7XG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIGJhY2t1cFBhdGggfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWVyZ2VWc0NvZGVVc2VyU2V0dGluZ3Moc2V0dGluZ3NQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7fVxcbicpO1xuICBjb25zdCBpbmRlbnQgPSBkZXRlY3RJbmRlbnQocmF3KTtcbiAgY29uc3QgcGFyc2VkID0gcmF3LnRyaW0oKS5sZW5ndGggPT09IDAgPyB7fSA6IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgY3VycmVudCA9IHBhcnNlZFsnY2hhdC5ob29rRmlsZXNMb2NhdGlvbnMnXTtcbiAgY29uc3QgbG9jYXRpb25zID0gKGN1cnJlbnQgJiYgdHlwZW9mIGN1cnJlbnQgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KGN1cnJlbnQpKVxuICAgID8geyAuLi4oY3VycmVudCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgfVxuICAgIDoge307XG5cbiAgaWYgKGxvY2F0aW9uc1snfi8uY29waWxvdC9ob29rcyddID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGxvY2F0aW9uc1snfi8uY29waWxvdC9ob29rcyddID0gdHJ1ZTtcbiAgcGFyc2VkWydjaGF0Lmhvb2tGaWxlc0xvY2F0aW9ucyddID0gbG9jYXRpb25zO1xuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG4gIGF3YWl0IHdyaXRlRmlsZShzZXR0aW5nc1BhdGgsIEpTT04uc3RyaW5naWZ5KHBhcnNlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUdlbWluaVNldHRpbmdzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7fVxcbicpO1xuXG4gIGNvbnN0IGluZGVudCA9IGRldGVjdEluZGVudChyYXcpO1xuICBjb25zdCBwYXJzZWQgPSByYXcudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHt9IDogSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IGNoYW5nZWQsIHBhcnNlZDogdXBkYXRlZCB9ID0gZW5zdXJlR2VtaW5pQmVmb3JlVG9vbEhvb2socGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKHNldHRpbmdzUGF0aCwgSlNPTi5zdHJpbmdpZnkodXBkYXRlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUN1cnNvckhvb2tzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7XFxuICBcInZlcnNpb25cIjogMSxcXG4gIFwiaG9va3NcIjoge31cXG59XFxuJyk7XG5cbiAgY29uc3QgaW5kZW50ID0gZGV0ZWN0SW5kZW50KHJhdyk7XG4gIGNvbnN0IHBhcnNlZCA9IHJhdy50cmltKCkubGVuZ3RoID09PSAwID8ge30gOiBKU09OLnBhcnNlKHJhdykgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHsgY2hhbmdlZCwgcGFyc2VkOiB1cGRhdGVkIH0gPSBlbnN1cmVDdXJzb3JQcmVUb29sVXNlSG9vayhwYXJzZWQsIGNvbW1hbmQpO1xuICBpZiAoIWNoYW5nZWQpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IHdyaXRlQmFja3VwSWZQcmVzZW50KHNldHRpbmdzUGF0aCwgcmF3KTtcblxuICBhd2FpdCB3cml0ZUZpbGUoc2V0dGluZ3NQYXRoLCBKU09OLnN0cmluZ2lmeSh1cGRhdGVkLCBudWxsLCBpbmRlbnQpICsgJ1xcbicsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lcmdlV2luZHN1cmZIb29rcyhzZXR0aW5nc1BhdGg6IHN0cmluZywgY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTx7IGNoYW5nZWQ6IGJvb2xlYW47IGJhY2t1cFBhdGg/OiBzdHJpbmcgfT4ge1xuICBhd2FpdCBta2RpcihkaXJuYW1lKHNldHRpbmdzUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IHJhdyA9IGF3YWl0IHJlYWRPcHRpb25hbFV0Zjgoc2V0dGluZ3NQYXRoLCAne1xcbiAgXCJob29rc1wiOiB7fVxcbn1cXG4nKTtcblxuICBjb25zdCBpbmRlbnQgPSBkZXRlY3RJbmRlbnQocmF3KTtcbiAgY29uc3QgcGFyc2VkID0gcmF3LnRyaW0oKS5sZW5ndGggPT09IDAgPyB7fSA6IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgeyBjaGFuZ2VkLCBwYXJzZWQ6IHVwZGF0ZWQgfSA9IGVuc3VyZVdpbmRzdXJmSG9va3MocGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKHNldHRpbmdzUGF0aCwgSlNPTi5zdHJpbmdpZnkodXBkYXRlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUNvZGV4SG9va3MoaG9va3NQYXRoOiBzdHJpbmcsIGNvbW1hbmQ6IHN0cmluZyk6IFByb21pc2U8eyBjaGFuZ2VkOiBib29sZWFuOyBiYWNrdXBQYXRoPzogc3RyaW5nIH0+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShob29rc1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCByYXcgPSBhd2FpdCByZWFkT3B0aW9uYWxVdGY4KGhvb2tzUGF0aCwgJ3t9XFxuJyk7XG5cbiAgY29uc3QgaW5kZW50ID0gZGV0ZWN0SW5kZW50KHJhdyk7XG4gIGNvbnN0IHBhcnNlZCA9IHJhdy50cmltKCkubGVuZ3RoID09PSAwID8ge30gOiBKU09OLnBhcnNlKHJhdykgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHsgY2hhbmdlZCwgcGFyc2VkOiB1cGRhdGVkIH0gPSBlbnN1cmVDb2RleFByZVRvb2xVc2VIb29rKHBhcnNlZCwgY29tbWFuZCk7XG4gIGlmICghY2hhbmdlZCkge1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBiYWNrdXBQYXRoID0gYXdhaXQgd3JpdGVCYWNrdXBJZlByZXNlbnQoaG9va3NQYXRoLCByYXcpO1xuXG4gIGF3YWl0IHdyaXRlRmlsZShob29rc1BhdGgsIEpTT04uc3RyaW5naWZ5KHVwZGF0ZWQsIG51bGwsIGluZGVudCkgKyAnXFxuJywgJ3V0Zi04Jyk7XG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIGJhY2t1cFBhdGggfTtcbn1cblxuZnVuY3Rpb24gZ2V0VG9tbExpbmVDb250ZW50KGxpbmU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGNvbW1lbnRJbmRleCA9IGxpbmUuaW5kZXhPZignIycpO1xuICByZXR1cm4gKGNvbW1lbnRJbmRleCA+PSAwID8gbGluZS5zbGljZSgwLCBjb21tZW50SW5kZXgpIDogbGluZSkudHJpbSgpO1xufVxuXG5mdW5jdGlvbiBpc1RvbWxTZWN0aW9uTGluZShsaW5lOiBzdHJpbmcsIHNlY3Rpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0VG9tbExpbmVDb250ZW50KGxpbmUpID09PSBgWyR7c2VjdGlvbn1dYDtcbn1cblxuZnVuY3Rpb24gcGFyc2VUb21sQm9vbGVhbkFzc2lnbm1lbnQobGluZTogc3RyaW5nLCBrZXk6IHN0cmluZyk6IGJvb2xlYW4gfCBudWxsIHtcbiAgY29uc3QgY29udGVudCA9IGdldFRvbWxMaW5lQ29udGVudChsaW5lKTtcbiAgaWYgKCFjb250ZW50LnN0YXJ0c1dpdGgoYCR7a2V5fSA9IGApKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgY29uc3QgdmFsdWUgPSBjb250ZW50LnNsaWNlKGAke2tleX0gPSBgLmxlbmd0aCkudHJpbSgpO1xuICBpZiAodmFsdWUgPT09ICd0cnVlJykgcmV0dXJuIHRydWU7XG4gIGlmICh2YWx1ZSA9PT0gJ2ZhbHNlJykgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gdXBkYXRlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KGxpbmU6IHN0cmluZywga2V5OiBzdHJpbmcsIG5leHRWYWx1ZTogYm9vbGVhbik6IHN0cmluZyB7XG4gIGNvbnN0IGNvbW1lbnRJbmRleCA9IGxpbmUuaW5kZXhPZignIycpO1xuICBjb25zdCBjb21tZW50U3VmZml4ID0gY29tbWVudEluZGV4ID49IDAgPyBsaW5lLnNsaWNlKGNvbW1lbnRJbmRleCkgOiAnJztcbiAgbGV0IHByZWZpeExlbmd0aCA9IDA7XG4gIHdoaWxlIChwcmVmaXhMZW5ndGggPCBsaW5lLmxlbmd0aCAmJiAvXFxzLy50ZXN0KGxpbmUuY2hhckF0KHByZWZpeExlbmd0aCkpKSB7XG4gICAgcHJlZml4TGVuZ3RoICs9IDE7XG4gIH1cbiAgY29uc3QgcHJlZml4ID0gbGluZS5zbGljZSgwLCBwcmVmaXhMZW5ndGgpO1xuICBjb25zdCBhc3NpZ25tZW50ID0gYCR7cHJlZml4fSR7a2V5fSA9ICR7bmV4dFZhbHVlID8gJ3RydWUnIDogJ2ZhbHNlJ31gO1xuICBjb25zdCB0cmltbWVkQ29tbWVudFN1ZmZpeCA9IGNvbW1lbnRTdWZmaXgudHJpbVN0YXJ0KCk7XG4gIGNvbnN0IHN1ZmZpeCA9IHRyaW1tZWRDb21tZW50U3VmZml4Lmxlbmd0aCA+IDAgPyBgICR7dHJpbW1lZENvbW1lbnRTdWZmaXh9YCA6ICcnO1xuICByZXR1cm4gYCR7YXNzaWdubWVudH0ke3N1ZmZpeH1gLnRyaW1FbmQoKTtcbn1cblxuZnVuY3Rpb24gc3RyaXBUcmFpbGluZ05ld2xpbmVzKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgZW5kID0gdmFsdWUubGVuZ3RoO1xuICB3aGlsZSAoZW5kID4gMCAmJiB2YWx1ZS5jaGFyQXQoZW5kIC0gMSkgPT09ICdcXG4nKSB7XG4gICAgZW5kIC09IDE7XG4gIH1cbiAgcmV0dXJuIHZhbHVlLnNsaWNlKDAsIGVuZCk7XG59XG5cbmZ1bmN0aW9uIGVuc3VyZUNvZGV4SG9va3NFbmFibGVkKHJhdzogc3RyaW5nKTogeyBjaGFuZ2VkOiBib29sZWFuOyBjb250ZW50OiBzdHJpbmcgfSB7XG4gIGNvbnN0IGxpbmVzID0gcmF3Lmxlbmd0aCA+IDAgPyByYXcuc3BsaXQoJ1xcbicpIDogW107XG4gIGNvbnN0IGRvdHRlZEluZGV4ID0gbGluZXMuZmluZEluZGV4KChsaW5lKSA9PiBwYXJzZVRvbWxCb29sZWFuQXNzaWdubWVudChsaW5lLCAnZmVhdHVyZXMuY29kZXhfaG9va3MnKSAhPT0gbnVsbCk7XG4gIGlmIChkb3R0ZWRJbmRleCA+PSAwKSB7XG4gICAgaWYgKHBhcnNlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KGxpbmVzW2RvdHRlZEluZGV4XSwgJ2ZlYXR1cmVzLmNvZGV4X2hvb2tzJykgPT09IHRydWUpIHtcbiAgICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlLCBjb250ZW50OiByYXcgfTtcbiAgICB9XG4gICAgY29uc3QgdXBkYXRlZExpbmVzID0gWy4uLmxpbmVzXTtcbiAgICB1cGRhdGVkTGluZXNbZG90dGVkSW5kZXhdID0gdXBkYXRlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KHVwZGF0ZWRMaW5lc1tkb3R0ZWRJbmRleF0sICdmZWF0dXJlcy5jb2RleF9ob29rcycsIHRydWUpO1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIGNvbnRlbnQ6IGAke3N0cmlwVHJhaWxpbmdOZXdsaW5lcyh1cGRhdGVkTGluZXMuam9pbignXFxuJykpfVxcbmAgfTtcbiAgfVxuXG4gIGNvbnN0IHNlY3Rpb25JbmRleCA9IGxpbmVzLmZpbmRJbmRleCgobGluZSkgPT4gaXNUb21sU2VjdGlvbkxpbmUobGluZSwgJ2ZlYXR1cmVzJykpO1xuICBpZiAoc2VjdGlvbkluZGV4ID49IDApIHtcbiAgICBjb25zdCBuZXh0U2VjdGlvbkluZGV4ID0gbGluZXMuZmluZEluZGV4KChsaW5lLCBpbmRleCkgPT4gaW5kZXggPiBzZWN0aW9uSW5kZXggJiYgZ2V0VG9tbExpbmVDb250ZW50KGxpbmUpLnN0YXJ0c1dpdGgoJ1snKSAmJiBnZXRUb21sTGluZUNvbnRlbnQobGluZSkuZW5kc1dpdGgoJ10nKSk7XG4gICAgY29uc3Qgc2VjdGlvbkVuZCA9IG5leHRTZWN0aW9uSW5kZXggPj0gMCA/IG5leHRTZWN0aW9uSW5kZXggOiBsaW5lcy5sZW5ndGg7XG4gICAgY29uc3Qga2V5SW5kZXggPSBsaW5lcy5maW5kSW5kZXgoKGxpbmUsIGluZGV4KSA9PiBpbmRleCA+IHNlY3Rpb25JbmRleCAmJiBpbmRleCA8IHNlY3Rpb25FbmQgJiYgcGFyc2VUb21sQm9vbGVhbkFzc2lnbm1lbnQobGluZSwgJ2NvZGV4X2hvb2tzJykgIT09IG51bGwpO1xuXG4gICAgaWYgKGtleUluZGV4ID49IDApIHtcbiAgICAgIGlmIChwYXJzZVRvbWxCb29sZWFuQXNzaWdubWVudChsaW5lc1trZXlJbmRleF0sICdjb2RleF9ob29rcycpID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlLCBjb250ZW50OiByYXcgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZWRMaW5lcyA9IFsuLi5saW5lc107XG4gICAgICB1cGRhdGVkTGluZXNba2V5SW5kZXhdID0gdXBkYXRlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KHVwZGF0ZWRMaW5lc1trZXlJbmRleF0sICdjb2RleF9ob29rcycsIHRydWUpO1xuICAgICAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgY29udGVudDogYCR7c3RyaXBUcmFpbGluZ05ld2xpbmVzKHVwZGF0ZWRMaW5lcy5qb2luKCdcXG4nKSl9XFxuYCB9O1xuICAgIH1cblxuICAgIGNvbnN0IHVwZGF0ZWRMaW5lcyA9IFsuLi5saW5lc107XG4gICAgdXBkYXRlZExpbmVzLnNwbGljZShzZWN0aW9uSW5kZXggKyAxLCAwLCAnY29kZXhfaG9va3MgPSB0cnVlJyk7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgY29udGVudDogYCR7c3RyaXBUcmFpbGluZ05ld2xpbmVzKHVwZGF0ZWRMaW5lcy5qb2luKCdcXG4nKSl9XFxuYCB9O1xuICB9XG5cbiAgY29uc3QgcHJlZml4ID0gcmF3LnRyaW0oKS5sZW5ndGggPiAwID8gYCR7c3RyaXBUcmFpbGluZ05ld2xpbmVzKHJhdyl9XFxuXFxuYCA6ICcnO1xuICByZXR1cm4ge1xuICAgIGNoYW5nZWQ6IHRydWUsXG4gICAgY29udGVudDogYCR7cHJlZml4fVtmZWF0dXJlc11cXG5jb2RleF9ob29rcyA9IHRydWVcXG5gLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUNvZGV4Q29uZmlnKGNvbmZpZ1BhdGg6IHN0cmluZyk6IFByb21pc2U8eyBjaGFuZ2VkOiBib29sZWFuOyBiYWNrdXBQYXRoPzogc3RyaW5nIH0+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShjb25maWdQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChjb25maWdQYXRoLCAnJyk7XG5cbiAgY29uc3QgeyBjaGFuZ2VkLCBjb250ZW50IH0gPSBlbnN1cmVDb2RleEhvb2tzRW5hYmxlZChyYXcpO1xuICBpZiAoIWNoYW5nZWQpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IHdyaXRlQmFja3VwSWZQcmVzZW50KGNvbmZpZ1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKGNvbmZpZ1BhdGgsIGNvbnRlbnQsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdyaXRlSG9va01hcmtlcihcbiAgaG9tZURpcjogc3RyaW5nLFxuICBtYXJrZXI6IFBlcm1pc3Npb25Ib29rTWFya2VyLFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGdldFBlcm1pc3Npb25Ib29rTWFya2VyUGF0aChob21lRGlyLCBtYXJrZXIuaG9zdCk7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUobWFya2VyUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICBhd2FpdCB3cml0ZUZpbGUobWFya2VyUGF0aCwgSlNPTi5zdHJpbmdpZnkobWFya2VyLCBudWxsLCAyKSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIG1hcmtlclBhdGg7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxIb29rQXNzZXRzRm9ySG9zdChcbiAgY2xpZW50OiBzdHJpbmcsXG4gIGhvbWVEaXI6IHN0cmluZyxcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8eyBzY3JpcHRQYXRoOiBzdHJpbmcgfT4ge1xuICBjb25zdCBub3JtYWxpemVkQ2xpZW50ID0gbm9ybWFsaXplSG9va0hvc3QoY2xpZW50KTtcbiAgY29uc3Qgc2hhcmVkVGFyZ2V0UGF0aCA9IGdldFBlcm1pc3Npb25Ib29rU2NyaXB0UGF0aChob21lRGlyKTtcbiAgY29uc3Qgc2hhcmVkU291cmNlUGF0aCA9IHNvdXJjZVNjcmlwdFBhdGggPz8gam9pbihyZXBvUm9vdEZyb21Nb2R1bGUoKSwgJ3NjcmlwdHMnLCAncHJldG9vbHVzZS1kb2xsaG91c2Uuc2gnKTtcblxuICBjb25zdCBzaGFyZWRTdGF0ID0gc3RhdFN5bmMoc2hhcmVkU291cmNlUGF0aCk7XG4gIGlmICghc2hhcmVkU3RhdC5pc0ZpbGUoKSkge1xuICAgIGxvZ2dlci53YXJuKGBbUGVybWlzc2lvbkhvb2tzXSBTaGFyZWQgaG9vayBicmlkZ2UgbWlzc2luZyBmb3IgJHtub3JtYWxpemVkQ2xpZW50fTogJHtzaGFyZWRTb3VyY2VQYXRofWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgUGVybWlzc2lvbiBob29rIHNvdXJjZSBzY3JpcHQgbm90IGZvdW5kOiAke3NoYXJlZFNvdXJjZVBhdGh9YCk7XG4gIH1cbiAgYXdhaXQgY29weUhvb2tBc3NldChzaGFyZWRTb3VyY2VQYXRoLCBzaGFyZWRUYXJnZXRQYXRoKTtcblxuICBjb25zdCB3cmFwcGVyVGFyZ2V0UGF0aCA9IGdldEhvb2tXcmFwcGVyUGF0aChub3JtYWxpemVkQ2xpZW50LCBob21lRGlyKTtcbiAgaWYgKCF3cmFwcGVyVGFyZ2V0UGF0aCkge1xuICAgIHJldHVybiB7IHNjcmlwdFBhdGg6IHNoYXJlZFRhcmdldFBhdGggfTtcbiAgfVxuXG4gIGNvbnN0IHdyYXBwZXJTb3VyY2VQYXRoID0gZ2V0SG9va1NvdXJjZVBhdGgobm9ybWFsaXplZENsaWVudCk7XG4gIGNvbnN0IHdyYXBwZXJTdGF0ID0gc3RhdFN5bmMod3JhcHBlclNvdXJjZVBhdGgpO1xuICBpZiAoIXdyYXBwZXJTdGF0LmlzRmlsZSgpKSB7XG4gICAgbG9nZ2VyLndhcm4oYFtQZXJtaXNzaW9uSG9va3NdIFdyYXBwZXIgaG9vayBzY3JpcHQgbWlzc2luZyBmb3IgJHtub3JtYWxpemVkQ2xpZW50fTogJHt3cmFwcGVyU291cmNlUGF0aH1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFBlcm1pc3Npb24gaG9vayB3cmFwcGVyIHNjcmlwdCBub3QgZm91bmQ6ICR7d3JhcHBlclNvdXJjZVBhdGh9YCk7XG4gIH1cbiAgYXdhaXQgY29weUhvb2tBc3NldCh3cmFwcGVyU291cmNlUGF0aCwgd3JhcHBlclRhcmdldFBhdGgpO1xuICByZXR1cm4geyBzY3JpcHRQYXRoOiB3cmFwcGVyVGFyZ2V0UGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsQ2xhdWRlQ29kZVBlcm1pc3Npb25Ib29rKFxuICBob21lRGlyOiBzdHJpbmcsXG4gIGluc3RhbGxlZEF0OiBzdHJpbmcsXG4gIHNvdXJjZVNjcmlwdFBhdGg/OiBzdHJpbmcsXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCBob3N0ID0gJ2NsYXVkZS1jb2RlJztcbiAgY29uc3QgeyBzY3JpcHRQYXRoIH0gPSBhd2FpdCBpbnN0YWxsSG9va0Fzc2V0c0Zvckhvc3QoaG9zdCwgaG9tZURpciwgc291cmNlU2NyaXB0UGF0aCk7XG4gIGNvbnN0IHNldHRpbmdzUGF0aCA9IGdldENsYXVkZUhvb2tTZXR0aW5nc1BhdGgoaG9tZURpcik7XG4gIGNvbnN0IHNldHRpbmdzUmVzdWx0ID0gYXdhaXQgbWVyZ2VDbGF1ZGVTZXR0aW5ncyhzZXR0aW5nc1BhdGgsIGBiYXNoICR7c2NyaXB0UGF0aH1gKTtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGF3YWl0IHdyaXRlSG9va01hcmtlcihob21lRGlyLCB7XG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGluc3RhbGxlZEF0LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIG1hcmtlclBhdGgsXG4gICAgYmFja3VwUGF0aDogc2V0dGluZ3NSZXN1bHQuYmFja3VwUGF0aCxcbiAgICBtZXNzYWdlOiAnSW5zdGFsbGVkIENsYXVkZSBDb2RlIHBlcm1pc3Npb24gaG9vayBhbmQgdXBkYXRlZCBzZXR0aW5ncy5qc29uLicsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxWc0NvZGVQZXJtaXNzaW9uSG9vayhcbiAgaG9tZURpcjogc3RyaW5nLFxuICBpbnN0YWxsZWRBdDogc3RyaW5nLFxuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nLFxuKTogUHJvbWlzZTxJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQ+IHtcbiAgY29uc3QgaG9zdCA9ICd2c2NvZGUnO1xuICBjb25zdCB7IHNjcmlwdFBhdGggfSA9IGF3YWl0IGluc3RhbGxIb29rQXNzZXRzRm9ySG9zdChob3N0LCBob21lRGlyLCBzb3VyY2VTY3JpcHRQYXRoKTtcbiAgY29uc3Qgc2V0dGluZ3NQYXRoID0gZ2V0VnNDb2RlSG9va1NldHRpbmdzUGF0aChob21lRGlyKTtcbiAgY29uc3QgdXNlclNldHRpbmdzUGF0aCA9IGdldFZzQ29kZVVzZXJTZXR0aW5nc1BhdGgoaG9tZURpcik7XG4gIGNvbnN0IGhvb2tSZXN1bHQgPSBhd2FpdCBtZXJnZVZzQ29kZUhvb2tTZXR0aW5ncyhzZXR0aW5nc1BhdGgsIGBiYXNoICR7c2NyaXB0UGF0aH1gKTtcbiAgY29uc3QgdXNlclNldHRpbmdzUmVzdWx0ID0gYXdhaXQgbWVyZ2VWc0NvZGVVc2VyU2V0dGluZ3ModXNlclNldHRpbmdzUGF0aCk7XG4gIGNvbnN0IG1hcmtlclBhdGggPSBhd2FpdCB3cml0ZUhvb2tNYXJrZXIoaG9tZURpciwge1xuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgYWRkaXRpb25hbFBhdGhzOiBbdXNlclNldHRpbmdzUGF0aF0sXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWRBdCxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdXBwb3J0ZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkOiB0cnVlLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBhZGRpdGlvbmFsUGF0aHM6IFt1c2VyU2V0dGluZ3NQYXRoXSxcbiAgICBtYXJrZXJQYXRoLFxuICAgIGJhY2t1cFBhdGg6IGhvb2tSZXN1bHQuYmFja3VwUGF0aCA/PyB1c2VyU2V0dGluZ3NSZXN1bHQuYmFja3VwUGF0aCxcbiAgICBtZXNzYWdlOiAnSW5zdGFsbGVkIFZTIENvZGUgcGVybWlzc2lvbiBob29rIGFuZCBlbmFibGVkIGNoYXQuaG9va0ZpbGVzTG9jYXRpb25zIGZvciB+Ly5jb3BpbG90L2hvb2tzLicsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxHZW1pbmlDbGlQZXJtaXNzaW9uSG9vayhcbiAgaG9tZURpcjogc3RyaW5nLFxuICBpbnN0YWxsZWRBdDogc3RyaW5nLFxuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nLFxuKTogUHJvbWlzZTxJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQ+IHtcbiAgY29uc3QgaG9zdCA9ICdnZW1pbmktY2xpJztcbiAgY29uc3QgeyBzY3JpcHRQYXRoIH0gPSBhd2FpdCBpbnN0YWxsSG9va0Fzc2V0c0Zvckhvc3QoaG9zdCwgaG9tZURpciwgc291cmNlU2NyaXB0UGF0aCk7XG4gIGNvbnN0IHNldHRpbmdzUGF0aCA9IGdldEdlbWluaUhvb2tTZXR0aW5nc1BhdGgoaG9tZURpcik7XG4gIGNvbnN0IHNldHRpbmdzUmVzdWx0ID0gYXdhaXQgbWVyZ2VHZW1pbmlTZXR0aW5ncyhzZXR0aW5nc1BhdGgsIGBiYXNoICR7c2NyaXB0UGF0aH1gKTtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGF3YWl0IHdyaXRlSG9va01hcmtlcihob21lRGlyLCB7XG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGluc3RhbGxlZEF0LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIG1hcmtlclBhdGgsXG4gICAgYmFja3VwUGF0aDogc2V0dGluZ3NSZXN1bHQuYmFja3VwUGF0aCxcbiAgICBtZXNzYWdlOiAnSW5zdGFsbGVkIEdlbWluaSBDTEkgcGVybWlzc2lvbiBob29rIGFuZCB1cGRhdGVkIHNldHRpbmdzLmpzb24uJyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEN1cnNvclBlcm1pc3Npb25Ib29rKFxuICBob21lRGlyOiBzdHJpbmcsXG4gIGluc3RhbGxlZEF0OiBzdHJpbmcsXG4gIHNvdXJjZVNjcmlwdFBhdGg/OiBzdHJpbmcsXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCBob3N0ID0gJ2N1cnNvcic7XG4gIGNvbnN0IHsgc2NyaXB0UGF0aCB9ID0gYXdhaXQgaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0KGhvc3QsIGhvbWVEaXIsIHNvdXJjZVNjcmlwdFBhdGgpO1xuICBjb25zdCBzZXR0aW5nc1BhdGggPSBnZXRDdXJzb3JIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIpO1xuICBjb25zdCBzZXR0aW5nc1Jlc3VsdCA9IGF3YWl0IG1lcmdlQ3Vyc29ySG9va3Moc2V0dGluZ3NQYXRoLCBgYmFzaCAke3NjcmlwdFBhdGh9YCk7XG4gIGNvbnN0IG1hcmtlclBhdGggPSBhd2FpdCB3cml0ZUhvb2tNYXJrZXIoaG9tZURpciwge1xuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWRBdCxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdXBwb3J0ZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkOiB0cnVlLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBtYXJrZXJQYXRoLFxuICAgIGJhY2t1cFBhdGg6IHNldHRpbmdzUmVzdWx0LmJhY2t1cFBhdGgsXG4gICAgbWVzc2FnZTogJ0luc3RhbGxlZCBDdXJzb3IgcGVybWlzc2lvbiBob29rIGFuZCB1cGRhdGVkIGhvb2tzLmpzb24uJyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbFdpbmRzdXJmUGVybWlzc2lvbkhvb2soXG4gIGhvbWVEaXI6IHN0cmluZyxcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZyxcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8SW5zdGFsbFBlcm1pc3Npb25Ib29rUmVzdWx0PiB7XG4gIGNvbnN0IGhvc3QgPSAnd2luZHN1cmYnO1xuICBjb25zdCB7IHNjcmlwdFBhdGggfSA9IGF3YWl0IGluc3RhbGxIb29rQXNzZXRzRm9ySG9zdChob3N0LCBob21lRGlyLCBzb3VyY2VTY3JpcHRQYXRoKTtcbiAgY29uc3Qgc2V0dGluZ3NQYXRoID0gZ2V0V2luZHN1cmZIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIpO1xuICBjb25zdCBzZXR0aW5nc1Jlc3VsdCA9IGF3YWl0IG1lcmdlV2luZHN1cmZIb29rcyhzZXR0aW5nc1BhdGgsIGBiYXNoICR7c2NyaXB0UGF0aH1gKTtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGF3YWl0IHdyaXRlSG9va01hcmtlcihob21lRGlyLCB7XG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGluc3RhbGxlZEF0LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIG1hcmtlclBhdGgsXG4gICAgYmFja3VwUGF0aDogc2V0dGluZ3NSZXN1bHQuYmFja3VwUGF0aCxcbiAgICBtZXNzYWdlOiAnSW5zdGFsbGVkIFdpbmRzdXJmIHBlcm1pc3Npb24gaG9va3MgYW5kIHVwZGF0ZWQgaG9va3MuanNvbi4nLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsQ29kZXhQZXJtaXNzaW9uSG9vayhcbiAgaG9tZURpcjogc3RyaW5nLFxuICBpbnN0YWxsZWRBdDogc3RyaW5nLFxuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nLFxuKTogUHJvbWlzZTxJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQ+IHtcbiAgY29uc3QgaG9zdCA9ICdjb2RleCc7XG4gIGNvbnN0IHsgc2NyaXB0UGF0aCB9ID0gYXdhaXQgaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0KGhvc3QsIGhvbWVEaXIsIHNvdXJjZVNjcmlwdFBhdGgpO1xuICBjb25zdCBzZXR0aW5nc1BhdGggPSBnZXRDb2RleEhvb2tTZXR0aW5nc1BhdGgoaG9tZURpcik7XG4gIGNvbnN0IGNvbmZpZ1BhdGggPSBnZXRDb2RleENvbmZpZ1BhdGgoaG9tZURpcik7XG4gIGNvbnN0IGhvb2tzUmVzdWx0ID0gYXdhaXQgbWVyZ2VDb2RleEhvb2tzKHNldHRpbmdzUGF0aCwgYGJhc2ggJHtzY3JpcHRQYXRofWApO1xuICBjb25zdCBjb25maWdSZXN1bHQgPSBhd2FpdCBtZXJnZUNvZGV4Q29uZmlnKGNvbmZpZ1BhdGgpO1xuICBjb25zdCBtYXJrZXJQYXRoID0gYXdhaXQgd3JpdGVIb29rTWFya2VyKGhvbWVEaXIsIHtcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGFkZGl0aW9uYWxQYXRoczogW2NvbmZpZ1BhdGhdLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkQXQsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgc3VwcG9ydGVkOiB0cnVlLFxuICAgIGluc3RhbGxlZDogdHJ1ZSxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgYWRkaXRpb25hbFBhdGhzOiBbY29uZmlnUGF0aF0sXG4gICAgbWFya2VyUGF0aCxcbiAgICBiYWNrdXBQYXRoOiBob29rc1Jlc3VsdC5iYWNrdXBQYXRoID8/IGNvbmZpZ1Jlc3VsdC5iYWNrdXBQYXRoLFxuICAgIG1lc3NhZ2U6ICdJbnN0YWxsZWQgQ29kZXggQmFzaCBwZXJtaXNzaW9uIGhvb2ssIGNyZWF0ZWQgaG9va3MuanNvbiwgYW5kIGVuYWJsZWQgZmVhdHVyZXMuY29kZXhfaG9va3MgaW4gY29uZmlnLnRvbWwuJyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbE1hbnVhbFBlcm1pc3Npb25Ib29rQXNzZXRzKFxuICBub3JtYWxpemVkQ2xpZW50OiBzdHJpbmcsXG4gIGhvbWVEaXI6IHN0cmluZyxcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZyxcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8SW5zdGFsbFBlcm1pc3Npb25Ib29rUmVzdWx0PiB7XG4gIGNvbnN0IHsgc2NyaXB0UGF0aCB9ID0gYXdhaXQgaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0KG5vcm1hbGl6ZWRDbGllbnQsIGhvbWVEaXIsIHNvdXJjZVNjcmlwdFBhdGgpO1xuICBjb25zdCBtYXJrZXJQYXRoID0gYXdhaXQgd3JpdGVIb29rTWFya2VyKGhvbWVEaXIsIHtcbiAgICBob3N0OiBub3JtYWxpemVkQ2xpZW50LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoOiB1bmRlZmluZWQsXG4gICAgY29uZmlndXJlZDogZmFsc2UsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkQXQsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgc3VwcG9ydGVkOiB0cnVlLFxuICAgIGluc3RhbGxlZDogdHJ1ZSxcbiAgICBjb25maWd1cmVkOiBmYWxzZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBob3N0OiBub3JtYWxpemVkQ2xpZW50LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgbWFya2VyUGF0aCxcbiAgICBtZXNzYWdlOiBgSW5zdGFsbGVkIERvbGxob3VzZSBwZXJtaXNzaW9uIGhvb2sgYXNzZXRzIGZvciAke25vcm1hbGl6ZWRDbGllbnR9LiBGaW5pc2ggdGhlIGNsaWVudC1zcGVjaWZpYyBob29rIHJlZ2lzdHJhdGlvbiBtYW51YWxseS5gLFxuICB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW5zdGFsbFBlcm1pc3Npb25Ib29rKFxuICBjbGllbnQ6IHN0cmluZyxcbiAgb3B0aW9uczogSW5zdGFsbFBlcm1pc3Npb25Ib29rT3B0aW9ucyA9IHt9LFxuKTogUHJvbWlzZTxJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQ+IHtcbiAgY29uc3Qgbm9ybWFsaXplZENsaWVudCA9IG5vcm1hbGl6ZUhvb2tIb3N0KGNsaWVudCk7XG4gIGNvbnN0IGhvbWVEaXIgPSBvcHRpb25zLmhvbWVEaXIgPz8gaG9tZWRpcigpO1xuICBjb25zdCBpbnN0YWxsZWRBdCA9IChvcHRpb25zLm5vdyA/PyBuZXcgRGF0ZSgpKS50b0lTT1N0cmluZygpO1xuXG4gIGlmIChub3JtYWxpemVkQ2xpZW50ID09PSAnY2xhdWRlLWNvZGUnKSB7XG4gICAgcmV0dXJuIGluc3RhbGxDbGF1ZGVDb2RlUGVybWlzc2lvbkhvb2soaG9tZURpciwgaW5zdGFsbGVkQXQsIG9wdGlvbnMuc291cmNlU2NyaXB0UGF0aCk7XG4gIH1cblxuICBpZiAobm9ybWFsaXplZENsaWVudCA9PT0gJ3ZzY29kZScpIHtcbiAgICByZXR1cm4gaW5zdGFsbFZzQ29kZVBlcm1pc3Npb25Ib29rKGhvbWVEaXIsIGluc3RhbGxlZEF0LCBvcHRpb25zLnNvdXJjZVNjcmlwdFBhdGgpO1xuICB9XG5cbiAgaWYgKG5vcm1hbGl6ZWRDbGllbnQgPT09ICdnZW1pbmktY2xpJykge1xuICAgIHJldHVybiBpbnN0YWxsR2VtaW5pQ2xpUGVybWlzc2lvbkhvb2soaG9tZURpciwgaW5zdGFsbGVkQXQsIG9wdGlvbnMuc291cmNlU2NyaXB0UGF0aCk7XG4gIH1cblxuICBpZiAobm9ybWFsaXplZENsaWVudCA9PT0gJ2N1cnNvcicpIHtcbiAgICByZXR1cm4gaW5zdGFsbEN1cnNvclBlcm1pc3Npb25Ib29rKGhvbWVEaXIsIGluc3RhbGxlZEF0LCBvcHRpb25zLnNvdXJjZVNjcmlwdFBhdGgpO1xuICB9XG5cbiAgaWYgKG5vcm1hbGl6ZWRDbGllbnQgPT09ICd3aW5kc3VyZicpIHtcbiAgICByZXR1cm4gaW5zdGFsbFdpbmRzdXJmUGVybWlzc2lvbkhvb2soaG9tZURpciwgaW5zdGFsbGVkQXQsIG9wdGlvbnMuc291cmNlU2NyaXB0UGF0aCk7XG4gIH1cblxuICBpZiAobm9ybWFsaXplZENsaWVudCA9PT0gJ2NvZGV4Jykge1xuICAgIHJldHVybiBpbnN0YWxsQ29kZXhQZXJtaXNzaW9uSG9vayhob21lRGlyLCBpbnN0YWxsZWRBdCwgb3B0aW9ucy5zb3VyY2VTY3JpcHRQYXRoKTtcbiAgfVxuXG4gIGlmIChnZXRIb29rV3JhcHBlckJhc2VuYW1lKG5vcm1hbGl6ZWRDbGllbnQpKSB7XG4gICAgcmV0dXJuIGluc3RhbGxNYW51YWxQZXJtaXNzaW9uSG9va0Fzc2V0cyhub3JtYWxpemVkQ2xpZW50LCBob21lRGlyLCBpbnN0YWxsZWRBdCwgb3B0aW9ucy5zb3VyY2VTY3JpcHRQYXRoKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgc3VwcG9ydGVkOiBmYWxzZSxcbiAgICBpbnN0YWxsZWQ6IGZhbHNlLFxuICAgIGNvbmZpZ3VyZWQ6IGZhbHNlLFxuICAgIGhvc3Q6IG5vcm1hbGl6ZWRDbGllbnQsXG4gICAgbWVzc2FnZTogYEF1dG9tYXRpYyBwZXJtaXNzaW9uIGhvb2sgd2lyaW5nIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciAke25vcm1hbGl6ZWRDbGllbnR9LmAsXG4gIH07XG59XG4iXX0=