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