@dollhousemcp/mcp-server 2.0.29 → 2.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +3 -3
- package/dist/services/BuildInfoService.d.ts +3 -0
- package/dist/services/BuildInfoService.d.ts.map +1 -1
- package/dist/services/BuildInfoService.js +19 -5
- package/dist/utils/permissionHookInstallers.d.ts +27 -0
- package/dist/utils/permissionHookInstallers.d.ts.map +1 -0
- package/dist/utils/permissionHookInstallers.js +465 -0
- package/dist/utils/permissionHookShared.d.ts +126 -0
- package/dist/utils/permissionHookShared.d.ts.map +1 -0
- package/dist/utils/permissionHookShared.js +388 -0
- package/dist/utils/permissionHookStatus.d.ts +10 -0
- package/dist/utils/permissionHookStatus.d.ts.map +1 -0
- package/dist/utils/permissionHookStatus.js +256 -0
- package/dist/utils/permissionHooks.d.ts +3 -91
- package/dist/utils/permissionHooks.d.ts.map +1 -1
- package/dist/utils/permissionHooks.js +4 -947
- package/dist/web/routes/healthRoutes.d.ts +3 -0
- package/dist/web/routes/healthRoutes.d.ts.map +1 -1
- package/dist/web/routes/healthRoutes.js +22 -2
- package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
- package/dist/web/routes/permissionRoutes.js +13 -2
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +9 -2
- package/package.json +3 -1
- package/scripts/permission-hook-config.sh +67 -0
- package/scripts/pretooluse-dollhouse.sh +42 -13
- package/scripts/pretooluse-vscode.sh +23 -10
- package/scripts/pretooluse-windsurf.sh +6 -6
- package/server.json +2 -2
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
import { dirname } from 'node:path';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { detectIndent, ensureCommandHook, getClaudeHookSettingsPath, getCodexConfigPath, getCodexHookSettingsPath, getCursorHookSettingsPath, getGeminiHookSettingsPath, getHookWrapperBasename, normalizeHooksRoot, getVsCodeHookSettingsPath, getVsCodeUserSettingsPath, getWindsurfHookSettingsPath, installHookAssetsForHost, normalizeHookHost, readOptionalUtf8, writeHookMarker, writeBackupIfPresent, } from './permissionHookShared.js';
|
|
5
|
+
import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
|
|
6
|
+
function normalizePermissionHookClient(client) {
|
|
7
|
+
const normalizedClient = UnicodeValidator.normalize(client).normalizedContent;
|
|
8
|
+
return normalizeHookHost(normalizedClient);
|
|
9
|
+
}
|
|
10
|
+
export function ensureClaudePreToolUseHook(parsed, command) {
|
|
11
|
+
return ensureCommandHook(parsed, 'PreToolUse', command, '*');
|
|
12
|
+
}
|
|
13
|
+
export function ensureVsCodePreToolUseHook(parsed, command) {
|
|
14
|
+
return ensureCommandHook(parsed, 'PreToolUse', command, '*');
|
|
15
|
+
}
|
|
16
|
+
export function ensureGeminiBeforeToolHook(parsed, command) {
|
|
17
|
+
return ensureCommandHook(parsed, 'BeforeTool', command, '.*');
|
|
18
|
+
}
|
|
19
|
+
export function ensureCodexPreToolUseHook(parsed, command) {
|
|
20
|
+
return ensureCommandHook(parsed, 'PreToolUse', command, 'Bash', {
|
|
21
|
+
statusMessage: 'Checking Bash permissions',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function ensureCursorPreToolUseHook(parsed, command) {
|
|
25
|
+
if (parsed.version !== 1) {
|
|
26
|
+
parsed.version = 1;
|
|
27
|
+
}
|
|
28
|
+
const hooksRoot = normalizeHooksRoot(parsed);
|
|
29
|
+
const existingEntries = Array.isArray(hooksRoot.preToolUse)
|
|
30
|
+
? hooksRoot.preToolUse.filter((entry) => typeof entry === 'object' && entry !== null)
|
|
31
|
+
: [];
|
|
32
|
+
hooksRoot.preToolUse = existingEntries;
|
|
33
|
+
const commandExists = existingEntries.some((entry) => entry.command === command
|
|
34
|
+
&& (entry.type === 'command' || entry.type === undefined));
|
|
35
|
+
if (commandExists) {
|
|
36
|
+
return { changed: false, parsed };
|
|
37
|
+
}
|
|
38
|
+
existingEntries.push({
|
|
39
|
+
type: 'command',
|
|
40
|
+
command,
|
|
41
|
+
matcher: '.*',
|
|
42
|
+
});
|
|
43
|
+
return { changed: true, parsed };
|
|
44
|
+
}
|
|
45
|
+
export function ensureWindsurfHooks(parsed, command) {
|
|
46
|
+
const hooksRoot = normalizeHooksRoot(parsed);
|
|
47
|
+
let changed = false;
|
|
48
|
+
const ensureEventHook = (eventName) => {
|
|
49
|
+
const existingEntries = Array.isArray(hooksRoot[eventName])
|
|
50
|
+
? hooksRoot[eventName].filter((entry) => typeof entry === 'object' && entry !== null)
|
|
51
|
+
: [];
|
|
52
|
+
hooksRoot[eventName] = existingEntries;
|
|
53
|
+
const commandExists = existingEntries.some((entry) => entry.command === command && (entry.type === 'command' || entry.type === undefined));
|
|
54
|
+
if (commandExists) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
existingEntries.push({
|
|
58
|
+
type: 'command',
|
|
59
|
+
command,
|
|
60
|
+
});
|
|
61
|
+
changed = true;
|
|
62
|
+
};
|
|
63
|
+
ensureEventHook('pre_run_command');
|
|
64
|
+
ensureEventHook('pre_mcp_tool_use');
|
|
65
|
+
return { changed, parsed };
|
|
66
|
+
}
|
|
67
|
+
async function mergeClaudeSettings(settingsPath, command) {
|
|
68
|
+
await mkdir(dirname(settingsPath), { recursive: true });
|
|
69
|
+
const raw = await readOptionalUtf8(settingsPath, '{}\n');
|
|
70
|
+
const indent = detectIndent(raw);
|
|
71
|
+
const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
|
|
72
|
+
const { changed, parsed: updated } = ensureClaudePreToolUseHook(parsed, command);
|
|
73
|
+
if (!changed) {
|
|
74
|
+
return { changed: false };
|
|
75
|
+
}
|
|
76
|
+
const backupPath = await writeBackupIfPresent(settingsPath, raw);
|
|
77
|
+
await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
|
|
78
|
+
return { changed: true, backupPath };
|
|
79
|
+
}
|
|
80
|
+
async function mergeVsCodeHookSettings(settingsPath, command) {
|
|
81
|
+
await mkdir(dirname(settingsPath), { recursive: true });
|
|
82
|
+
const raw = await readOptionalUtf8(settingsPath, '{}\n');
|
|
83
|
+
const indent = detectIndent(raw);
|
|
84
|
+
const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
|
|
85
|
+
const { changed, parsed: updated } = ensureVsCodePreToolUseHook(parsed, command);
|
|
86
|
+
if (!changed) {
|
|
87
|
+
return { changed: false };
|
|
88
|
+
}
|
|
89
|
+
const backupPath = await writeBackupIfPresent(settingsPath, raw);
|
|
90
|
+
await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
|
|
91
|
+
return { changed: true, backupPath };
|
|
92
|
+
}
|
|
93
|
+
async function mergeVsCodeUserSettings(settingsPath) {
|
|
94
|
+
await mkdir(dirname(settingsPath), { recursive: true });
|
|
95
|
+
const raw = await readOptionalUtf8(settingsPath, '{}\n');
|
|
96
|
+
const indent = detectIndent(raw);
|
|
97
|
+
const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
|
|
98
|
+
const current = parsed['chat.hookFilesLocations'];
|
|
99
|
+
const locations = (current && typeof current === 'object' && !Array.isArray(current))
|
|
100
|
+
? { ...current }
|
|
101
|
+
: {};
|
|
102
|
+
if (locations['~/.copilot/hooks'] === true) {
|
|
103
|
+
return { changed: false };
|
|
104
|
+
}
|
|
105
|
+
locations['~/.copilot/hooks'] = true;
|
|
106
|
+
parsed['chat.hookFilesLocations'] = locations;
|
|
107
|
+
const backupPath = await writeBackupIfPresent(settingsPath, raw);
|
|
108
|
+
await writeFile(settingsPath, JSON.stringify(parsed, null, indent) + '\n', 'utf-8');
|
|
109
|
+
return { changed: true, backupPath };
|
|
110
|
+
}
|
|
111
|
+
async function mergeGeminiSettings(settingsPath, command) {
|
|
112
|
+
await mkdir(dirname(settingsPath), { recursive: true });
|
|
113
|
+
const raw = await readOptionalUtf8(settingsPath, '{}\n');
|
|
114
|
+
const indent = detectIndent(raw);
|
|
115
|
+
const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
|
|
116
|
+
const { changed, parsed: updated } = ensureGeminiBeforeToolHook(parsed, command);
|
|
117
|
+
if (!changed) {
|
|
118
|
+
return { changed: false };
|
|
119
|
+
}
|
|
120
|
+
const backupPath = await writeBackupIfPresent(settingsPath, raw);
|
|
121
|
+
await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
|
|
122
|
+
return { changed: true, backupPath };
|
|
123
|
+
}
|
|
124
|
+
async function mergeCursorHooks(settingsPath, command) {
|
|
125
|
+
await mkdir(dirname(settingsPath), { recursive: true });
|
|
126
|
+
const raw = await readOptionalUtf8(settingsPath, '{\n "version": 1,\n "hooks": {}\n}\n');
|
|
127
|
+
const indent = detectIndent(raw);
|
|
128
|
+
const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
|
|
129
|
+
const { changed, parsed: updated } = ensureCursorPreToolUseHook(parsed, command);
|
|
130
|
+
if (!changed) {
|
|
131
|
+
return { changed: false };
|
|
132
|
+
}
|
|
133
|
+
const backupPath = await writeBackupIfPresent(settingsPath, raw);
|
|
134
|
+
await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
|
|
135
|
+
return { changed: true, backupPath };
|
|
136
|
+
}
|
|
137
|
+
async function mergeWindsurfHooks(settingsPath, command) {
|
|
138
|
+
await mkdir(dirname(settingsPath), { recursive: true });
|
|
139
|
+
const raw = await readOptionalUtf8(settingsPath, '{\n "hooks": {}\n}\n');
|
|
140
|
+
const indent = detectIndent(raw);
|
|
141
|
+
const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
|
|
142
|
+
const { changed, parsed: updated } = ensureWindsurfHooks(parsed, command);
|
|
143
|
+
if (!changed) {
|
|
144
|
+
return { changed: false };
|
|
145
|
+
}
|
|
146
|
+
const backupPath = await writeBackupIfPresent(settingsPath, raw);
|
|
147
|
+
await writeFile(settingsPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
|
|
148
|
+
return { changed: true, backupPath };
|
|
149
|
+
}
|
|
150
|
+
async function mergeCodexHooks(hooksPath, command) {
|
|
151
|
+
await mkdir(dirname(hooksPath), { recursive: true });
|
|
152
|
+
const raw = await readOptionalUtf8(hooksPath, '{}\n');
|
|
153
|
+
const indent = detectIndent(raw);
|
|
154
|
+
const parsed = raw.trim().length === 0 ? {} : JSON.parse(raw);
|
|
155
|
+
const { changed, parsed: updated } = ensureCodexPreToolUseHook(parsed, command);
|
|
156
|
+
if (!changed) {
|
|
157
|
+
return { changed: false };
|
|
158
|
+
}
|
|
159
|
+
const backupPath = await writeBackupIfPresent(hooksPath, raw);
|
|
160
|
+
await writeFile(hooksPath, JSON.stringify(updated, null, indent) + '\n', 'utf-8');
|
|
161
|
+
return { changed: true, backupPath };
|
|
162
|
+
}
|
|
163
|
+
function getTomlLineContent(line) {
|
|
164
|
+
const commentIndex = line.indexOf('#');
|
|
165
|
+
return (commentIndex >= 0 ? line.slice(0, commentIndex) : line).trim();
|
|
166
|
+
}
|
|
167
|
+
function isTomlSectionLine(line, section) {
|
|
168
|
+
return getTomlLineContent(line) === `[${section}]`;
|
|
169
|
+
}
|
|
170
|
+
function parseTomlBooleanAssignment(line, key) {
|
|
171
|
+
const content = getTomlLineContent(line);
|
|
172
|
+
if (!content.startsWith(`${key} = `)) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
const value = content.slice(`${key} = `.length).trim();
|
|
176
|
+
if (value === 'true')
|
|
177
|
+
return true;
|
|
178
|
+
if (value === 'false')
|
|
179
|
+
return false;
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
function updateTomlBooleanAssignment(line, key, nextValue) {
|
|
183
|
+
const commentIndex = line.indexOf('#');
|
|
184
|
+
const commentSuffix = commentIndex >= 0 ? line.slice(commentIndex) : '';
|
|
185
|
+
let prefixLength = 0;
|
|
186
|
+
while (prefixLength < line.length && /\s/.test(line.charAt(prefixLength))) {
|
|
187
|
+
prefixLength += 1;
|
|
188
|
+
}
|
|
189
|
+
const prefix = line.slice(0, prefixLength);
|
|
190
|
+
const assignment = `${prefix}${key} = ${nextValue ? 'true' : 'false'}`;
|
|
191
|
+
const trimmedCommentSuffix = commentSuffix.trimStart();
|
|
192
|
+
const suffix = trimmedCommentSuffix.length > 0 ? ` ${trimmedCommentSuffix}` : '';
|
|
193
|
+
return `${assignment}${suffix}`.trimEnd();
|
|
194
|
+
}
|
|
195
|
+
function stripTrailingNewlines(value) {
|
|
196
|
+
let end = value.length;
|
|
197
|
+
while (end > 0 && value.charAt(end - 1) === '\n') {
|
|
198
|
+
end -= 1;
|
|
199
|
+
}
|
|
200
|
+
return value.slice(0, end);
|
|
201
|
+
}
|
|
202
|
+
function ensureCodexHooksEnabled(raw) {
|
|
203
|
+
const lines = raw.length > 0 ? raw.split('\n') : [];
|
|
204
|
+
const dottedIndex = lines.findIndex((line) => parseTomlBooleanAssignment(line, 'features.codex_hooks') !== null);
|
|
205
|
+
if (dottedIndex >= 0) {
|
|
206
|
+
if (parseTomlBooleanAssignment(lines[dottedIndex], 'features.codex_hooks') === true) {
|
|
207
|
+
return { changed: false, content: raw };
|
|
208
|
+
}
|
|
209
|
+
const updatedLines = [...lines];
|
|
210
|
+
updatedLines[dottedIndex] = updateTomlBooleanAssignment(updatedLines[dottedIndex], 'features.codex_hooks', true);
|
|
211
|
+
return { changed: true, content: `${stripTrailingNewlines(updatedLines.join('\n'))}\n` };
|
|
212
|
+
}
|
|
213
|
+
const sectionIndex = lines.findIndex((line) => isTomlSectionLine(line, 'features'));
|
|
214
|
+
if (sectionIndex >= 0) {
|
|
215
|
+
const nextSectionIndex = lines.findIndex((line, index) => index > sectionIndex && getTomlLineContent(line).startsWith('[') && getTomlLineContent(line).endsWith(']'));
|
|
216
|
+
const sectionEnd = nextSectionIndex >= 0 ? nextSectionIndex : lines.length;
|
|
217
|
+
const keyIndex = lines.findIndex((line, index) => index > sectionIndex && index < sectionEnd && parseTomlBooleanAssignment(line, 'codex_hooks') !== null);
|
|
218
|
+
if (keyIndex >= 0) {
|
|
219
|
+
if (parseTomlBooleanAssignment(lines[keyIndex], 'codex_hooks') === true) {
|
|
220
|
+
return { changed: false, content: raw };
|
|
221
|
+
}
|
|
222
|
+
const updatedLines = [...lines];
|
|
223
|
+
updatedLines[keyIndex] = updateTomlBooleanAssignment(updatedLines[keyIndex], 'codex_hooks', true);
|
|
224
|
+
return { changed: true, content: `${stripTrailingNewlines(updatedLines.join('\n'))}\n` };
|
|
225
|
+
}
|
|
226
|
+
const updatedLines = [...lines];
|
|
227
|
+
updatedLines.splice(sectionIndex + 1, 0, 'codex_hooks = true');
|
|
228
|
+
return { changed: true, content: `${stripTrailingNewlines(updatedLines.join('\n'))}\n` };
|
|
229
|
+
}
|
|
230
|
+
const prefix = raw.trim().length > 0 ? `${stripTrailingNewlines(raw)}\n\n` : '';
|
|
231
|
+
return {
|
|
232
|
+
changed: true,
|
|
233
|
+
content: `${prefix}[features]\ncodex_hooks = true\n`,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
async function mergeCodexConfig(configPath) {
|
|
237
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
238
|
+
const raw = await readOptionalUtf8(configPath, '');
|
|
239
|
+
const { changed, content } = ensureCodexHooksEnabled(raw);
|
|
240
|
+
if (!changed) {
|
|
241
|
+
return { changed: false };
|
|
242
|
+
}
|
|
243
|
+
const backupPath = await writeBackupIfPresent(configPath, raw);
|
|
244
|
+
await writeFile(configPath, content, 'utf-8');
|
|
245
|
+
return { changed: true, backupPath };
|
|
246
|
+
}
|
|
247
|
+
async function installClaudeCodePermissionHook(homeDir, installedAt, sourceScriptPath) {
|
|
248
|
+
const host = 'claude-code';
|
|
249
|
+
const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
|
|
250
|
+
const settingsPath = getClaudeHookSettingsPath(homeDir);
|
|
251
|
+
const settingsResult = await mergeClaudeSettings(settingsPath, `bash ${scriptPath}`);
|
|
252
|
+
const markerPath = await writeHookMarker(homeDir, {
|
|
253
|
+
host,
|
|
254
|
+
scriptPath,
|
|
255
|
+
settingsPath,
|
|
256
|
+
configured: true,
|
|
257
|
+
assetsPrepared: true,
|
|
258
|
+
installedAt,
|
|
259
|
+
});
|
|
260
|
+
return {
|
|
261
|
+
supported: true,
|
|
262
|
+
installed: true,
|
|
263
|
+
configured: true,
|
|
264
|
+
assetsPrepared: true,
|
|
265
|
+
host,
|
|
266
|
+
scriptPath,
|
|
267
|
+
settingsPath,
|
|
268
|
+
markerPath,
|
|
269
|
+
backupPath: settingsResult.backupPath,
|
|
270
|
+
message: 'Installed Claude Code permission hook and updated settings.json.',
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
async function installVsCodePermissionHook(homeDir, installedAt, sourceScriptPath) {
|
|
274
|
+
const host = 'vscode';
|
|
275
|
+
const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
|
|
276
|
+
const settingsPath = getVsCodeHookSettingsPath(homeDir);
|
|
277
|
+
const userSettingsPath = getVsCodeUserSettingsPath(homeDir);
|
|
278
|
+
const hookResult = await mergeVsCodeHookSettings(settingsPath, `bash ${scriptPath}`);
|
|
279
|
+
const userSettingsResult = await mergeVsCodeUserSettings(userSettingsPath);
|
|
280
|
+
const markerPath = await writeHookMarker(homeDir, {
|
|
281
|
+
host,
|
|
282
|
+
scriptPath,
|
|
283
|
+
settingsPath,
|
|
284
|
+
additionalPaths: [userSettingsPath],
|
|
285
|
+
configured: true,
|
|
286
|
+
assetsPrepared: true,
|
|
287
|
+
installedAt,
|
|
288
|
+
});
|
|
289
|
+
return {
|
|
290
|
+
supported: true,
|
|
291
|
+
installed: true,
|
|
292
|
+
configured: true,
|
|
293
|
+
assetsPrepared: true,
|
|
294
|
+
host,
|
|
295
|
+
scriptPath,
|
|
296
|
+
settingsPath,
|
|
297
|
+
additionalPaths: [userSettingsPath],
|
|
298
|
+
markerPath,
|
|
299
|
+
backupPath: hookResult.backupPath ?? userSettingsResult.backupPath,
|
|
300
|
+
message: 'Installed VS Code permission hook and enabled chat.hookFilesLocations for ~/.copilot/hooks.',
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
async function installGeminiCliPermissionHook(homeDir, installedAt, sourceScriptPath) {
|
|
304
|
+
const host = 'gemini-cli';
|
|
305
|
+
const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
|
|
306
|
+
const settingsPath = getGeminiHookSettingsPath(homeDir);
|
|
307
|
+
const settingsResult = await mergeGeminiSettings(settingsPath, `bash ${scriptPath}`);
|
|
308
|
+
const markerPath = await writeHookMarker(homeDir, {
|
|
309
|
+
host,
|
|
310
|
+
scriptPath,
|
|
311
|
+
settingsPath,
|
|
312
|
+
configured: true,
|
|
313
|
+
assetsPrepared: true,
|
|
314
|
+
installedAt,
|
|
315
|
+
});
|
|
316
|
+
return {
|
|
317
|
+
supported: true,
|
|
318
|
+
installed: true,
|
|
319
|
+
configured: true,
|
|
320
|
+
assetsPrepared: true,
|
|
321
|
+
host,
|
|
322
|
+
scriptPath,
|
|
323
|
+
settingsPath,
|
|
324
|
+
markerPath,
|
|
325
|
+
backupPath: settingsResult.backupPath,
|
|
326
|
+
message: 'Installed Gemini CLI permission hook and updated settings.json.',
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
async function installCursorPermissionHook(homeDir, installedAt, sourceScriptPath) {
|
|
330
|
+
const host = 'cursor';
|
|
331
|
+
const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
|
|
332
|
+
const settingsPath = getCursorHookSettingsPath(homeDir);
|
|
333
|
+
const settingsResult = await mergeCursorHooks(settingsPath, `bash ${scriptPath}`);
|
|
334
|
+
const markerPath = await writeHookMarker(homeDir, {
|
|
335
|
+
host,
|
|
336
|
+
scriptPath,
|
|
337
|
+
settingsPath,
|
|
338
|
+
configured: true,
|
|
339
|
+
assetsPrepared: true,
|
|
340
|
+
installedAt,
|
|
341
|
+
});
|
|
342
|
+
return {
|
|
343
|
+
supported: true,
|
|
344
|
+
installed: true,
|
|
345
|
+
configured: true,
|
|
346
|
+
assetsPrepared: true,
|
|
347
|
+
host,
|
|
348
|
+
scriptPath,
|
|
349
|
+
settingsPath,
|
|
350
|
+
markerPath,
|
|
351
|
+
backupPath: settingsResult.backupPath,
|
|
352
|
+
message: 'Installed Cursor permission hook and updated hooks.json.',
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
async function installWindsurfPermissionHook(homeDir, installedAt, sourceScriptPath) {
|
|
356
|
+
const host = 'windsurf';
|
|
357
|
+
const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
|
|
358
|
+
const settingsPath = getWindsurfHookSettingsPath(homeDir);
|
|
359
|
+
const settingsResult = await mergeWindsurfHooks(settingsPath, `bash ${scriptPath}`);
|
|
360
|
+
const markerPath = await writeHookMarker(homeDir, {
|
|
361
|
+
host,
|
|
362
|
+
scriptPath,
|
|
363
|
+
settingsPath,
|
|
364
|
+
configured: true,
|
|
365
|
+
assetsPrepared: true,
|
|
366
|
+
installedAt,
|
|
367
|
+
});
|
|
368
|
+
return {
|
|
369
|
+
supported: true,
|
|
370
|
+
installed: true,
|
|
371
|
+
configured: true,
|
|
372
|
+
assetsPrepared: true,
|
|
373
|
+
host,
|
|
374
|
+
scriptPath,
|
|
375
|
+
settingsPath,
|
|
376
|
+
markerPath,
|
|
377
|
+
backupPath: settingsResult.backupPath,
|
|
378
|
+
message: 'Installed Windsurf permission hooks and updated hooks.json.',
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
async function installCodexPermissionHook(homeDir, installedAt, sourceScriptPath) {
|
|
382
|
+
const host = 'codex';
|
|
383
|
+
const { scriptPath } = await installHookAssetsForHost(host, homeDir, sourceScriptPath);
|
|
384
|
+
const settingsPath = getCodexHookSettingsPath(homeDir);
|
|
385
|
+
const configPath = getCodexConfigPath(homeDir);
|
|
386
|
+
const hooksResult = await mergeCodexHooks(settingsPath, `bash ${scriptPath}`);
|
|
387
|
+
const configResult = await mergeCodexConfig(configPath);
|
|
388
|
+
const markerPath = await writeHookMarker(homeDir, {
|
|
389
|
+
host,
|
|
390
|
+
scriptPath,
|
|
391
|
+
settingsPath,
|
|
392
|
+
additionalPaths: [configPath],
|
|
393
|
+
configured: true,
|
|
394
|
+
assetsPrepared: true,
|
|
395
|
+
installedAt,
|
|
396
|
+
});
|
|
397
|
+
return {
|
|
398
|
+
supported: true,
|
|
399
|
+
installed: true,
|
|
400
|
+
configured: true,
|
|
401
|
+
assetsPrepared: true,
|
|
402
|
+
host,
|
|
403
|
+
scriptPath,
|
|
404
|
+
settingsPath,
|
|
405
|
+
additionalPaths: [configPath],
|
|
406
|
+
markerPath,
|
|
407
|
+
backupPath: hooksResult.backupPath ?? configResult.backupPath,
|
|
408
|
+
message: 'Installed Codex Bash permission hook, created hooks.json, and enabled features.codex_hooks in config.toml.',
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
async function installManualPermissionHookAssets(normalizedClient, homeDir, installedAt, sourceScriptPath) {
|
|
412
|
+
const { scriptPath } = await installHookAssetsForHost(normalizedClient, homeDir, sourceScriptPath);
|
|
413
|
+
const markerPath = await writeHookMarker(homeDir, {
|
|
414
|
+
host: normalizedClient,
|
|
415
|
+
scriptPath,
|
|
416
|
+
settingsPath: undefined,
|
|
417
|
+
configured: false,
|
|
418
|
+
assetsPrepared: true,
|
|
419
|
+
installedAt,
|
|
420
|
+
});
|
|
421
|
+
return {
|
|
422
|
+
supported: true,
|
|
423
|
+
installed: true,
|
|
424
|
+
configured: false,
|
|
425
|
+
assetsPrepared: true,
|
|
426
|
+
host: normalizedClient,
|
|
427
|
+
scriptPath,
|
|
428
|
+
markerPath,
|
|
429
|
+
message: `Installed Dollhouse permission hook assets for ${normalizedClient}. Finish the client-specific hook registration manually.`,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
export async function installPermissionHook(client, options = {}) {
|
|
433
|
+
const normalizedClient = normalizePermissionHookClient(client);
|
|
434
|
+
const homeDir = options.homeDir ?? homedir();
|
|
435
|
+
const installedAt = (options.now ?? new Date()).toISOString();
|
|
436
|
+
if (normalizedClient === 'claude-code') {
|
|
437
|
+
return installClaudeCodePermissionHook(homeDir, installedAt, options.sourceScriptPath);
|
|
438
|
+
}
|
|
439
|
+
if (normalizedClient === 'vscode') {
|
|
440
|
+
return installVsCodePermissionHook(homeDir, installedAt, options.sourceScriptPath);
|
|
441
|
+
}
|
|
442
|
+
if (normalizedClient === 'gemini-cli') {
|
|
443
|
+
return installGeminiCliPermissionHook(homeDir, installedAt, options.sourceScriptPath);
|
|
444
|
+
}
|
|
445
|
+
if (normalizedClient === 'cursor') {
|
|
446
|
+
return installCursorPermissionHook(homeDir, installedAt, options.sourceScriptPath);
|
|
447
|
+
}
|
|
448
|
+
if (normalizedClient === 'windsurf') {
|
|
449
|
+
return installWindsurfPermissionHook(homeDir, installedAt, options.sourceScriptPath);
|
|
450
|
+
}
|
|
451
|
+
if (normalizedClient === 'codex') {
|
|
452
|
+
return installCodexPermissionHook(homeDir, installedAt, options.sourceScriptPath);
|
|
453
|
+
}
|
|
454
|
+
if (getHookWrapperBasename(normalizedClient)) {
|
|
455
|
+
return installManualPermissionHookAssets(normalizedClient, homeDir, installedAt, options.sourceScriptPath);
|
|
456
|
+
}
|
|
457
|
+
return {
|
|
458
|
+
supported: false,
|
|
459
|
+
installed: false,
|
|
460
|
+
configured: false,
|
|
461
|
+
host: normalizedClient,
|
|
462
|
+
message: `Automatic permission hook wiring is not yet supported for ${normalizedClient}.`,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvbkhvb2tJbnN0YWxsZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL3Blcm1pc3Npb25Ib29rSW5zdGFsbGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDbEMsT0FBTyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNwRCxPQUFPLEVBR0wsWUFBWSxFQUNaLGlCQUFpQixFQUNqQix5QkFBeUIsRUFDekIsa0JBQWtCLEVBQ2xCLHdCQUF3QixFQUN4Qix5QkFBeUIsRUFDekIseUJBQXlCLEVBQ3pCLHNCQUFzQixFQUN0QixrQkFBa0IsRUFDbEIseUJBQXlCLEVBQ3pCLHlCQUF5QixFQUN6QiwyQkFBMkIsRUFDM0Isd0JBQXdCLEVBQ3hCLGlCQUFpQixFQUNqQixnQkFBZ0IsRUFDaEIsZUFBZSxFQUNmLG9CQUFvQixHQUNyQixNQUFNLDJCQUEyQixDQUFDO0FBQ25DLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBRTlFLFNBQVMsNkJBQTZCLENBQUMsTUFBYztJQUNuRCxNQUFNLGdCQUFnQixHQUFHLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQztJQUM5RSxPQUFPLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUVELE1BQU0sVUFBVSwwQkFBMEIsQ0FDeEMsTUFBK0IsRUFDL0IsT0FBZTtJQUVmLE9BQU8saUJBQWlCLENBQUMsTUFBTSxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDL0QsQ0FBQztBQUVELE1BQU0sVUFBVSwwQkFBMEIsQ0FDeEMsTUFBK0IsRUFDL0IsT0FBZTtJQUVmLE9B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LENBQUMsQ0FBQztJQUM3RyxDQUFDO0lBRUQsT0FBTztRQUNMLFNBQVMsRUFBRSxLQUFLO1FBQ2hCLFNBQVMsRUFBRSxLQUFLO1FBQ2hCLFVBQVUsRUFBRSxLQUFLO1FBQ2pCLElBQUksRUFBRSxnQkFBZ0I7UUFDdEIsT0FBTyxFQUFFLDZEQUE2RCxnQkFBZ0IsR0FBRztLQUMxRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRpcm5hbWUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgaG9tZWRpciB9IGZyb20gJ25vZGU6b3MnO1xuaW1wb3J0IHsgbWtkaXIsIHdyaXRlRmlsZSB9IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnO1xuaW1wb3J0IHtcbiAgdHlwZSBJbnN0YWxsUGVybWlzc2lvbkhvb2tPcHRpb25zLFxuICB0eXBlIEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdCxcbiAgZGV0ZWN0SW5kZW50LFxuICBlbnN1cmVDb21tYW5kSG9vayxcbiAgZ2V0Q2xhdWRlSG9va1NldHRpbmdzUGF0aCxcbiAgZ2V0Q29kZXhDb25maWdQYXRoLFxuICBnZXRDb2RleEhvb2tTZXR0aW5nc1BhdGgsXG4gIGdldEN1cnNvckhvb2tTZXR0aW5nc1BhdGgsXG4gIGdldEdlbWluaUhvb2tTZXR0aW5nc1BhdGgsXG4gIGdldEhvb2tXcmFwcGVyQmFzZW5hbWUsXG4gIG5vcm1hbGl6ZUhvb2tzUm9vdCxcbiAgZ2V0VnNDb2RlSG9va1NldHRpbmdzUGF0aCxcbiAgZ2V0VnNDb2RlVXNlclNldHRpbmdzUGF0aCxcbiAgZ2V0V2luZHN1cmZIb29rU2V0dGluZ3NQYXRoLFxuICBpbnN0YWxsSG9va0Fzc2V0c0Zvckhvc3QsXG4gIG5vcm1hbGl6ZUhvb2tIb3N0LFxuICByZWFkT3B0aW9uYWxVdGY4LFxuICB3cml0ZUhvb2tNYXJrZXIsXG4gIHdyaXRlQmFja3VwSWZQcmVzZW50LFxufSBmcm9tICcuL3Blcm1pc3Npb25Ib29rU2hhcmVkLmpzJztcbmltcG9ydCB7IFVuaWNvZGVWYWxpZGF0b3IgfSBmcm9tICcuLi9zZWN1cml0eS92YWxpZGF0b3JzL3VuaWNvZGVWYWxpZGF0b3IuanMnO1xuXG5mdW5jdGlvbiBub3JtYWxpemVQZXJtaXNzaW9uSG9va0NsaWVudChjbGllbnQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IG5vcm1hbGl6ZWRDbGllbnQgPSBVbmljb2RlVmFsaWRhdG9yLm5vcm1hbGl6ZShjbGllbnQpLm5vcm1hbGl6ZWRDb250ZW50O1xuICByZXR1cm4gbm9ybWFsaXplSG9va0hvc3Qobm9ybWFsaXplZENsaWVudCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVDbGF1ZGVQcmVUb29sVXNlSG9vayhcbiAgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgY29tbWFuZDogc3RyaW5nLFxuKTogeyBjaGFuZ2VkOiBib29sZWFuOyBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0ge1xuICByZXR1cm4gZW5zdXJlQ29tbWFuZEhvb2socGFyc2VkLCAnUHJlVG9vbFVzZScsIGNvbW1hbmQsICcqJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVWc0NvZGVQcmVUb29sVXNlSG9vayhcbiAgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgY29tbWFuZDogc3RyaW5nLFxuKTogeyBjaGFuZ2VkOiBib29sZWFuOyBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0ge1xuICByZXR1cm4gZW5zdXJlQ29tbWFuZEhvb2socGFyc2VkLCAnUHJlVG9vbFVzZScsIGNvbW1hbmQsICcqJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVHZW1pbmlCZWZvcmVUb29sSG9vayhcbiAgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgY29tbWFuZDogc3RyaW5nLFxuKTogeyBjaGFuZ2VkOiBib29sZWFuOyBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0ge1xuICByZXR1cm4gZW5zdXJlQ29tbWFuZEhvb2socGFyc2VkLCAnQmVmb3JlVG9vbCcsIGNvbW1hbmQsICcuKicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlQ29kZXhQcmVUb29sVXNlSG9vayhcbiAgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgY29tbWFuZDogc3RyaW5nLFxuKTogeyBjaGFuZ2VkOiBib29sZWFuOyBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0ge1xuICByZXR1cm4gZW5zdXJlQ29tbWFuZEhvb2socGFyc2VkLCAnUHJlVG9vbFVzZScsIGNvbW1hbmQsICdCYXNoJywge1xuICAgIHN0YXR1c01lc3NhZ2U6ICdDaGVja2luZyBCYXNoIHBlcm1pc3Npb25zJyxcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVDdXJzb3JQcmVUb29sVXNlSG9vayhcbiAgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgY29tbWFuZDogc3RyaW5nLFxuKTogeyBjaGFuZ2VkOiBib29sZWFuOyBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0ge1xuICBpZiAocGFyc2VkLnZlcnNpb24gIT09IDEpIHtcbiAgICBwYXJzZWQudmVyc2lvbiA9IDE7XG4gIH1cbiAgY29uc3QgaG9va3NSb290ID0gbm9ybWFsaXplSG9va3NSb290KHBhcnNlZCk7XG4gIGNvbnN0IGV4aXN0aW5nRW50cmllczogQXJyYXk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+ID0gQXJyYXkuaXNBcnJheShob29rc1Jvb3QucHJlVG9vbFVzZSlcbiAgICA/IGhvb2tzUm9vdC5wcmVUb29sVXNlLmZpbHRlcigoZW50cnkpOiBlbnRyeSBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiB0eXBlb2YgZW50cnkgPT09ICdvYmplY3QnICYmIGVudHJ5ICE9PSBudWxsKVxuICAgIDogW107XG4gIGhvb2tzUm9vdC5wcmVUb29sVXNlID0gZXhpc3RpbmdFbnRyaWVzO1xuXG4gIGNvbnN0IGNvbW1hbmRFeGlzdHMgPSBleGlzdGluZ0VudHJpZXMuc29tZSgoZW50cnkpID0+XG4gICAgZW50cnkuY29tbWFuZCA9PT0gY29tbWFuZFxuICAgICYmIChlbnRyeS50eXBlID09PSAnY29tbWFuZCcgfHwgZW50cnkudHlwZSA9PT0gdW5kZWZpbmVkKSxcbiAgKTtcbiAgaWYgKGNvbW1hbmRFeGlzdHMpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSwgcGFyc2VkIH07XG4gIH1cblxuICBleGlzdGluZ0VudHJpZXMucHVzaCh7XG4gICAgdHlwZTogJ2NvbW1hbmQnLFxuICAgIGNvbW1hbmQsXG4gICAgbWF0Y2hlcjogJy4qJyxcbiAgfSk7XG5cbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgcGFyc2VkIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVXaW5kc3VyZkhvb2tzKFxuICBwYXJzZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBjb21tYW5kOiBzdHJpbmcsXG4pOiB7IGNoYW5nZWQ6IGJvb2xlYW47IHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfSB7XG4gIGNvbnN0IGhvb2tzUm9vdCA9IG5vcm1hbGl6ZUhvb2tzUm9vdChwYXJzZWQpO1xuICBsZXQgY2hhbmdlZCA9IGZhbHNlO1xuXG4gIGNvbnN0IGVuc3VyZUV2ZW50SG9vayA9IChldmVudE5hbWU6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IGV4aXN0aW5nRW50cmllczogQXJyYXk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+ID0gQXJyYXkuaXNBcnJheShob29rc1Jvb3RbZXZlbnROYW1lXSlcbiAgICAgID8gaG9va3NSb290W2V2ZW50TmFtZV0uZmlsdGVyKChlbnRyeSk6IGVudHJ5IGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+IHR5cGVvZiBlbnRyeSA9PT0gJ29iamVjdCcgJiYgZW50cnkgIT09IG51bGwpXG4gICAgICA6IFtdO1xuICAgIGhvb2tzUm9vdFtldmVudE5hbWVdID0gZXhpc3RpbmdFbnRyaWVzO1xuXG4gICAgY29uc3QgY29tbWFuZEV4aXN0cyA9IGV4aXN0aW5nRW50cmllcy5zb21lKChlbnRyeSkgPT5cbiAgICAgIGVudHJ5LmNvbW1hbmQgPT09IGNvbW1hbmQgJiYgKGVudHJ5LnR5cGUgPT09ICdjb21tYW5kJyB8fCBlbnRyeS50eXBlID09PSB1bmRlZmluZWQpLFxuICAgICk7XG4gICAgaWYgKGNvbW1hbmRFeGlzdHMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBleGlzdGluZ0VudHJpZXMucHVzaCh7XG4gICAgICB0eXBlOiAnY29tbWFuZCcsXG4gICAgICBjb21tYW5kLFxuICAgIH0pO1xuICAgIGNoYW5nZWQgPSB0cnVlO1xuICB9O1xuXG4gIGVuc3VyZUV2ZW50SG9vaygncHJlX3J1bl9jb21tYW5kJyk7XG4gIGVuc3VyZUV2ZW50SG9vaygncHJlX21jcF90b29sX3VzZScpO1xuXG4gIHJldHVybiB7IGNoYW5nZWQsIHBhcnNlZCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUNsYXVkZVNldHRpbmdzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7fVxcbicpO1xuXG4gIGNvbnN0IGluZGVudCA9IGRldGVjdEluZGVudChyYXcpO1xuICBjb25zdCBwYXJzZWQgPSByYXcudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHt9IDogSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IGNoYW5nZWQsIHBhcnNlZDogdXBkYXRlZCB9ID0gZW5zdXJlQ2xhdWRlUHJlVG9vbFVzZUhvb2socGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKHNldHRpbmdzUGF0aCwgSlNPTi5zdHJpbmdpZnkodXBkYXRlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZVZzQ29kZUhvb2tTZXR0aW5ncyhzZXR0aW5nc1BhdGg6IHN0cmluZywgY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTx7IGNoYW5nZWQ6IGJvb2xlYW47IGJhY2t1cFBhdGg/OiBzdHJpbmcgfT4ge1xuICBhd2FpdCBta2RpcihkaXJuYW1lKHNldHRpbmdzUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IHJhdyA9IGF3YWl0IHJlYWRPcHRpb25hbFV0Zjgoc2V0dGluZ3NQYXRoLCAne31cXG4nKTtcblxuICBjb25zdCBpbmRlbnQgPSBkZXRlY3RJbmRlbnQocmF3KTtcbiAgY29uc3QgcGFyc2VkID0gcmF3LnRyaW0oKS5sZW5ndGggPT09IDAgPyB7fSA6IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgeyBjaGFuZ2VkLCBwYXJzZWQ6IHVwZGF0ZWQgfSA9IGVuc3VyZVZzQ29kZVByZVRvb2xVc2VIb29rKHBhcnNlZCwgY29tbWFuZCk7XG4gIGlmICghY2hhbmdlZCkge1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBiYWNrdXBQYXRoID0gYXdhaXQgd3JpdGVCYWNrdXBJZlByZXNlbnQoc2V0dGluZ3NQYXRoLCByYXcpO1xuXG4gIGF3YWl0IHdyaXRlRmlsZShzZXR0aW5nc1BhdGgsIEpTT04uc3RyaW5naWZ5KHVwZGF0ZWQsIG51bGwsIGluZGVudCkgKyAnXFxuJywgJ3V0Zi04Jyk7XG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIGJhY2t1cFBhdGggfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWVyZ2VWc0NvZGVVc2VyU2V0dGluZ3Moc2V0dGluZ3NQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7fVxcbicpO1xuICBjb25zdCBpbmRlbnQgPSBkZXRlY3RJbmRlbnQocmF3KTtcbiAgY29uc3QgcGFyc2VkID0gcmF3LnRyaW0oKS5sZW5ndGggPT09IDAgPyB7fSA6IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgY3VycmVudCA9IHBhcnNlZFsnY2hhdC5ob29rRmlsZXNMb2NhdGlvbnMnXTtcbiAgY29uc3QgbG9jYXRpb25zID0gKGN1cnJlbnQgJiYgdHlwZW9mIGN1cnJlbnQgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KGN1cnJlbnQpKVxuICAgID8geyAuLi4oY3VycmVudCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgfVxuICAgIDoge307XG5cbiAgaWYgKGxvY2F0aW9uc1snfi8uY29waWxvdC9ob29rcyddID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGxvY2F0aW9uc1snfi8uY29waWxvdC9ob29rcyddID0gdHJ1ZTtcbiAgcGFyc2VkWydjaGF0Lmhvb2tGaWxlc0xvY2F0aW9ucyddID0gbG9jYXRpb25zO1xuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG4gIGF3YWl0IHdyaXRlRmlsZShzZXR0aW5nc1BhdGgsIEpTT04uc3RyaW5naWZ5KHBhcnNlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUdlbWluaVNldHRpbmdzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7fVxcbicpO1xuXG4gIGNvbnN0IGluZGVudCA9IGRldGVjdEluZGVudChyYXcpO1xuICBjb25zdCBwYXJzZWQgPSByYXcudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHt9IDogSlNPTi5wYXJzZShyYXcpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCB7IGNoYW5nZWQsIHBhcnNlZDogdXBkYXRlZCB9ID0gZW5zdXJlR2VtaW5pQmVmb3JlVG9vbEhvb2socGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKHNldHRpbmdzUGF0aCwgSlNPTi5zdHJpbmdpZnkodXBkYXRlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUN1cnNvckhvb2tzKHNldHRpbmdzUGF0aDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiBQcm9taXNlPHsgY2hhbmdlZDogYm9vbGVhbjsgYmFja3VwUGF0aD86IHN0cmluZyB9PiB7XG4gIGF3YWl0IG1rZGlyKGRpcm5hbWUoc2V0dGluZ3NQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChzZXR0aW5nc1BhdGgsICd7XFxuICBcInZlcnNpb25cIjogMSxcXG4gIFwiaG9va3NcIjoge31cXG59XFxuJyk7XG5cbiAgY29uc3QgaW5kZW50ID0gZGV0ZWN0SW5kZW50KHJhdyk7XG4gIGNvbnN0IHBhcnNlZCA9IHJhdy50cmltKCkubGVuZ3RoID09PSAwID8ge30gOiBKU09OLnBhcnNlKHJhdykgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHsgY2hhbmdlZCwgcGFyc2VkOiB1cGRhdGVkIH0gPSBlbnN1cmVDdXJzb3JQcmVUb29sVXNlSG9vayhwYXJzZWQsIGNvbW1hbmQpO1xuICBpZiAoIWNoYW5nZWQpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IHdyaXRlQmFja3VwSWZQcmVzZW50KHNldHRpbmdzUGF0aCwgcmF3KTtcblxuICBhd2FpdCB3cml0ZUZpbGUoc2V0dGluZ3NQYXRoLCBKU09OLnN0cmluZ2lmeSh1cGRhdGVkLCBudWxsLCBpbmRlbnQpICsgJ1xcbicsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lcmdlV2luZHN1cmZIb29rcyhzZXR0aW5nc1BhdGg6IHN0cmluZywgY29tbWFuZDogc3RyaW5nKTogUHJvbWlzZTx7IGNoYW5nZWQ6IGJvb2xlYW47IGJhY2t1cFBhdGg/OiBzdHJpbmcgfT4ge1xuICBhd2FpdCBta2RpcihkaXJuYW1lKHNldHRpbmdzUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gIGNvbnN0IHJhdyA9IGF3YWl0IHJlYWRPcHRpb25hbFV0Zjgoc2V0dGluZ3NQYXRoLCAne1xcbiAgXCJob29rc1wiOiB7fVxcbn1cXG4nKTtcblxuICBjb25zdCBpbmRlbnQgPSBkZXRlY3RJbmRlbnQocmF3KTtcbiAgY29uc3QgcGFyc2VkID0gcmF3LnRyaW0oKS5sZW5ndGggPT09IDAgPyB7fSA6IEpTT04ucGFyc2UocmF3KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3QgeyBjaGFuZ2VkLCBwYXJzZWQ6IHVwZGF0ZWQgfSA9IGVuc3VyZVdpbmRzdXJmSG9va3MocGFyc2VkLCBjb21tYW5kKTtcbiAgaWYgKCFjaGFuZ2VkKSB7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGNvbnN0IGJhY2t1cFBhdGggPSBhd2FpdCB3cml0ZUJhY2t1cElmUHJlc2VudChzZXR0aW5nc1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKHNldHRpbmdzUGF0aCwgSlNPTi5zdHJpbmdpZnkodXBkYXRlZCwgbnVsbCwgaW5kZW50KSArICdcXG4nLCAndXRmLTgnKTtcbiAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgYmFja3VwUGF0aCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUNvZGV4SG9va3MoaG9va3NQYXRoOiBzdHJpbmcsIGNvbW1hbmQ6IHN0cmluZyk6IFByb21pc2U8eyBjaGFuZ2VkOiBib29sZWFuOyBiYWNrdXBQYXRoPzogc3RyaW5nIH0+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShob29rc1BhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICBjb25zdCByYXcgPSBhd2FpdCByZWFkT3B0aW9uYWxVdGY4KGhvb2tzUGF0aCwgJ3t9XFxuJyk7XG5cbiAgY29uc3QgaW5kZW50ID0gZGV0ZWN0SW5kZW50KHJhdyk7XG4gIGNvbnN0IHBhcnNlZCA9IHJhdy50cmltKCkubGVuZ3RoID09PSAwID8ge30gOiBKU09OLnBhcnNlKHJhdykgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNvbnN0IHsgY2hhbmdlZCwgcGFyc2VkOiB1cGRhdGVkIH0gPSBlbnN1cmVDb2RleFByZVRvb2xVc2VIb29rKHBhcnNlZCwgY29tbWFuZCk7XG4gIGlmICghY2hhbmdlZCkge1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlIH07XG4gIH1cblxuICBjb25zdCBiYWNrdXBQYXRoID0gYXdhaXQgd3JpdGVCYWNrdXBJZlByZXNlbnQoaG9va3NQYXRoLCByYXcpO1xuXG4gIGF3YWl0IHdyaXRlRmlsZShob29rc1BhdGgsIEpTT04uc3RyaW5naWZ5KHVwZGF0ZWQsIG51bGwsIGluZGVudCkgKyAnXFxuJywgJ3V0Zi04Jyk7XG4gIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIGJhY2t1cFBhdGggfTtcbn1cblxuZnVuY3Rpb24gZ2V0VG9tbExpbmVDb250ZW50KGxpbmU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGNvbW1lbnRJbmRleCA9IGxpbmUuaW5kZXhPZignIycpO1xuICByZXR1cm4gKGNvbW1lbnRJbmRleCA+PSAwID8gbGluZS5zbGljZSgwLCBjb21tZW50SW5kZXgpIDogbGluZSkudHJpbSgpO1xufVxuXG5mdW5jdGlvbiBpc1RvbWxTZWN0aW9uTGluZShsaW5lOiBzdHJpbmcsIHNlY3Rpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0VG9tbExpbmVDb250ZW50KGxpbmUpID09PSBgWyR7c2VjdGlvbn1dYDtcbn1cblxuZnVuY3Rpb24gcGFyc2VUb21sQm9vbGVhbkFzc2lnbm1lbnQobGluZTogc3RyaW5nLCBrZXk6IHN0cmluZyk6IGJvb2xlYW4gfCBudWxsIHtcbiAgY29uc3QgY29udGVudCA9IGdldFRvbWxMaW5lQ29udGVudChsaW5lKTtcbiAgaWYgKCFjb250ZW50LnN0YXJ0c1dpdGgoYCR7a2V5fSA9IGApKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgY29uc3QgdmFsdWUgPSBjb250ZW50LnNsaWNlKGAke2tleX0gPSBgLmxlbmd0aCkudHJpbSgpO1xuICBpZiAodmFsdWUgPT09ICd0cnVlJykgcmV0dXJuIHRydWU7XG4gIGlmICh2YWx1ZSA9PT0gJ2ZhbHNlJykgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gdXBkYXRlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KGxpbmU6IHN0cmluZywga2V5OiBzdHJpbmcsIG5leHRWYWx1ZTogYm9vbGVhbik6IHN0cmluZyB7XG4gIGNvbnN0IGNvbW1lbnRJbmRleCA9IGxpbmUuaW5kZXhPZignIycpO1xuICBjb25zdCBjb21tZW50U3VmZml4ID0gY29tbWVudEluZGV4ID49IDAgPyBsaW5lLnNsaWNlKGNvbW1lbnRJbmRleCkgOiAnJztcbiAgbGV0IHByZWZpeExlbmd0aCA9IDA7XG4gIHdoaWxlIChwcmVmaXhMZW5ndGggPCBsaW5lLmxlbmd0aCAmJiAvXFxzLy50ZXN0KGxpbmUuY2hhckF0KHByZWZpeExlbmd0aCkpKSB7XG4gICAgcHJlZml4TGVuZ3RoICs9IDE7XG4gIH1cbiAgY29uc3QgcHJlZml4ID0gbGluZS5zbGljZSgwLCBwcmVmaXhMZW5ndGgpO1xuICBjb25zdCBhc3NpZ25tZW50ID0gYCR7cHJlZml4fSR7a2V5fSA9ICR7bmV4dFZhbHVlID8gJ3RydWUnIDogJ2ZhbHNlJ31gO1xuICBjb25zdCB0cmltbWVkQ29tbWVudFN1ZmZpeCA9IGNvbW1lbnRTdWZmaXgudHJpbVN0YXJ0KCk7XG4gIGNvbnN0IHN1ZmZpeCA9IHRyaW1tZWRDb21tZW50U3VmZml4Lmxlbmd0aCA+IDAgPyBgICR7dHJpbW1lZENvbW1lbnRTdWZmaXh9YCA6ICcnO1xuICByZXR1cm4gYCR7YXNzaWdubWVudH0ke3N1ZmZpeH1gLnRyaW1FbmQoKTtcbn1cblxuZnVuY3Rpb24gc3RyaXBUcmFpbGluZ05ld2xpbmVzKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgZW5kID0gdmFsdWUubGVuZ3RoO1xuICB3aGlsZSAoZW5kID4gMCAmJiB2YWx1ZS5jaGFyQXQoZW5kIC0gMSkgPT09ICdcXG4nKSB7XG4gICAgZW5kIC09IDE7XG4gIH1cbiAgcmV0dXJuIHZhbHVlLnNsaWNlKDAsIGVuZCk7XG59XG5cbmZ1bmN0aW9uIGVuc3VyZUNvZGV4SG9va3NFbmFibGVkKHJhdzogc3RyaW5nKTogeyBjaGFuZ2VkOiBib29sZWFuOyBjb250ZW50OiBzdHJpbmcgfSB7XG4gIGNvbnN0IGxpbmVzID0gcmF3Lmxlbmd0aCA+IDAgPyByYXcuc3BsaXQoJ1xcbicpIDogW107XG4gIGNvbnN0IGRvdHRlZEluZGV4ID0gbGluZXMuZmluZEluZGV4KChsaW5lKSA9PiBwYXJzZVRvbWxCb29sZWFuQXNzaWdubWVudChsaW5lLCAnZmVhdHVyZXMuY29kZXhfaG9va3MnKSAhPT0gbnVsbCk7XG4gIGlmIChkb3R0ZWRJbmRleCA+PSAwKSB7XG4gICAgaWYgKHBhcnNlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KGxpbmVzW2RvdHRlZEluZGV4XSwgJ2ZlYXR1cmVzLmNvZGV4X2hvb2tzJykgPT09IHRydWUpIHtcbiAgICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlLCBjb250ZW50OiByYXcgfTtcbiAgICB9XG4gICAgY29uc3QgdXBkYXRlZExpbmVzID0gWy4uLmxpbmVzXTtcbiAgICB1cGRhdGVkTGluZXNbZG90dGVkSW5kZXhdID0gdXBkYXRlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KHVwZGF0ZWRMaW5lc1tkb3R0ZWRJbmRleF0sICdmZWF0dXJlcy5jb2RleF9ob29rcycsIHRydWUpO1xuICAgIHJldHVybiB7IGNoYW5nZWQ6IHRydWUsIGNvbnRlbnQ6IGAke3N0cmlwVHJhaWxpbmdOZXdsaW5lcyh1cGRhdGVkTGluZXMuam9pbignXFxuJykpfVxcbmAgfTtcbiAgfVxuXG4gIGNvbnN0IHNlY3Rpb25JbmRleCA9IGxpbmVzLmZpbmRJbmRleCgobGluZSkgPT4gaXNUb21sU2VjdGlvbkxpbmUobGluZSwgJ2ZlYXR1cmVzJykpO1xuICBpZiAoc2VjdGlvbkluZGV4ID49IDApIHtcbiAgICBjb25zdCBuZXh0U2VjdGlvbkluZGV4ID0gbGluZXMuZmluZEluZGV4KChsaW5lLCBpbmRleCkgPT4gaW5kZXggPiBzZWN0aW9uSW5kZXggJiYgZ2V0VG9tbExpbmVDb250ZW50KGxpbmUpLnN0YXJ0c1dpdGgoJ1snKSAmJiBnZXRUb21sTGluZUNvbnRlbnQobGluZSkuZW5kc1dpdGgoJ10nKSk7XG4gICAgY29uc3Qgc2VjdGlvbkVuZCA9IG5leHRTZWN0aW9uSW5kZXggPj0gMCA/IG5leHRTZWN0aW9uSW5kZXggOiBsaW5lcy5sZW5ndGg7XG4gICAgY29uc3Qga2V5SW5kZXggPSBsaW5lcy5maW5kSW5kZXgoKGxpbmUsIGluZGV4KSA9PiBpbmRleCA+IHNlY3Rpb25JbmRleCAmJiBpbmRleCA8IHNlY3Rpb25FbmQgJiYgcGFyc2VUb21sQm9vbGVhbkFzc2lnbm1lbnQobGluZSwgJ2NvZGV4X2hvb2tzJykgIT09IG51bGwpO1xuXG4gICAgaWYgKGtleUluZGV4ID49IDApIHtcbiAgICAgIGlmIChwYXJzZVRvbWxCb29sZWFuQXNzaWdubWVudChsaW5lc1trZXlJbmRleF0sICdjb2RleF9ob29rcycpID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiB7IGNoYW5nZWQ6IGZhbHNlLCBjb250ZW50OiByYXcgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZWRMaW5lcyA9IFsuLi5saW5lc107XG4gICAgICB1cGRhdGVkTGluZXNba2V5SW5kZXhdID0gdXBkYXRlVG9tbEJvb2xlYW5Bc3NpZ25tZW50KHVwZGF0ZWRMaW5lc1trZXlJbmRleF0sICdjb2RleF9ob29rcycsIHRydWUpO1xuICAgICAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgY29udGVudDogYCR7c3RyaXBUcmFpbGluZ05ld2xpbmVzKHVwZGF0ZWRMaW5lcy5qb2luKCdcXG4nKSl9XFxuYCB9O1xuICAgIH1cblxuICAgIGNvbnN0IHVwZGF0ZWRMaW5lcyA9IFsuLi5saW5lc107XG4gICAgdXBkYXRlZExpbmVzLnNwbGljZShzZWN0aW9uSW5kZXggKyAxLCAwLCAnY29kZXhfaG9va3MgPSB0cnVlJyk7XG4gICAgcmV0dXJuIHsgY2hhbmdlZDogdHJ1ZSwgY29udGVudDogYCR7c3RyaXBUcmFpbGluZ05ld2xpbmVzKHVwZGF0ZWRMaW5lcy5qb2luKCdcXG4nKSl9XFxuYCB9O1xuICB9XG5cbiAgY29uc3QgcHJlZml4ID0gcmF3LnRyaW0oKS5sZW5ndGggPiAwID8gYCR7c3RyaXBUcmFpbGluZ05ld2xpbmVzKHJhdyl9XFxuXFxuYCA6ICcnO1xuICByZXR1cm4ge1xuICAgIGNoYW5nZWQ6IHRydWUsXG4gICAgY29udGVudDogYCR7cHJlZml4fVtmZWF0dXJlc11cXG5jb2RleF9ob29rcyA9IHRydWVcXG5gLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBtZXJnZUNvZGV4Q29uZmlnKGNvbmZpZ1BhdGg6IHN0cmluZyk6IFByb21pc2U8eyBjaGFuZ2VkOiBib29sZWFuOyBiYWNrdXBQYXRoPzogc3RyaW5nIH0+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShjb25maWdQYXRoKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3QgcmF3ID0gYXdhaXQgcmVhZE9wdGlvbmFsVXRmOChjb25maWdQYXRoLCAnJyk7XG5cbiAgY29uc3QgeyBjaGFuZ2VkLCBjb250ZW50IH0gPSBlbnN1cmVDb2RleEhvb2tzRW5hYmxlZChyYXcpO1xuICBpZiAoIWNoYW5nZWQpIHtcbiAgICByZXR1cm4geyBjaGFuZ2VkOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3QgYmFja3VwUGF0aCA9IGF3YWl0IHdyaXRlQmFja3VwSWZQcmVzZW50KGNvbmZpZ1BhdGgsIHJhdyk7XG5cbiAgYXdhaXQgd3JpdGVGaWxlKGNvbmZpZ1BhdGgsIGNvbnRlbnQsICd1dGYtOCcpO1xuICByZXR1cm4geyBjaGFuZ2VkOiB0cnVlLCBiYWNrdXBQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxDbGF1ZGVDb2RlUGVybWlzc2lvbkhvb2soXG4gIGhvbWVEaXI6IHN0cmluZyxcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZyxcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8SW5zdGFsbFBlcm1pc3Npb25Ib29rUmVzdWx0PiB7XG4gIGNvbnN0IGhvc3QgPSAnY2xhdWRlLWNvZGUnO1xuICBjb25zdCB7IHNjcmlwdFBhdGggfSA9IGF3YWl0IGluc3RhbGxIb29rQXNzZXRzRm9ySG9zdChob3N0LCBob21lRGlyLCBzb3VyY2VTY3JpcHRQYXRoKTtcbiAgY29uc3Qgc2V0dGluZ3NQYXRoID0gZ2V0Q2xhdWRlSG9va1NldHRpbmdzUGF0aChob21lRGlyKTtcbiAgY29uc3Qgc2V0dGluZ3NSZXN1bHQgPSBhd2FpdCBtZXJnZUNsYXVkZVNldHRpbmdzKHNldHRpbmdzUGF0aCwgYGJhc2ggJHtzY3JpcHRQYXRofWApO1xuICBjb25zdCBtYXJrZXJQYXRoID0gYXdhaXQgd3JpdGVIb29rTWFya2VyKGhvbWVEaXIsIHtcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkQXQsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgc3VwcG9ydGVkOiB0cnVlLFxuICAgIGluc3RhbGxlZDogdHJ1ZSxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgbWFya2VyUGF0aCxcbiAgICBiYWNrdXBQYXRoOiBzZXR0aW5nc1Jlc3VsdC5iYWNrdXBQYXRoLFxuICAgIG1lc3NhZ2U6ICdJbnN0YWxsZWQgQ2xhdWRlIENvZGUgcGVybWlzc2lvbiBob29rIGFuZCB1cGRhdGVkIHNldHRpbmdzLmpzb24uJyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbFZzQ29kZVBlcm1pc3Npb25Ib29rKFxuICBob21lRGlyOiBzdHJpbmcsXG4gIGluc3RhbGxlZEF0OiBzdHJpbmcsXG4gIHNvdXJjZVNjcmlwdFBhdGg/OiBzdHJpbmcsXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCBob3N0ID0gJ3ZzY29kZSc7XG4gIGNvbnN0IHsgc2NyaXB0UGF0aCB9ID0gYXdhaXQgaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0KGhvc3QsIGhvbWVEaXIsIHNvdXJjZVNjcmlwdFBhdGgpO1xuICBjb25zdCBzZXR0aW5nc1BhdGggPSBnZXRWc0NvZGVIb29rU2V0dGluZ3NQYXRoKGhvbWVEaXIpO1xuICBjb25zdCB1c2VyU2V0dGluZ3NQYXRoID0gZ2V0VnNDb2RlVXNlclNldHRpbmdzUGF0aChob21lRGlyKTtcbiAgY29uc3QgaG9va1Jlc3VsdCA9IGF3YWl0IG1lcmdlVnNDb2RlSG9va1NldHRpbmdzKHNldHRpbmdzUGF0aCwgYGJhc2ggJHtzY3JpcHRQYXRofWApO1xuICBjb25zdCB1c2VyU2V0dGluZ3NSZXN1bHQgPSBhd2FpdCBtZXJnZVZzQ29kZVVzZXJTZXR0aW5ncyh1c2VyU2V0dGluZ3NQYXRoKTtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGF3YWl0IHdyaXRlSG9va01hcmtlcihob21lRGlyLCB7XG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBhZGRpdGlvbmFsUGF0aHM6IFt1c2VyU2V0dGluZ3NQYXRoXSxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGluc3RhbGxlZEF0LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGFkZGl0aW9uYWxQYXRoczogW3VzZXJTZXR0aW5nc1BhdGhdLFxuICAgIG1hcmtlclBhdGgsXG4gICAgYmFja3VwUGF0aDogaG9va1Jlc3VsdC5iYWNrdXBQYXRoID8/IHVzZXJTZXR0aW5nc1Jlc3VsdC5iYWNrdXBQYXRoLFxuICAgIG1lc3NhZ2U6ICdJbnN0YWxsZWQgVlMgQ29kZSBwZXJtaXNzaW9uIGhvb2sgYW5kIGVuYWJsZWQgY2hhdC5ob29rRmlsZXNMb2NhdGlvbnMgZm9yIH4vLmNvcGlsb3QvaG9va3MuJyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaW5zdGFsbEdlbWluaUNsaVBlcm1pc3Npb25Ib29rKFxuICBob21lRGlyOiBzdHJpbmcsXG4gIGluc3RhbGxlZEF0OiBzdHJpbmcsXG4gIHNvdXJjZVNjcmlwdFBhdGg/OiBzdHJpbmcsXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCBob3N0ID0gJ2dlbWluaS1jbGknO1xuICBjb25zdCB7IHNjcmlwdFBhdGggfSA9IGF3YWl0IGluc3RhbGxIb29rQXNzZXRzRm9ySG9zdChob3N0LCBob21lRGlyLCBzb3VyY2VTY3JpcHRQYXRoKTtcbiAgY29uc3Qgc2V0dGluZ3NQYXRoID0gZ2V0R2VtaW5pSG9va1NldHRpbmdzUGF0aChob21lRGlyKTtcbiAgY29uc3Qgc2V0dGluZ3NSZXN1bHQgPSBhd2FpdCBtZXJnZUdlbWluaVNldHRpbmdzKHNldHRpbmdzUGF0aCwgYGJhc2ggJHtzY3JpcHRQYXRofWApO1xuICBjb25zdCBtYXJrZXJQYXRoID0gYXdhaXQgd3JpdGVIb29rTWFya2VyKGhvbWVEaXIsIHtcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkQXQsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgc3VwcG9ydGVkOiB0cnVlLFxuICAgIGluc3RhbGxlZDogdHJ1ZSxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgbWFya2VyUGF0aCxcbiAgICBiYWNrdXBQYXRoOiBzZXR0aW5nc1Jlc3VsdC5iYWNrdXBQYXRoLFxuICAgIG1lc3NhZ2U6ICdJbnN0YWxsZWQgR2VtaW5pIENMSSBwZXJtaXNzaW9uIGhvb2sgYW5kIHVwZGF0ZWQgc2V0dGluZ3MuanNvbi4nLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsQ3Vyc29yUGVybWlzc2lvbkhvb2soXG4gIGhvbWVEaXI6IHN0cmluZyxcbiAgaW5zdGFsbGVkQXQ6IHN0cmluZyxcbiAgc291cmNlU2NyaXB0UGF0aD86IHN0cmluZyxcbik6IFByb21pc2U8SW5zdGFsbFBlcm1pc3Npb25Ib29rUmVzdWx0PiB7XG4gIGNvbnN0IGhvc3QgPSAnY3Vyc29yJztcbiAgY29uc3QgeyBzY3JpcHRQYXRoIH0gPSBhd2FpdCBpbnN0YWxsSG9va0Fzc2V0c0Zvckhvc3QoaG9zdCwgaG9tZURpciwgc291cmNlU2NyaXB0UGF0aCk7XG4gIGNvbnN0IHNldHRpbmdzUGF0aCA9IGdldEN1cnNvckhvb2tTZXR0aW5nc1BhdGgoaG9tZURpcik7XG4gIGNvbnN0IHNldHRpbmdzUmVzdWx0ID0gYXdhaXQgbWVyZ2VDdXJzb3JIb29rcyhzZXR0aW5nc1BhdGgsIGBiYXNoICR7c2NyaXB0UGF0aH1gKTtcbiAgY29uc3QgbWFya2VyUGF0aCA9IGF3YWl0IHdyaXRlSG9va01hcmtlcihob21lRGlyLCB7XG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGluc3RhbGxlZEF0LFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHN1cHBvcnRlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWQ6IHRydWUsXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIG1hcmtlclBhdGgsXG4gICAgYmFja3VwUGF0aDogc2V0dGluZ3NSZXN1bHQuYmFja3VwUGF0aCxcbiAgICBtZXNzYWdlOiAnSW5zdGFsbGVkIEN1cnNvciBwZXJtaXNzaW9uIGhvb2sgYW5kIHVwZGF0ZWQgaG9va3MuanNvbi4nLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsV2luZHN1cmZQZXJtaXNzaW9uSG9vayhcbiAgaG9tZURpcjogc3RyaW5nLFxuICBpbnN0YWxsZWRBdDogc3RyaW5nLFxuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nLFxuKTogUHJvbWlzZTxJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQ+IHtcbiAgY29uc3QgaG9zdCA9ICd3aW5kc3VyZic7XG4gIGNvbnN0IHsgc2NyaXB0UGF0aCB9ID0gYXdhaXQgaW5zdGFsbEhvb2tBc3NldHNGb3JIb3N0KGhvc3QsIGhvbWVEaXIsIHNvdXJjZVNjcmlwdFBhdGgpO1xuICBjb25zdCBzZXR0aW5nc1BhdGggPSBnZXRXaW5kc3VyZkhvb2tTZXR0aW5nc1BhdGgoaG9tZURpcik7XG4gIGNvbnN0IHNldHRpbmdzUmVzdWx0ID0gYXdhaXQgbWVyZ2VXaW5kc3VyZkhvb2tzKHNldHRpbmdzUGF0aCwgYGJhc2ggJHtzY3JpcHRQYXRofWApO1xuICBjb25zdCBtYXJrZXJQYXRoID0gYXdhaXQgd3JpdGVIb29rTWFya2VyKGhvbWVEaXIsIHtcbiAgICBob3N0LFxuICAgIHNjcmlwdFBhdGgsXG4gICAgc2V0dGluZ3NQYXRoLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkQXQsXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgc3VwcG9ydGVkOiB0cnVlLFxuICAgIGluc3RhbGxlZDogdHJ1ZSxcbiAgICBjb25maWd1cmVkOiB0cnVlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgbWFya2VyUGF0aCxcbiAgICBiYWNrdXBQYXRoOiBzZXR0aW5nc1Jlc3VsdC5iYWNrdXBQYXRoLFxuICAgIG1lc3NhZ2U6ICdJbnN0YWxsZWQgV2luZHN1cmYgcGVybWlzc2lvbiBob29rcyBhbmQgdXBkYXRlZCBob29rcy5qc29uLicsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3RhbGxDb2RleFBlcm1pc3Npb25Ib29rKFxuICBob21lRGlyOiBzdHJpbmcsXG4gIGluc3RhbGxlZEF0OiBzdHJpbmcsXG4gIHNvdXJjZVNjcmlwdFBhdGg/OiBzdHJpbmcsXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCBob3N0ID0gJ2NvZGV4JztcbiAgY29uc3QgeyBzY3JpcHRQYXRoIH0gPSBhd2FpdCBpbnN0YWxsSG9va0Fzc2V0c0Zvckhvc3QoaG9zdCwgaG9tZURpciwgc291cmNlU2NyaXB0UGF0aCk7XG4gIGNvbnN0IHNldHRpbmdzUGF0aCA9IGdldENvZGV4SG9va1NldHRpbmdzUGF0aChob21lRGlyKTtcbiAgY29uc3QgY29uZmlnUGF0aCA9IGdldENvZGV4Q29uZmlnUGF0aChob21lRGlyKTtcbiAgY29uc3QgaG9va3NSZXN1bHQgPSBhd2FpdCBtZXJnZUNvZGV4SG9va3Moc2V0dGluZ3NQYXRoLCBgYmFzaCAke3NjcmlwdFBhdGh9YCk7XG4gIGNvbnN0IGNvbmZpZ1Jlc3VsdCA9IGF3YWl0IG1lcmdlQ29kZXhDb25maWcoY29uZmlnUGF0aCk7XG4gIGNvbnN0IG1hcmtlclBhdGggPSBhd2FpdCB3cml0ZUhvb2tNYXJrZXIoaG9tZURpciwge1xuICAgIGhvc3QsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGgsXG4gICAgYWRkaXRpb25hbFBhdGhzOiBbY29uZmlnUGF0aF0sXG4gICAgY29uZmlndXJlZDogdHJ1ZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWRBdCxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdXBwb3J0ZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkOiB0cnVlLFxuICAgIGNvbmZpZ3VyZWQ6IHRydWUsXG4gICAgYXNzZXRzUHJlcGFyZWQ6IHRydWUsXG4gICAgaG9zdCxcbiAgICBzY3JpcHRQYXRoLFxuICAgIHNldHRpbmdzUGF0aCxcbiAgICBhZGRpdGlvbmFsUGF0aHM6IFtjb25maWdQYXRoXSxcbiAgICBtYXJrZXJQYXRoLFxuICAgIGJhY2t1cFBhdGg6IGhvb2tzUmVzdWx0LmJhY2t1cFBhdGggPz8gY29uZmlnUmVzdWx0LmJhY2t1cFBhdGgsXG4gICAgbWVzc2FnZTogJ0luc3RhbGxlZCBDb2RleCBCYXNoIHBlcm1pc3Npb24gaG9vaywgY3JlYXRlZCBob29rcy5qc29uLCBhbmQgZW5hYmxlZCBmZWF0dXJlcy5jb2RleF9ob29rcyBpbiBjb25maWcudG9tbC4nLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbnN0YWxsTWFudWFsUGVybWlzc2lvbkhvb2tBc3NldHMoXG4gIG5vcm1hbGl6ZWRDbGllbnQ6IHN0cmluZyxcbiAgaG9tZURpcjogc3RyaW5nLFxuICBpbnN0YWxsZWRBdDogc3RyaW5nLFxuICBzb3VyY2VTY3JpcHRQYXRoPzogc3RyaW5nLFxuKTogUHJvbWlzZTxJbnN0YWxsUGVybWlzc2lvbkhvb2tSZXN1bHQ+IHtcbiAgY29uc3QgeyBzY3JpcHRQYXRoIH0gPSBhd2FpdCBpbnN0YWxsSG9va0Fzc2V0c0Zvckhvc3Qobm9ybWFsaXplZENsaWVudCwgaG9tZURpciwgc291cmNlU2NyaXB0UGF0aCk7XG4gIGNvbnN0IG1hcmtlclBhdGggPSBhd2FpdCB3cml0ZUhvb2tNYXJrZXIoaG9tZURpciwge1xuICAgIGhvc3Q6IG5vcm1hbGl6ZWRDbGllbnQsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBzZXR0aW5nc1BhdGg6IHVuZGVmaW5lZCxcbiAgICBjb25maWd1cmVkOiBmYWxzZSxcbiAgICBhc3NldHNQcmVwYXJlZDogdHJ1ZSxcbiAgICBpbnN0YWxsZWRBdCxcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdXBwb3J0ZWQ6IHRydWUsXG4gICAgaW5zdGFsbGVkOiB0cnVlLFxuICAgIGNvbmZpZ3VyZWQ6IGZhbHNlLFxuICAgIGFzc2V0c1ByZXBhcmVkOiB0cnVlLFxuICAgIGhvc3Q6IG5vcm1hbGl6ZWRDbGllbnQsXG4gICAgc2NyaXB0UGF0aCxcbiAgICBtYXJrZXJQYXRoLFxuICAgIG1lc3NhZ2U6IGBJbnN0YWxsZWQgRG9sbGhvdXNlIHBlcm1pc3Npb24gaG9vayBhc3NldHMgZm9yICR7bm9ybWFsaXplZENsaWVudH0uIEZpbmlzaCB0aGUgY2xpZW50LXNwZWNpZmljIGhvb2sgcmVnaXN0cmF0aW9uIG1hbnVhbGx5LmAsXG4gIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsUGVybWlzc2lvbkhvb2soXG4gIGNsaWVudDogc3RyaW5nLFxuICBvcHRpb25zOiBJbnN0YWxsUGVybWlzc2lvbkhvb2tPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPEluc3RhbGxQZXJtaXNzaW9uSG9va1Jlc3VsdD4ge1xuICBjb25zdCBub3JtYWxpemVkQ2xpZW50ID0gbm9ybWFsaXplUGVybWlzc2lvbkhvb2tDbGllbnQoY2xpZW50KTtcbiAgY29uc3QgaG9tZURpciA9IG9wdGlvbnMuaG9tZURpciA/PyBob21lZGlyKCk7XG4gIGNvbnN0IGluc3RhbGxlZEF0ID0gKG9wdGlvbnMubm93ID8/IG5ldyBEYXRlKCkpLnRvSVNPU3RyaW5nKCk7XG5cbiAgaWYgKG5vcm1hbGl6ZWRDbGllbnQgPT09ICdjbGF1ZGUtY29kZScpIHtcbiAgICByZXR1cm4gaW5zdGFsbENsYXVkZUNvZGVQZXJtaXNzaW9uSG9vayhob21lRGlyLCBpbnN0YWxsZWRBdCwgb3B0aW9ucy5zb3VyY2VTY3JpcHRQYXRoKTtcbiAgfVxuXG4gIGlmIChub3JtYWxpemVkQ2xpZW50ID09PSAndnNjb2RlJykge1xuICAgIHJldHVybiBpbnN0YWxsVnNDb2RlUGVybWlzc2lvbkhvb2soaG9tZURpciwgaW5zdGFsbGVkQXQsIG9wdGlvbnMuc291cmNlU2NyaXB0UGF0aCk7XG4gIH1cblxuICBpZiAobm9ybWFsaXplZENsaWVudCA9PT0gJ2dlbWluaS1jbGknKSB7XG4gICAgcmV0dXJuIGluc3RhbGxHZW1pbmlDbGlQZXJtaXNzaW9uSG9vayhob21lRGlyLCBpbnN0YWxsZWRBdCwgb3B0aW9ucy5zb3VyY2VTY3JpcHRQYXRoKTtcbiAgfVxuXG4gIGlmIChub3JtYWxpemVkQ2xpZW50ID09PSAnY3Vyc29yJykge1xuICAgIHJldHVybiBpbnN0YWxsQ3Vyc29yUGVybWlzc2lvbkhvb2soaG9tZURpciwgaW5zdGFsbGVkQXQsIG9wdGlvbnMuc291cmNlU2NyaXB0UGF0aCk7XG4gIH1cblxuICBpZiAobm9ybWFsaXplZENsaWVudCA9PT0gJ3dpbmRzdXJmJykge1xuICAgIHJldHVybiBpbnN0YWxsV2luZHN1cmZQZXJtaXNzaW9uSG9vayhob21lRGlyLCBpbnN0YWxsZWRBdCwgb3B0aW9ucy5zb3VyY2VTY3JpcHRQYXRoKTtcbiAgfVxuXG4gIGlmIChub3JtYWxpemVkQ2xpZW50ID09PSAnY29kZXgnKSB7XG4gICAgcmV0dXJuIGluc3RhbGxDb2RleFBlcm1pc3Npb25Ib29rKGhvbWVEaXIsIGluc3RhbGxlZEF0LCBvcHRpb25zLnNvdXJjZVNjcmlwdFBhdGgpO1xuICB9XG5cbiAgaWYgKGdldEhvb2tXcmFwcGVyQmFzZW5hbWUobm9ybWFsaXplZENsaWVudCkpIHtcbiAgICByZXR1cm4gaW5zdGFsbE1hbnVhbFBlcm1pc3Npb25Ib29rQXNzZXRzKG5vcm1hbGl6ZWRDbGllbnQsIGhvbWVEaXIsIGluc3RhbGxlZEF0LCBvcHRpb25zLnNvdXJjZVNjcmlwdFBhdGgpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBzdXBwb3J0ZWQ6IGZhbHNlLFxuICAgIGluc3RhbGxlZDogZmFsc2UsXG4gICAgY29uZmlndXJlZDogZmFsc2UsXG4gICAgaG9zdDogbm9ybWFsaXplZENsaWVudCxcbiAgICBtZXNzYWdlOiBgQXV0b21hdGljIHBlcm1pc3Npb24gaG9vayB3aXJpbmcgaXMgbm90IHlldCBzdXBwb3J0ZWQgZm9yICR7bm9ybWFsaXplZENsaWVudH0uYCxcbiAgfTtcbn1cbiJdfQ==
|