@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
JavaScript
/**
* 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=