UNPKG

llmverify

Version:

AI Output Verification Toolkit — Local-first LLM safety, hallucination detection, PII redaction, prompt injection defense, and runtime monitoring. Zero telemetry. OWASP LLM Top 10 aligned.

182 lines 20.6 kB
"use strict"; /** * Plugin API * * High-level API for creating and using plugins * * @module plugins/api */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createPlugin = createPlugin; exports.use = use; exports.createBlacklistPlugin = createBlacklistPlugin; exports.createRegexPlugin = createRegexPlugin; exports.createLengthValidatorPlugin = createLengthValidatorPlugin; exports.createKeywordDetectorPlugin = createKeywordDetectorPlugin; const registry_1 = require("./registry"); /** * Helper function to create a plugin */ function createPlugin(config) { return { id: config.id, name: config.name, version: config.version || '1.0.0', description: config.description, author: config.author, category: config.category || 'custom', enabled: config.enabled !== false, priority: config.priority || 0, execute: config.execute }; } /** * Use a plugin (register and enable) */ function use(plugin) { const registry = (0, registry_1.getPluginRegistry)(); registry.register(plugin); } /** * Create a blacklist plugin */ function createBlacklistPlugin(blacklist, options) { return createPlugin({ id: options?.id || 'blacklist', name: options?.name || 'Blacklist Filter', description: 'Detects blacklisted words', category: 'security', execute: (context) => { const findings = []; const content = options?.caseSensitive ? context.content : context.content.toLowerCase(); for (const word of blacklist) { const searchWord = options?.caseSensitive ? word : word.toLowerCase(); if (content.includes(searchWord)) { findings.push({ category: 'security', severity: 'medium', message: `Blacklisted term detected: ${word}` }); } } return { findings, score: findings.length > 0 ? 0.5 : 0 }; } }); } /** * Create a regex pattern plugin */ function createRegexPlugin(patterns, options) { return createPlugin({ id: options?.id || 'regex-patterns', name: options?.name || 'Regex Patterns', description: 'Detects custom regex patterns', category: 'custom', execute: (context) => { const findings = []; for (const { pattern, message, severity } of patterns) { try { const matches = context.content.match(pattern); if (matches) { findings.push({ category: 'custom', severity: severity || 'medium', message: message }); } } catch (error) { console.error('Regex pattern error:', error); } } return { findings, score: findings.length > 0 ? 0.5 : 0 }; } }); } /** * Create a length validator plugin */ function createLengthValidatorPlugin(config, options) { return createPlugin({ id: options?.id || 'length-validator', name: options?.name || 'Length Validator', description: 'Validates content length', category: 'quality', execute: (context) => { const findings = []; const length = context.content.length; if (config.min && length < config.min) { findings.push({ category: 'quality', severity: 'low', message: `Content too short: ${length} < ${config.min}`, metadata: { length, min: config.min } }); } if (config.max && length > config.max) { findings.push({ category: 'quality', severity: 'medium', message: `Content too long: ${length} > ${config.max}`, metadata: { length, max: config.max } }); } return { findings, score: findings.length > 0 ? 0.3 : 0 }; } }); } /** * Create a keyword detector plugin */ function createKeywordDetectorPlugin(keywords, options) { return createPlugin({ id: options?.id || 'keyword-detector', name: options?.name || 'Keyword Detector', description: 'Detects required and forbidden keywords', category: 'quality', execute: (context) => { const findings = []; const content = options?.caseSensitive ? context.content : context.content.toLowerCase(); // Check required keywords if (keywords.required) { for (const keyword of keywords.required) { const searchKeyword = options?.caseSensitive ? keyword : keyword.toLowerCase(); if (!content.includes(searchKeyword)) { findings.push({ category: 'quality', severity: 'medium', message: `Required keyword missing: ${keyword}` }); } } } // Check forbidden keywords if (keywords.forbidden) { for (const keyword of keywords.forbidden) { const searchKeyword = options?.caseSensitive ? keyword : keyword.toLowerCase(); if (content.includes(searchKeyword)) { findings.push({ category: 'security', severity: 'high', message: `Forbidden keyword detected: ${keyword}` }); } } } return { findings, score: findings.length > 0 ? 0.6 : 0 }; } }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbnMvYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBT0gsb0NBc0JDO0FBS0Qsa0JBR0M7QUFLRCxzREErQkM7QUFLRCw4Q0FxQ0M7QUFLRCxrRUF3Q0M7QUFLRCxrRUFtREM7QUF0TkQseUNBQXVFO0FBRXZFOztHQUVHO0FBQ0gsU0FBZ0IsWUFBWSxDQUFDLE1BVTVCO0lBQ0MsT0FBTztRQUNMLEVBQUUsRUFBRSxNQUFNLENBQUMsRUFBRTtRQUNiLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtRQUNqQixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sSUFBSSxPQUFPO1FBQ2xDLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztRQUMvQixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07UUFDckIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLElBQUksUUFBUTtRQUNyQyxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sS0FBSyxLQUFLO1FBQ2pDLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxJQUFJLENBQUM7UUFDOUIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO0tBQ3hCLENBQUM7QUFDSixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixHQUFHLENBQUMsTUFBYztJQUNoQyxNQUFNLFFBQVEsR0FBRyxJQUFBLDRCQUFpQixHQUFFLENBQUM7SUFDckMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUM1QixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixxQkFBcUIsQ0FBQyxTQUFtQixFQUFFLE9BSTFEO0lBQ0MsT0FBTyxZQUFZLENBQUM7UUFDbEIsRUFBRSxFQUFFLE9BQU8sRUFBRSxFQUFFLElBQUksV0FBVztRQUM5QixJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksSUFBSSxrQkFBa0I7UUFDekMsV0FBVyxFQUFFLDJC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Q0FBQyxJQUFJLENBQUM7NEJBQ1osUUFBUSxFQUFFLFVBQVU7NEJBQ3BCLFFBQVEsRUFBRSxNQUFNOzRCQUNoQixPQUFPLEVBQUUsK0JBQStCLE9BQU8sRUFBRTt5QkFDbEQsQ0FBQyxDQUFDO29CQUNMLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7WUFFRCxPQUFPO2dCQUNMLFFBQVE7Z0JBQ1IsS0FBSyxFQUFFLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDckMsQ0FBQztRQUNKLENBQUM7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQbHVnaW4gQVBJXG4gKiBcbiAqIEhpZ2gtbGV2ZWwgQVBJIGZvciBjcmVhdGluZyBhbmQgdXNpbmcgcGx1Z2luc1xuICogXG4gKiBAbW9kdWxlIHBsdWdpbnMvYXBpXG4gKi9cblxuaW1wb3J0IHsgUGx1Z2luLCBQbHVnaW5GdW5jdGlvbiwgZ2V0UGx1Z2luUmVnaXN0cnkgfSBmcm9tICcuL3JlZ2lzdHJ5JztcblxuLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdG8gY3JlYXRlIGEgcGx1Z2luXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVQbHVnaW4oY29uZmlnOiB7XG4gIGlkOiBzdHJpbmc7XG4gIG5hbWU6IHN0cmluZztcbiAgdmVyc2lvbj86IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIGF1dGhvcj86IHN0cmluZztcbiAgY2F0ZWdvcnk/OiBQbHVnaW5bJ2NhdGVnb3J5J107XG4gIGVuYWJsZWQ/OiBib29sZWFuO1xuICBwcmlvcml0eT86IG51bWJlcjtcbiAgZXhlY3V0ZTogUGx1Z2luRnVuY3Rpb247XG59KTogUGx1Z2luIHtcbiAgcmV0dXJuIHtcbiAgICBpZDogY29uZmlnLmlkLFxuICAgIG5hbWU6IGNvbmZpZy5uYW1lLFxuICAgIHZlcnNpb246IGNvbmZpZy52ZXJzaW9uIHx8ICcxLjAuMCcsXG4gICAgZGVzY3JpcHRpb246IGNvbmZpZy5kZXNjcmlwdGlvbixcbiAgICBhdXRob3I6IGNvbmZpZy5hdXRob3IsXG4gICAgY2F0ZWdvcnk6IGNvbmZpZy5jYXRlZ29yeSB8fCAnY3VzdG9tJyxcbiAgICBlbmFibGVkOiBjb25maWcuZW5hYmxlZCAhPT0gZmFsc2UsXG4gICAgcHJpb3JpdHk6IGNvbmZpZy5wcmlvcml0eSB8fCAwLFxuICAgIGV4ZWN1dGU6IGNvbmZpZy5leGVjdXRlXG4gIH07XG59XG5cbi8qKlxuICogVXNlIGEgcGx1Z2luIChyZWdpc3RlciBhbmQgZW5hYmxlKVxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlKHBsdWdpbjogUGx1Z2luKTogdm9pZCB7XG4gIGNvbnN0IHJlZ2lzdHJ5ID0gZ2V0UGx1Z2luUmVnaXN0cnkoKTtcbiAgcmVnaXN0cnkucmVnaXN0ZXIocGx1Z2luKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBibGFja2xpc3QgcGx1Z2luXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVCbGFja2xpc3RQbHVnaW4oYmxhY2tsaXN0OiBzdHJpbmdbXSwgb3B0aW9ucz86IHtcbiAgaWQ/OiBzdHJpbmc7XG4gIG5hbWU/OiBzdHJpbmc7XG4gIGNhc2VTZW5zaXRpdmU/OiBib29sZWFuO1xufSk6IFBsdWdpbiB7XG4gIHJldHVybiBjcmVhdGVQbHVnaW4oe1xuICAgIGlkOiBvcHRpb25zPy5pZCB8fCAnYmxhY2tsaXN0JyxcbiAgICBuYW1lOiBvcHRpb25zPy5uYW1lIHx8ICdCbGFja2xpc3QgRmlsdGVyJyxcbiAgICBkZXNjcmlwdGlvbjogJ0RldGVjdHMgYmxhY2tsaXN0ZWQgd29yZHMnLFxuICAgIGNhdGVnb3J5OiAnc2VjdXJpdHknLFxuICAgIGV4ZWN1dGU6IChjb250ZXh0KSA9PiB7XG4gICAgICBjb25zdCBmaW5kaW5nczogYW55W10gPSBbXTtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBvcHRpb25zPy5jYXNlU2Vuc2l0aXZlID8gY29udGV4dC5jb250ZW50IDogY29udGV4dC5jb250ZW50LnRvTG93ZXJDYXNlKCk7XG4gICAgICBcbiAgICAgIGZvciAoY29uc3Qgd29yZCBvZiBibGFja2xpc3QpIHtcbiAgICAgICAgY29uc3Qgc2VhcmNoV29yZCA9IG9wdGlvbnM/LmNhc2VTZW5zaXRpdmUgPyB3b3JkIDogd29yZC50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAoY29udGVudC5pbmNsdWRlcyhzZWFyY2hXb3JkKSkge1xuICAgICAgICAgIGZpbmRpbmdzLnB1c2goe1xuICAgICAgICAgICAgY2F0ZWdvcnk6ICdzZWN1cml0eScsXG4gICAgICAgICAgICBzZXZlcml0eTogJ21lZGl1bScsXG4gICAgICAgICAgICBtZXNzYWdlOiBgQmxhY2tsaXN0ZWQgdGVybSBkZXRlY3RlZDogJHt3b3JkfWBcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBmaW5kaW5ncyxcbiAgICAgICAgc2NvcmU6IGZpbmRpbmdzLmxlbmd0aCA+IDAgPyAwLjUgOiAwXG4gICAgICB9O1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgcmVnZXggcGF0dGVybiBwbHVnaW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlZ2V4UGx1Z2luKHBhdHRlcm5zOiBBcnJheTx7XG4gIHBhdHRlcm46IFJlZ0V4cDtcbiAgbWVzc2FnZTogc3RyaW5nO1xuICBzZXZlcml0eT86IHN0cmluZztcbn0+LCBvcHRpb25zPzoge1xuICBpZD86IHN0cmluZztcbiAgbmFtZT86IHN0cmluZztcbn0pOiBQbHVnaW4ge1xuICByZXR1cm4gY3JlYXRlUGx1Z2luKHtcbiAgICBpZDogb3B0aW9ucz8uaWQgfHwgJ3JlZ2V4LXBhdHRlcm5zJyxcbiAgICBuYW1lOiBvcHRpb25zPy5uYW1lIHx8ICdSZWdleCBQYXR0ZXJucycsXG4gICAgZGVzY3JpcHRpb246ICdEZXRlY3RzIGN1c3RvbSByZWdleCBwYXR0ZXJucycsXG4gICAgY2F0ZWdvcnk6ICdjdXN0b20nLFxuICAgIGV4ZWN1dGU6IChjb250ZXh0KSA9PiB7XG4gICAgICBjb25zdCBmaW5kaW5nczogYW55W10gPSBbXTtcbiAgICAgIFxuICAgICAgZm9yIChjb25zdCB7IHBhdHRlcm4sIG1lc3NhZ2UsIHNldmVyaXR5IH0gb2YgcGF0dGVybnMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBtYXRjaGVzID0gY29udGV4dC5jb250ZW50Lm1hdGNoKHBhdHRlcm4pO1xuICAgICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICBmaW5kaW5ncy5wdXNoKHtcbiAgICAgICAgICAgICAgY2F0ZWdvcnk6ICdjdXN0b20nLFxuICAgICAgICAgICAgICBzZXZlcml0eTogc2V2ZXJpdHkgfHwgJ21lZGl1bScsXG4gICAgICAgICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdSZWdleCBwYXR0ZXJuIGVycm9yOicsIGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBmaW5kaW5ncyxcbiAgICAgICAgc2NvcmU6IGZpbmRpbmdzLmxlbmd0aCA+IDAgPyAwLjUgOiAwXG4gICAgICB9O1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgbGVuZ3RoIHZhbGlkYXRvciBwbHVnaW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUxlbmd0aFZhbGlkYXRvclBsdWdpbihjb25maWc6IHtcbiAgbWluPzogbnVtYmVyO1xuICBtYXg/OiBudW1iZXI7XG59LCBvcHRpb25zPzoge1xuICBpZD86IHN0cmluZztcbiAgbmFtZT86IHN0cmluZztcbn0pOiBQbHVnaW4ge1xuICByZXR1cm4gY3JlYXRlUGx1Z2luKHtcbiAgICBpZDogb3B0aW9ucz8uaWQgfHwgJ2xlbmd0aC12YWxpZGF0b3InLFxuICAgIG5hbWU6IG9wdGlvbnM/Lm5hbWUgfHwgJ0xlbmd0aCBWYWxpZGF0b3InLFxuICAgIGRlc2NyaXB0aW9uOiAnVmFsaWRhdGVzIGNvbnRlbnQgbGVuZ3RoJyxcbiAgICBjYXRlZ29yeTogJ3F1YWxpdHknLFxuICAgIGV4ZWN1dGU6IChjb250ZXh0KSA9PiB7XG4gICAgICBjb25zdCBmaW5kaW5nczogYW55W10gPSBbXTtcbiAgICAgIGNvbnN0IGxlbmd0aCA9IGNvbnRleHQuY29udGVudC5sZW5ndGg7XG4gICAgICBcbiAgICAgIGlmIChjb25maWcubWluICYmIGxlbmd0aCA8IGNvbmZpZy5taW4pIHtcbiAgICAgICAgZmluZGluZ3MucHVzaCh7XG4gICAgICAgICAgY2F0ZWdvcnk6ICdxdWFsaXR5JyxcbiAgICAgICAgICBzZXZlcml0eTogJ2xvdycsXG4gICAgICAgICAgbWVzc2FnZTogYENvbnRlbnQgdG9vIHNob3J0OiAke2xlbmd0aH0gPCAke2NvbmZpZy5taW59YCxcbiAgICAgICAgICBtZXRhZGF0YTogeyBsZW5ndGgsIG1pbjogY29uZmlnLm1pbiB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgXG4gICAgICBpZiAoY29uZmlnLm1heCAmJiBsZW5ndGggPiBjb25maWcubWF4KSB7XG4gICAgICAgIGZpbmRpbmdzLnB1c2goe1xuICAgICAgICAgIGNhdGVnb3J5OiAncXVhbGl0eScsXG4gICAgICAgICAgc2V2ZXJpdHk6ICdtZWRpdW0nLFxuICAgICAgICAgIG1lc3NhZ2U6IGBDb250ZW50IHRvbyBsb25nOiAke2xlbmd0aH0gPiAke2NvbmZpZy5tYXh9YCxcbiAgICAgICAgICBtZXRhZGF0YTogeyBsZW5ndGgsIG1heDogY29uZmlnLm1heCB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBmaW5kaW5ncyxcbiAgICAgICAgc2NvcmU6IGZpbmRpbmdzLmxlbmd0aCA+IDAgPyAwLjMgOiAwXG4gICAgICB9O1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGEga2V5d29yZCBkZXRlY3RvciBwbHVnaW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUtleXdvcmREZXRlY3RvclBsdWdpbihrZXl3b3Jkczoge1xuICByZXF1aXJlZD86IHN0cmluZ1tdO1xuICBmb3JiaWRkZW4/OiBzdHJpbmdbXTtcbn0sIG9wdGlvbnM/OiB7XG4gIGlkPzogc3RyaW5nO1xuICBuYW1lPzogc3RyaW5nO1xuICBjYXNlU2Vuc2l0aXZlPzogYm9vbGVhbjtcbn0pOiBQbHVnaW4ge1xuICByZXR1cm4gY3JlYXRlUGx1Z2luKHtcbiAgICBpZDogb3B0aW9ucz8uaWQgfHwgJ2tleXdvcmQtZGV0ZWN0b3InLFxuICAgIG5hbWU6IG9wdGlvbnM/Lm5hbWUgfHwgJ0tleXdvcmQgRGV0ZWN0b3InLFxuICAgIGRlc2NyaXB0aW9uOiAnRGV0ZWN0cyByZXF1aXJlZCBhbmQgZm9yYmlkZGVuIGtleXdvcmRzJyxcbiAgICBjYXRlZ29yeTogJ3F1YWxpdHknLFxuICAgIGV4ZWN1dGU6IChjb250ZXh0KSA9PiB7XG4gICAgICBjb25zdCBmaW5kaW5nczogYW55W10gPSBbXTtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBvcHRpb25zPy5jYXNlU2Vuc2l0aXZlID8gY29udGV4dC5jb250ZW50IDogY29udGV4dC5jb250ZW50LnRvTG93ZXJDYXNlKCk7XG4gICAgICBcbiAgICAgIC8vIENoZWNrIHJlcXVpcmVkIGtleXdvcmRzXG4gICAgICBpZiAoa2V5d29yZHMucmVxdWlyZWQpIHtcbiAgICAgICAgZm9yIChjb25zdCBrZXl3b3JkIG9mIGtleXdvcmRzLnJlcXVpcmVkKSB7XG4gICAgICAgICAgY29uc3Qgc2VhcmNoS2V5d29yZCA9IG9wdGlvbnM/LmNhc2VTZW5zaXRpdmUgPyBrZXl3b3JkIDoga2V5d29yZC50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgIGlmICghY29udGVudC5pbmNsdWRlcyhzZWFyY2hLZXl3b3JkKSkge1xuICAgICAgICAgICAgZmluZGluZ3MucHVzaCh7XG4gICAgICAgICAgICAgIGNhdGVnb3J5OiAncXVhbGl0eScsXG4gICAgICAgICAgICAgIHNldmVyaXR5OiAnbWVkaXVtJyxcbiAgICAgICAgICAgICAgbWVzc2FnZTogYFJlcXVpcmVkIGtleXdvcmQgbWlzc2luZzogJHtrZXl3b3JkfWBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBDaGVjayBmb3JiaWRkZW4ga2V5d29yZHNcbiAgICAgIGlmIChrZXl3b3Jkcy5mb3JiaWRkZW4pIHtcbiAgICAgICAgZm9yIChjb25zdCBrZXl3b3JkIG9mIGtleXdvcmRzLmZvcmJpZGRlbikge1xuICAgICAgICAgIGNvbnN0IHNlYXJjaEtleXdvcmQgPSBvcHRpb25zPy5jYXNlU2Vuc2l0aXZlID8ga2V5d29yZCA6IGtleXdvcmQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICBpZiAoY29udGVudC5pbmNsdWRlcyhzZWFyY2hLZXl3b3JkKSkge1xuICAgICAgICAgICAgZmluZGluZ3MucHVzaCh7XG4gICAgICAgICAgICAgIGNhdGVnb3J5OiAnc2VjdXJpdHknLFxuICAgICAgICAgICAgICBzZXZlcml0eTogJ2hpZ2gnLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBgRm9yYmlkZGVuIGtleXdvcmQgZGV0ZWN0ZWQ6ICR7a2V5d29yZH1gXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZmluZGluZ3MsXG4gICAgICAgIHNjb3JlOiBmaW5kaW5ncy5sZW5ndGggPiAwID8gMC42IDogMFxuICAgICAgfTtcbiAgICB9XG4gIH0pO1xufVxuIl19