UNPKG

@dollhousemcp/mcp-server

Version:

DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.

197 lines 18.8 kB
/** * MCP Client Detector for Telemetry * * Detects which MCP client is running the server by examining environment variables, * process arguments, and parent process information. Used for telemetry and debugging. * * Issue #1358: MCP client detection for enhanced telemetry */ /** * Detect client from environment variables (most reliable) * @internal */ function detectFromEnvironmentVariables() { // Claude Desktop detection if (process.env.CLAUDE_DESKTOP === 'true' || process.env.CLAUDE_DESKTOP_VERSION) { return 'claude-desktop'; } // Claude Code detection if (process.env.CLAUDE_CODE === 'true' || process.env.TERM_PROGRAM === 'claude-code') { return 'claude-code'; } // VS Code detection if (process.env.VSCODE_CWD || process.env.VSCODE_PID || process.env.VSCODE_IPC_HOOK || process.env.VSCODE_NLS_CONFIG || process.env.TERM_PROGRAM === 'vscode') { return 'vscode'; } return null; } /** * Detect client from process arguments * @internal */ function detectFromProcessArguments() { const argv = process.argv.join(' ').toLowerCase(); if (argv.includes('claude') && argv.includes('desktop')) { return 'claude-desktop'; } if (argv.includes('claude') && argv.includes('code')) { return 'claude-code'; } if (argv.includes('vscode') || argv.includes('code.exe')) { return 'vscode'; } return null; } /** * Detect client from process metadata (execPath and title) * @internal */ function detectFromProcessMetadata() { const execPath = process.execPath?.toLowerCase() ?? ''; const processTitle = process.title?.toLowerCase() ?? ''; // Check execPath if (execPath.includes('claude') && execPath.includes('desktop')) { return 'claude-desktop'; } if (execPath.includes('claude') && execPath.includes('code')) { return 'claude-code'; } if (execPath.includes('vscode') || execPath.includes('visual studio code')) { return 'vscode'; } // Check process title if (processTitle.includes('claude desktop')) { return 'claude-desktop'; } if (processTitle.includes('claude code')) { return 'claude-code'; } if (processTitle.includes('vscode') || processTitle.includes('visual studio code')) { return 'vscode'; } return null; } /** * Detect client from TERM_PROGRAM environment variable * @internal */ function detectFromTermProgram() { if (!process.env.TERM_PROGRAM) { return null; } const termProgram = process.env.TERM_PROGRAM.toLowerCase(); if (termProgram.includes('claude')) { if (termProgram.includes('desktop')) { return 'claude-desktop'; } if (termProgram.includes('code')) { return 'claude-code'; } } if (termProgram.includes('vscode')) { return 'vscode'; } return null; } /** * Detect which MCP client is running the server * * Detection heuristics (in priority order): * 1. Environment variables (most reliable) * 2. Process arguments * 3. Process metadata (execPath and title) * 4. TERM_PROGRAM environment variable * 5. Unknown (fallback) * * @returns The detected MCP client type * * @example * ```typescript * const client = detectMCPClient(); * console.log(`Running in: ${client}`); * // Output: "Running in: claude-code" * ``` */ export function detectMCPClient() { try { // FIX: Reduced cognitive complexity by extracting detection stages into helper functions // Previously: 28 (limit 15) - Now: much lower due to early returns in helpers return detectFromEnvironmentVariables() ?? detectFromProcessArguments() ?? detectFromProcessMetadata() ?? detectFromTermProgram() ?? 'unknown'; } catch { // Never throw errors - always return a valid result return 'unknown'; } } /** * Get detailed client detection information for debugging * * @returns Object containing detected client and relevant environment info * * @example * ```typescript * const info = getClientDetectionInfo(); * console.log(info); * // { * // client: 'claude-code', * // termProgram: 'claude-code', * // hasVscodeEnv: false, * // hasClaudeDesktopEnv: false * // } * ``` */ export function getClientDetectionInfo() { try { const client = detectMCPClient(); return { client, termProgram: process.env.TERM_PROGRAM, hasVscodeEnv: !!(process.env.VSCODE_CWD || process.env.VSCODE_PID || process.env.VSCODE_IPC_HOOK), hasClaudeDesktopEnv: !!(process.env.CLAUDE_DESKTOP || process.env.CLAUDE_DESKTOP_VERSION), hasClaudeCodeEnv: !!(process.env.CLAUDE_CODE || (process.env.TERM_PROGRAM === 'claude-code')), processTitle: process.title, execPath: process.execPath }; } catch { // Never throw - return minimal safe info return { client: 'unknown', hasVscodeEnv: false, hasClaudeDesktopEnv: false, hasClaudeCodeEnv: false }; } } /** * Check if running in a specific MCP client * * @param client - The client type to check for * @returns True if running in the specified client * * @example * ```typescript * if (isRunningInClient('claude-code')) { * console.log('Running in Claude Code'); * } * ``` */ export function isRunningInClient(client) { try { return detectMCPClient() === client; } catch { return false; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50RGV0ZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVsZW1ldHJ5L2NsaWVudERldGVjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7O0dBT0c7QUFJSDs7O0dBR0c7QUFDSCxTQUFTLDhCQUE4QjtJQUNyQywyQkFBMkI7SUFDM0IsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsS0FBSyxNQUFNLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQ2hGLE9BQU8sZ0JBQWdCLENBQUM7SUFDMUIsQ0FBQztJQUVELHdCQUF3QjtJQUN4QixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxLQUFLLE1BQU0sSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksS0FBSyxhQUFhLEVBQUUsQ0FBQztRQUNyRixPQUFPLGFBQWEsQ0FBQztJQUN2QixDQUFDO0lBRUQsb0JBQW9CO0lBQ3BCLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVO1FBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCO1FBQzVELE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzFDLE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLDBCQUEwQjtJQUNqQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUVsRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFD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LE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxNQUFxQjtJQUNyRCxJQUFJLENBQUM7UUFDSCxPQUFPLGVBQWUsRUFBRSxLQUFLLE1BQU0sQ0FBQztJQUN0QyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTUNQIENsaWVudCBEZXRlY3RvciBmb3IgVGVsZW1ldHJ5XG4gKlxuICogRGV0ZWN0cyB3aGljaCBNQ1AgY2xpZW50IGlzIHJ1bm5pbmcgdGhlIHNlcnZlciBieSBleGFtaW5pbmcgZW52aXJvbm1lbnQgdmFyaWFibGVzLFxuICogcHJvY2VzcyBhcmd1bWVudHMsIGFuZCBwYXJlbnQgcHJvY2VzcyBpbmZvcm1hdGlvbi4gVXNlZCBmb3IgdGVsZW1ldHJ5IGFuZCBkZWJ1Z2dpbmcuXG4gKlxuICogSXNzdWUgIzEzNTg6IE1DUCBjbGllbnQgZGV0ZWN0aW9uIGZvciBlbmhhbmNlZCB0ZWxlbWV0cnlcbiAqL1xuXG5leHBvcnQgdHlwZSBNQ1BDbGllbnRUeXBlID0gJ2NsYXVkZS1kZXNrdG9wJyB8ICdjbGF1ZGUtY29kZScgfCAndnNjb2RlJyB8ICd1bmtub3duJztcblxuLyoqXG4gKiBEZXRlY3QgY2xpZW50IGZyb20gZW52aXJvbm1lbnQgdmFyaWFibGVzIChtb3N0IHJlbGlhYmxlKVxuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIGRldGVjdEZyb21FbnZpcm9ubWVudFZhcmlhYmxlcygpOiBNQ1BDbGllbnRUeXBlIHwgbnVsbCB7XG4gIC8vIENsYXVkZSBEZXNrdG9wIGRldGVjdGlvblxuICBpZiAocHJvY2Vzcy5lbnYuQ0xBVURFX0RFU0tUT1AgPT09ICd0cnVlJyB8fCBwcm9jZXNzLmVudi5DTEFVREVfREVTS1RPUF9WRVJTSU9OKSB7XG4gICAgcmV0dXJuICdjbGF1ZGUtZGVza3RvcCc7XG4gIH1cblxuICAvLyBDbGF1ZGUgQ29kZSBkZXRlY3Rpb25cbiAgaWYgKHByb2Nlc3MuZW52LkNMQVVERV9DT0RFID09PSAndHJ1ZScgfHwgcHJvY2Vzcy5lbnYuVEVSTV9QUk9HUkFNID09PSAnY2xhdWRlLWNvZGUnKSB7XG4gICAgcmV0dXJuICdjbGF1ZGUtY29kZSc7XG4gIH1cblxuICAvLyBWUyBDb2RlIGRldGVjdGlvblxuICBpZiAocHJvY2Vzcy5lbnYuVlNDT0RFX0NXRCB8fCBwcm9jZXNzLmVudi5WU0NPREVfUElEIHx8XG4gICAgICBwcm9jZXNzLmVudi5WU0NPREVfSVBDX0hPT0sgfHwgcHJvY2Vzcy5lbnYuVlNDT0RFX05MU19DT05GSUcgfHxcbiAgICAgIHByb2Nlc3MuZW52LlRFUk1fUFJPR1JBTSA9PT0gJ3ZzY29kZScpIHtcbiAgICByZXR1cm4gJ3ZzY29kZSc7XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBEZXRlY3QgY2xpZW50IGZyb20gcHJvY2VzcyBhcmd1bWVudHNcbiAqIEBpbnRlcm5hbFxuICovXG5mdW5jdGlvbiBkZXRlY3RGcm9tUHJvY2Vzc0FyZ3VtZW50cygpOiBNQ1BDbGllbnRUeXBlIHwgbnVsbCB7XG4gIGNvbnN0IGFyZ3YgPSBwcm9jZXNzLmFyZ3Yuam9pbignICcpLnRvTG93ZXJDYXNlKCk7XG5cbiAgaWYgKGFyZ3YuaW5jbHVkZXMoJ2NsYXVkZScpICYmIGFyZ3YuaW5jbHVkZXMoJ2Rlc2t0b3AnKSkge1xuICAgIHJldHVybiAnY2xhdWRlLWRlc2t0b3AnO1xuICB9XG5cbiAgaWYgKGFyZ3YuaW5jbHVkZXMoJ2NsYXVkZScpICYmIGFyZ3YuaW5jbHVkZXMoJ2NvZGUnKSkge1xuICAgIHJldHVybiAnY2xhdWRlLWNvZGUnO1xuICB9XG5cbiAgaWYgKGFyZ3YuaW5jbHVkZXMoJ3ZzY29kZScpIHx8IGFyZ3YuaW5jbHVkZXMoJ2NvZGUuZXhlJykpIHtcbiAgICByZXR1cm4gJ3ZzY29kZSc7XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBEZXRlY3QgY2xpZW50IGZyb20gcHJvY2VzcyBtZXRhZGF0YSAoZXhlY1BhdGggYW5kIHRpdGxlKVxuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIGRldGVjdEZyb21Qcm9jZXNzTWV0YWRhdGEoKTogTUNQQ2xpZW50VHlwZSB8IG51bGwge1xuICBjb25zdCBleGVjUGF0aCA9IHByb2Nlc3MuZXhlY1BhdGg/LnRvTG93ZXJDYXNlKCkgPz8gJyc7XG4gIGNvbnN0IHByb2Nlc3NUaXRsZSA9IHByb2Nlc3MudGl0bGU/LnRvTG93ZXJDYXNlKCkgPz8gJyc7XG5cbiAgLy8gQ2hlY2sgZXhlY1BhdGhcbiAgaWYgKGV4ZWNQYXRoLmluY2x1ZGVzKCdjbGF1ZGUnKSAmJiBleGVjUGF0aC5pbmNsdWRlcygnZGVza3RvcCcpKSB7XG4gICAgcmV0dXJuICdjbGF1ZGUtZGVza3RvcCc7XG4gIH1cbiAgaWYgKGV4ZWNQYXRoLmluY2x1ZGVzKCdjbGF1ZGUnKSAmJiBleGVjUGF0aC5pbmNsdWRlcygnY29kZScpKSB7XG4gICAgcmV0dXJuICdjbGF1ZGUtY29kZSc7XG4gIH1cbiAgaWYgKGV4ZWNQYXRoLmluY2x1ZGVzKCd2c2NvZGUnKSB8fCBleGVjUGF0aC5pbmNsdWRlcygndmlzdWFsIHN0dWRpbyBjb2RlJykpIHtcbiAgICByZXR1cm4gJ3ZzY29kZSc7XG4gIH1cblxuICAvLyBDaGVjayBwcm9jZXNzIHRpdGxlXG4gIGlmIChwcm9jZXNzVGl0bGUuaW5jbHVkZXMoJ2NsYXVkZSBkZXNrdG9wJykpIHtcbiAgICByZXR1cm4gJ2NsYXVkZS1kZXNrdG9wJztcbiAgfVxuICBpZiAocHJvY2Vzc1RpdGxlLmluY2x1ZGVzKCdjbGF1ZGUgY29kZScpKSB7XG4gICAgcmV0dXJuICdjbGF1ZGUtY29kZSc7XG4gIH1cbiAgaWYgKHByb2Nlc3NUaXRsZS5pbmNsdWRlcygndnNjb2RlJykgfHwgcHJvY2Vzc1RpdGxlLmluY2x1ZGVzKCd2aXN1YWwgc3R1ZGlvIGNvZGUnKSkge1xuICAgIHJldHVybiAndnNjb2RlJztcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIERldGVjdCBjbGllbnQgZnJvbSBURVJNX1BST0dSQU0gZW52aXJvbm1lbnQgdmFyaWFibGVcbiAqIEBpbnRlcm5hbFxuICovXG5mdW5jdGlvbiBkZXRlY3RGcm9tVGVybVByb2dyYW0oKTogTUNQQ2xpZW50VHlwZSB8IG51bGwge1xuICBpZiAoIXByb2Nlc3MuZW52LlRFUk1fUFJPR1JBTSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdGVybVByb2dyYW0gPSBwcm9jZXNzLmVudi5URVJNX1BST0dSQU0udG9Mb3dlckNhc2UoKTtcblxuICBpZiAodGVybVByb2dyYW0uaW5jbHVkZXMoJ2NsYXVkZScpKSB7XG4gICAgaWYgKHRlcm1Qcm9ncmFtLmluY2x1ZGVzKCdkZXNrdG9wJykpIHtcbiAgICAgIHJldHVybiAnY2xhdWRlLWRlc2t0b3AnO1xuICAgIH1cbiAgICBpZiAodGVybVByb2dyYW0uaW5jbHVkZXMoJ2NvZGUnKSkge1xuICAgICAgcmV0dXJuICdjbGF1ZGUtY29kZSc7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRlcm1Qcm9ncmFtLmluY2x1ZGVzKCd2c2NvZGUnKSkge1xuICAgIHJldHVybiAndnNjb2RlJztcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIERldGVjdCB3aGljaCBNQ1AgY2xpZW50IGlzIHJ1bm5pbmcgdGhlIHNlcnZlclxuICpcbiAqIERldGVjdGlvbiBoZXVyaXN0aWNzIChpbiBwcmlvcml0eSBvcmRlcik6XG4gKiAxLiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgKG1vc3QgcmVsaWFibGUpXG4gKiAyLiBQcm9jZXNzIGFyZ3VtZW50c1xuICogMy4gUHJvY2VzcyBtZXRhZGF0YSAoZXhlY1BhdGggYW5kIHRpdGxlKVxuICogNC4gVEVSTV9QUk9HUkFNIGVudmlyb25tZW50IHZhcmlhYmxlXG4gKiA1LiBVbmtub3duIChmYWxsYmFjaylcbiAqXG4gKiBAcmV0dXJucyBUaGUgZGV0ZWN0ZWQgTUNQIGNsaWVudCB0eXBlXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGNsaWVudCA9IGRldGVjdE1DUENsaWVudCgpO1xuICogY29uc29sZS5sb2coYFJ1bm5pbmcgaW46ICR7Y2xpZW50fWApO1xuICogLy8gT3V0cHV0OiBcIlJ1bm5pbmcgaW46IGNsYXVkZS1jb2RlXCJcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGV0ZWN0TUNQQ2xpZW50KCk6IE1DUENsaWVudFR5cGUge1xuICB0cnkge1xuICAgIC8vIEZJWDogUmVkdWNlZCBjb2duaXRpdmUgY29tcGxleGl0eSBieSBleHRyYWN0aW5nIGRldGVjdGlvbiBzdGFnZXMgaW50byBoZWxwZXIgZnVuY3Rpb25zXG4gICAgLy8gUHJldmlvdXNseTogMjggKGxpbWl0IDE1KSAtIE5vdzogbXVjaCBsb3dlciBkdWUgdG8gZWFybHkgcmV0dXJucyBpbiBoZWxwZXJzXG4gICAgcmV0dXJuIGRldGVjdEZyb21FbnZpcm9ubWVudFZhcmlhYmxlcygpID8/XG4gICAgICAgICAgIGRldGVjdEZyb21Qcm9jZXNzQXJndW1lbnRzKCkgPz9cbiAgICAgICAgICAgZGV0ZWN0RnJvbVByb2Nlc3NNZXRhZGF0YSgpID8/XG4gICAgICAgICAgIGRldGVjdEZyb21UZXJtUHJvZ3JhbSgpID8/XG4gICAgICAgICAgICd1bmtub3duJztcbiAgfSBjYXRjaCB7XG4gICAgLy8gTmV2ZXIgdGhyb3cgZXJyb3JzIC0gYWx3YXlzIHJldHVybiBhIHZhbGlkIHJlc3VsdFxuICAgIHJldHVybiAndW5rbm93bic7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXQgZGV0YWlsZWQgY2xpZW50IGRldGVjdGlvbiBpbmZvcm1hdGlvbiBmb3IgZGVidWdnaW5nXG4gKlxuICogQHJldHVybnMgT2JqZWN0IGNvbnRhaW5pbmcgZGV0ZWN0ZWQgY2xpZW50IGFuZCByZWxldmFudCBlbnZpcm9ubWVudCBpbmZvXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGluZm8gPSBnZXRDbGllbnREZXRlY3Rpb25JbmZvKCk7XG4gKiBjb25zb2xlLmxvZyhpbmZvKTtcbiAqIC8vIHtcbiAqIC8vICAgY2xpZW50OiAnY2xhdWRlLWNvZGUnLFxuICogLy8gICB0ZXJtUHJvZ3JhbTogJ2NsYXVkZS1jb2RlJyxcbiAqIC8vICAgaGFzVnNjb2RlRW52OiBmYWxzZSxcbiAqIC8vICAgaGFzQ2xhdWRlRGVza3RvcEVudjogZmFsc2VcbiAqIC8vIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q2xpZW50RGV0ZWN0aW9uSW5mbygpOiB7XG4gIGNsaWVudDogTUNQQ2xpZW50VHlwZTtcbiAgdGVybVByb2dyYW0/OiBzdHJpbmc7XG4gIGhhc1ZzY29kZUVudjogYm9vbGVhbjtcbiAgaGFzQ2xhdWRlRGVza3RvcEVudjogYm9vbGVhbjtcbiAgaGFzQ2xhdWRlQ29kZUVudjogYm9vbGVhbjtcbiAgcHJvY2Vzc1RpdGxlPzogc3RyaW5nO1xuICBleGVjUGF0aD86IHN0cmluZztcbn0ge1xuICB0cnkge1xuICAgIGNvbnN0IGNsaWVudCA9IGRldGVjdE1DUENsaWVudCgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNsaWVudCxcbiAgICAgIHRlcm1Qcm9ncmFtOiBwcm9jZXNzLmVudi5URVJNX1BST0dSQU0sXG4gICAgICBoYXNWc2NvZGVFbnY6ICEhKFxuICAgICAgICBwcm9jZXNzLmVudi5WU0NPREVfQ1dEIHx8XG4gICAgICAgIHByb2Nlc3MuZW52LlZTQ09ERV9QSUQgfHxcbiAgICAgICAgcHJvY2Vzcy5lbnYuVlNDT0RFX0lQQ19IT09LXG4gICAgICApLFxuICAgICAgaGFzQ2xhdWRlRGVza3RvcEVudjogISEoXG4gICAgICAgIHByb2Nlc3MuZW52LkNMQVVERV9ERVNLVE9QIHx8XG4gICAgICAgIHByb2Nlc3MuZW52LkNMQVVERV9ERVNLVE9QX1ZFUlNJT05cbiAgICAgICksXG4gICAgICBoYXNDbGF1ZGVDb2RlRW52OiAhIShcbiAgICAgICAgcHJvY2Vzcy5lbnYuQ0xBVURFX0NPREUgfHxcbiAgICAgICAgKHByb2Nlc3MuZW52LlRFUk1fUFJPR1JBTSA9PT0gJ2NsYXVkZS1jb2RlJylcbiAgICAgICksXG4gICAgICBwcm9jZXNzVGl0bGU6IHByb2Nlc3MudGl0bGUsXG4gICAgICBleGVjUGF0aDogcHJvY2Vzcy5leGVjUGF0aFxuICAgIH07XG4gIH0gY2F0Y2gge1xuICAgIC8vIE5ldmVyIHRocm93IC0gcmV0dXJuIG1pbmltYWwgc2FmZSBpbmZvXG4gICAgcmV0dXJuIHtcbiAgICAgIGNsaWVudDogJ3Vua25vd24nLFxuICAgICAgaGFzVnNjb2RlRW52OiBmYWxzZSxcbiAgICAgIGhhc0NsYXVkZURlc2t0b3BFbnY6IGZhbHNlLFxuICAgICAgaGFzQ2xhdWRlQ29kZUVudjogZmFsc2VcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgcnVubmluZyBpbiBhIHNwZWNpZmljIE1DUCBjbGllbnRcbiAqXG4gKiBAcGFyYW0gY2xpZW50IC0gVGhlIGNsaWVudCB0eXBlIHRvIGNoZWNrIGZvclxuICogQHJldHVybnMgVHJ1ZSBpZiBydW5uaW5nIGluIHRoZSBzcGVjaWZpZWQgY2xpZW50XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGlmIChpc1J1bm5pbmdJbkNsaWVudCgnY2xhdWRlLWNvZGUnKSkge1xuICogICBjb25zb2xlLmxvZygnUnVubmluZyBpbiBDbGF1ZGUgQ29kZScpO1xuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1J1bm5pbmdJbkNsaWVudChjbGllbnQ6IE1DUENsaWVudFR5cGUpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZGV0ZWN0TUNQQ2xpZW50KCkgPT09IGNsaWVudDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG4iXX0=