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.
197 lines • 17.5 kB
JavaScript
;
/**
* Intent Detection Module
*
* Detects the primary intent/purpose of LLM output.
*
* @module engines/classification/intent
* @author Haiec
* @license MIT
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectIntent = detectIntent;
exports.getPrimaryIntent = getPrimaryIntent;
const utils_1 = require("./utils");
/**
* Intent detection patterns.
*/
const INTENT_PATTERNS = [
{
tag: 'summary',
patterns: [
/\b(in summary|to summarize|overall|in conclusion|key points?|main points?)\b/i,
/\b(tldr|tl;dr|brief overview)\b/i
],
weight: 1.0
},
{
tag: 'explanation',
patterns: [
/\b(because|therefore|this means|in other words|for example|such as)\b/i,
/\b(the reason|explains?|due to|as a result)\b/i,
/\b(works by|functions by|operates by)\b/i
],
weight: 0.8
},
{
tag: 'code',
patterns: [
/```[\s\S]*```/,
/\b(function|const|let|var|class|import|export|return|if|else|for|while)\b/,
/[{}\[\]();]=>/,
/\b(def|async|await|try|catch)\b/
],
weight: 1.0
},
{
tag: 'list',
patterns: [
/^[-*•]\s+/m,
/^\d+[.)]\s+/m,
/\b(here are|the following|steps?:|items?:)\b/i
],
weight: 0.9
},
{
tag: 'question',
patterns: [
/\?$/m,
/\b(what|why|how|when|where|who|which|would you|could you|can you)\b/i
],
weight: 0.7
},
{
tag: 'instruction',
patterns: [
/\b(step \d|first,?|then,?|next,?|finally,?|make sure|ensure|remember to)\b/i,
/\b(you should|you need to|you must|please|do not|don't)\b/i
],
weight: 0.8
},
{
tag: 'creative',
patterns: [
/\b(once upon|imagine|picture this|in a world)\b/i,
/\b(poem|story|tale|narrative|fiction)\b/i
],
weight: 0.9
},
{
tag: 'analysis',
patterns: [
/\b(analysis|analyzing|examine|examining|evaluate|evaluating)\b/i,
/\b(pros and cons|advantages|disadvantages|strengths|weaknesses)\b/i,
/\b(factors|considerations|implications)\b/i
],
weight: 0.8
},
{
tag: 'comparison',
patterns: [
/\b(compared to|versus|vs\.?|differ|difference|similar|unlike|whereas)\b/i,
/\b(on the other hand|in contrast|alternatively)\b/i
],
weight: 0.9
},
{
tag: 'definition',
patterns: [
/\b(is defined as|refers to|means|is a|are a)\b/i,
/\b(definition|meaning|concept of)\b/i
],
weight: 0.7
},
{
tag: 'translation',
patterns: [
/\b(translates? to|in [a-z]+ language|translation)\b/i
],
weight: 1.0
},
{
tag: 'conversation',
patterns: [
/\b(hi|hello|hey|thanks|thank you|you're welcome|sure|okay|ok)\b/i,
/\b(I think|I believe|in my opinion|personally)\b/i
],
weight: 0.5
},
{
tag: 'data',
patterns: [
/\b(data|dataset|statistics|numbers|figures|metrics)\b/i,
/\d+%|\d+\.\d+/,
/\b(table|chart|graph)\b/i
],
weight: 0.7
}
];
/**
* Detects intent candidates from text.
*
* @param text - The text to analyze
* @returns Array of intent candidates sorted by confidence
*/
function detectIntent(text) {
const candidates = [];
const words = (0, utils_1.tokenize)(text);
const bullets = (0, utils_1.countBullets)(text);
for (const { tag, patterns, weight } of INTENT_PATTERNS) {
let matchCount = 0;
const signals = [];
for (const pattern of patterns) {
if (pattern.test(text)) {
matchCount++;
signals.push(pattern.source.substring(0, 30));
}
}
if (matchCount > 0) {
// Calculate confidence based on matches and text characteristics
let confidence = (matchCount / patterns.length) * weight;
// Boost for structural matches
if (tag === 'list' && bullets >= 3) {
confidence = Math.min(1, confidence + 0.3);
}
if (tag === 'code' && text.includes('```')) {
confidence = Math.min(1, confidence + 0.4);
}
// Normalize by text length (longer text = more reliable)
if (words.length < 20) {
confidence *= 0.7;
}
else if (words.length > 100) {
confidence = Math.min(1, confidence * 1.1);
}
candidates.push({
tag,
confidence: Math.round(confidence * 100) / 100,
signals
});
}
}
// Sort by confidence descending
candidates.sort((a, b) => b.confidence - a.confidence);
// If no candidates, return unknown
if (candidates.length === 0) {
candidates.push({
tag: 'unknown',
confidence: 0.5,
signals: ['no_patterns_matched']
});
}
return candidates;
}
/**
* Gets the primary intent from candidates.
*/
function getPrimaryIntent(candidates) {
if (candidates.length === 0)
return null;
const top = candidates[0];
// Only return if confidence is reasonable
if (top.confidence >= 0.3) {
return top.tag;
}
return null;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2VuZ2luZXMvY2xhc3NpZmljYXRpb24vaW50ZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7R0FRRzs7QUFrSUgsb0NBd0RDO0FBS0QsNENBVUM7QUF0TUQsbUNBQWlEO0FBRWpEOztHQUVHO0FBQ0gsTUFBTSxlQUFlLEdBSWhCO0lBQ0g7UUFDRSxHQUFHLEVBQUUsU0FBUztRQUNkLFFBQVEsRUFBRTtZQUNSLCtFQUErRTtZQUMvRSxrQ0FBa0M7U0FDbkM7UUFDRCxNQUFNLEVBQUUsR0FBRztLQUNaO0lBQ0Q7UUFDRSxHQUFHLEVBQUUsYUFBYTtRQUNsQixRQUFRLEVBQUU7WUFDUix3RUFBd0U7WUFDeEUsZ0RBQWdEO1lBQ2hELDBDQUEwQztTQUMzQztRQUNELE1BQU0sRUFBRSxHQUFHO0tBQ1o7SUFDRDtRQUNFLEdBQUcsRUFBRSxNQUFNO1FBQ1gsUUFBUSxFQUFFO1lBQ1IsZUFBZTtZQUNmLDJFQUEyRTtZQUMzRSxlQUFlO1lBQ2YsaUNBQWlDO1NBQ2xDO1FBQ0QsTUFBTSxFQUFFLEdBQUc7S0FDWjtJQUNEO1FBQ0UsR0FBRyxFQUFFLE1BQU07UUFDWCxRQUFRLEVBQUU7WUFDUixZQUFZO1lBQ1osY0FBYztZQUNkLCtDQUErQztTQUNoRDtRQUNELE1BQU0sRUFBRSxHQUFHO0tBQ1o7SUFDRDtRQUNFLEdBQUcsRUFBRSxVQUFVO1FBQ2YsUUFBUSxFQUFFO1lBQ1IsTUFBTTtZQUNOLHNFQUFzRTtTQUN2RTtRQUNELE1BQU0sRUFBRSxHQUFHO0tBQ1o7SUFDRDtRQUNFLEdBQUcsRUFBRSxhQUFhO1FBQ2xCLFFBQVEsRUFBRTtZQUNSLDZFQUE2RTtZQUM3RSw0REFBNEQ7U0FDN0Q7UUFDRCxNQUFNLEVBQUUsR0FBRztLQUNaO0lBQ0Q7UUFDRSxHQUFHLEVBQUUsVUFBVTtRQUNmLFFBQVEsRUFBRTtZQUNSLGtEQUFrRDtZQUNsRCwwQ0FBMEM7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QUM3QyxDQUFDO1lBRUQsVUFBVSxDQUFDLElBQUksQ0FBQztnQkFDZCxHQUFHO2dCQUNILFVBQVUsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHO2dCQUM5QyxPQUFPO2FBQ1IsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7SUFFRCxnQ0FBZ0M7SUFDaEMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRXZELG1DQUFtQztJQUNuQyxJQUFJLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDNUIsVUFBVSxDQUFDLElBQUksQ0FBQztZQUNkLEdBQUcsRUFBRSxTQUFTO1lBQ2QsVUFBVSxFQUFFLEdBQUc7WUFDZixPQUFPLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQztTQUNqQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsZ0JBQWdCLENBQUMsVUFBNkI7SUFDNUQsSUFBSSxVQUFVLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUV6QyxNQUFNLEdBQUcsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUIsMENBQTBDO0lBQzFDLElBQUksR0FBRyxDQUFDLFVBQVUsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUMxQixPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUM7SUFDakIsQ0FBQztJQUVELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogSW50ZW50IERldGVjdGlvbiBNb2R1bGVcbiAqIFxuICogRGV0ZWN0cyB0aGUgcHJpbWFyeSBpbnRlbnQvcHVycG9zZSBvZiBMTE0gb3V0cHV0LlxuICogXG4gKiBAbW9kdWxlIGVuZ2luZXMvY2xhc3NpZmljYXRpb24vaW50ZW50XG4gKiBAYXV0aG9yIEhhaWVjXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuXG5pbXBvcnQgeyBJbnRlbnRUYWcsIEludGVudENhbmRpZGF0ZSB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgY291bnRCdWxsZXRzLCB0b2tlbml6ZSB9IGZyb20gJy4vdXRpbHMnO1xuXG4vKipcbiAqIEludGVudCBkZXRlY3Rpb24gcGF0dGVybnMuXG4gKi9cbmNvbnN0IElOVEVOVF9QQVRURVJOUzogQXJyYXk8e1xuICB0YWc6IEludGVudFRhZztcbiAgcGF0dGVybnM6IFJlZ0V4cFtdO1xuICB3ZWlnaHQ6IG51bWJlcjtcbn0+ID0gW1xuICB7XG4gICAgdGFnOiAnc3VtbWFyeScsXG4gICAgcGF0dGVybnM6IFtcbiAgICAgIC9cXGIoaW4gc3VtbWFyeXx0byBzdW1tYXJpemV8b3ZlcmFsbHxpbiBjb25jbHVzaW9ufGtleSBwb2ludHM/fG1haW4gcG9pbnRzPylcXGIvaSxcbiAgICAgIC9cXGIodGxkcnx0bDtkcnxicmllZiBvdmVydmlldylcXGIvaVxuICAgIF0sXG4gICAgd2VpZ2h0OiAxLjBcbiAgfSxcbiAge1xuICAgIHRhZzogJ2V4cGxhbmF0aW9uJyxcbiAgICBwYXR0ZXJuczogW1xuICAgICAgL1xcYihiZWNhdXNlfHRoZXJlZm9yZXx0aGlzIG1lYW5zfGluIG90aGVyIHdvcmRzfGZvciBleGFtcGxlfHN1Y2ggYXMpXFxiL2ksXG4gICAgICAvXFxiKHRoZSByZWFzb258ZXhwbGFpbnM/fGR1ZSB0b3xhcyBhIHJlc3VsdClcXGIvaSxcbiAgICAgIC9cXGIod29ya3MgYnl8ZnVuY3Rpb25zIGJ5fG9wZXJhdGVzIGJ5KVxcYi9pXG4gICAgXSxcbiAgICB3ZWlnaHQ6IDAuOFxuICB9LFxuICB7XG4gICAgdGFnOiAnY29kZScsXG4gICAgcGF0dGVybnM6IFtcbiAgICAgIC9gYGBbXFxzXFxTXSpgYGAvLFxuICAgICAgL1xcYihmdW5jdGlvbnxjb25zdHxsZXR8dmFyfGNsYXNzfGltcG9ydHxleHBvcnR8cmV0dXJufGlmfGVsc2V8Zm9yfHdoaWxlKVxcYi8sXG4gICAgICAvW3t9XFxbXFxdKCk7XT0+LyxcbiAgICAgIC9cXGIoZGVmfGFzeW5jfGF3YWl0fHRyeXxjYXRjaClcXGIvXG4gICAgXSxcbiAgICB3ZWlnaHQ6IDEuMFxuICB9LFxuICB7XG4gICAgdGFnOiAnbGlzdCcsXG4gICAgcGF0dGVybnM6IFtcbiAgICAgIC9eWy0q4oCiXVxccysvbSxcbiAgICAgIC9eXFxkK1suKV1cXHMrL20sXG4gICAgICAvXFxiKGhlcmUgYXJlfHRoZSBmb2xsb3dpbmd8c3RlcHM/OnxpdGVtcz86KVxcYi9pXG4gICAgXSxcbiAgICB3ZWlnaHQ6IDAuOVxuICB9LFxuICB7XG4gICAgdGFnOiAncXVlc3Rpb24nLFxuICAgIHBhdHRlcm5zOiBbXG4gICAgICAvXFw/JC9tLFxuICAgICAgL1xcYih3aGF0fHdoeXxob3d8d2hlbnx3aGVyZXx3aG98d2hpY2h8d291bGQgeW91fGNvdWxkIHlvdXxjYW4geW91KVxcYi9pXG4gICAgXSxcbiAgICB3ZWlnaHQ6IDAuN1xuICB9LFxuICB7XG4gICAgdGFnOiAnaW5zdHJ1Y3Rpb24nLFxuICAgIHBhdHRlcm5zOiBbXG4gICAgICAvXFxiKHN0ZXAgXFxkfGZpcnN0LD98dGhlbiw/fG5leHQsP3xmaW5hbGx5LD98bWFrZSBzdXJlfGVuc3VyZXxyZW1lbWJlciB0bylcXGIvaSxcbiAgICAgIC9cXGIoeW91IHNob3VsZHx5b3UgbmVlZCB0b3x5b3UgbXVzdHxwbGVhc2V8ZG8gbm90fGRvbid0KVxcYi9pXG4gICAgXSxcbiAgICB3ZWlnaHQ6IDAuOFxuICB9LFxuICB7XG4gICAgdGFnOiAnY3JlYXRpdmUnLFxuICAgIHBhdHRlcm5zOiBbXG4gICAgICAvXFxiKG9uY2UgdXBvbnxpbWFnaW5lfHBpY3R1cmUgdGhpc3xpbiBhIHdvcmxkKVxcYi9pLFxuICAgICAgL1xcYihwb2VtfHN0b3J5fHRhbGV8bmFycmF0aXZlfGZpY3Rpb24pXFxiL2lcbiAgICBdLFxuICAgIHdlaWdodDogMC45XG4gIH0sXG4gIHtcbiAgICB0YWc6ICdhbmFseXNpcycsXG4gICAgcGF0dGVybnM6IFtcbiAgICAgIC9cXGIoYW5hbHlzaXN8YW5hbHl6aW5nfGV4YW1pbmV8ZXhhbWluaW5nfGV2YWx1YXRlfGV2YWx1YXRpbmcpXFxiL2ksXG4gICAgICAvXFxiKHByb3MgYW5kIGNvbnN8YWR2YW50YWdlc3xkaXNhZHZhbnRhZ2VzfHN0cmVuZ3Roc3x3ZWFrbmVzc2VzKVxcYi9pLFxuICAgICAgL1xcYihmYWN0b3JzfGNvbnNpZGVyYXRpb25zfGltcGxpY2F0aW9ucylcXGIvaVxuICAgIF0sXG4gICAgd2VpZ2h0OiAwLjhcbiAgfSxcbiAge1xuICAgIHRhZzogJ2NvbXBhcmlzb24nLFxuICAgIHBhdHRlcm5zOiBbXG4gICAgICAvXFxiKGNvbXBhcmVkIHRvfHZlcnN1c3x2c1xcLj98ZGlmZmVyfGRpZmZlcmVuY2V8c2ltaWxhcnx1bmxpa2V8d2hlcmVhcylcXGIvaSxcbiAgICAgIC9cXGIob24gdGhlIG90aGVyIGhhbmR8aW4gY29udHJhc3R8YWx0ZXJuYXRpdmVseSlcXGIvaVxuICAgIF0sXG4gICAgd2VpZ2h0OiAwLjlcbiAgfSxcbiAge1xuICAgIHRhZzogJ2RlZmluaXRpb24nLFxuICAgIHBhdHRlcm5zOiBbXG4gICAgICAvXFxiKGlzIGRlZmluZWQgYXN8cmVmZXJzIHRvfG1lYW5zfGlzIGF8YXJlIGEpXFxiL2ksXG4gICAgICAvXFxiKGRlZmluaXRpb258bWVhbmluZ3xjb25jZXB0IG9mKVxcYi9pXG4gICAgXSxcbiAgICB3ZWlnaHQ6IDAuN1xuICB9LFxuICB7XG4gICAgdGFnOiAndHJhbnNsYXRpb24nLFxuICAgIHBhdHRlcm5zOiBbXG4gICAgICAvXFxiKHRyYW5zbGF0ZXM/IHRvfGluIFthLXpdKyBsYW5ndWFnZXx0cmFuc2xhdGlvbilcXGIvaVxuICAgIF0sXG4gICAgd2VpZ2h0OiAxLjBcbiAgfSxcbiAge1xuICAgIHRhZzogJ2NvbnZlcnNhdGlvbicsXG4gICAgcGF0dGVybnM6IFtcbiAgICAgIC9cXGIoaGl8aGVsbG98aGV5fHRoYW5rc3x0aGFuayB5b3V8eW91J3JlIHdlbGNvbWV8c3VyZXxva2F5fG9rKVxcYi9pLFxuICAgICAgL1xcYihJIHRoaW5rfEkgYmVsaWV2ZXxpbiBteSBvcGluaW9ufHBlcnNvbmFsbHkpXFxiL2lcbiAgICBdLFxuICAgIHdlaWdodDogMC41XG4gIH0sXG4gIHtcbiAgICB0YWc6ICdkYXRhJyxcbiAgICBwYXR0ZXJuczogW1xuICAgICAgL1xcYihkYXRhfGRhdGFzZXR8c3RhdGlzdGljc3xudW1iZXJzfGZpZ3VyZXN8bWV0cmljcylcXGIvaSxcbiAgICAgIC9cXGQrJXxcXGQrXFwuXFxkKy8sXG4gICAgICAvXFxiKHRhYmxlfGNoYXJ0fGdyYXBoKVxcYi9pXG4gICAgXSxcbiAgICB3ZWlnaHQ6IDAuN1xuICB9XG5dO1xuXG4vKipcbiAqIERldGVjdHMgaW50ZW50IGNhbmRpZGF0ZXMgZnJvbSB0ZXh0LlxuICogXG4gKiBAcGFyYW0gdGV4dCAtIFRoZSB0ZXh0IHRvIGFuYWx5emVcbiAqIEByZXR1cm5zIEFycmF5IG9mIGludGVudCBjYW5kaWRhdGVzIHNvcnRlZCBieSBjb25maWRlbmNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RJbnRlbnQodGV4dDogc3RyaW5nKTogSW50ZW50Q2FuZGlkYXRlW10ge1xuICBjb25zdCBjYW5kaWRhdGVzOiBJbnRlbnRDYW5kaWRhdGVbXSA9IFtdO1xuICBjb25zdCB3b3JkcyA9IHRva2VuaXplKHRleHQpO1xuICBjb25zdCBidWxsZXRzID0gY291bnRCdWxsZXRzKHRleHQpO1xuICBcbiAgZm9yIChjb25zdCB7IHRhZywgcGF0dGVybnMsIHdlaWdodCB9IG9mIElOVEVOVF9QQVRURVJOUykge1xuICAgIGxldCBtYXRjaENvdW50ID0gMDtcbiAgICBjb25zdCBzaWduYWxzOiBzdHJpbmdbXSA9IFtdO1xuICAgIFxuICAgIGZvciAoY29uc3QgcGF0dGVybiBvZiBwYXR0ZXJucykge1xuICAgICAgaWYgKHBhdHRlcm4udGVzdCh0ZXh0KSkge1xuICAgICAgICBtYXRjaENvdW50Kys7XG4gICAgICAgIHNpZ25hbHMucHVzaChwYXR0ZXJuLnNvdXJjZS5zdWJzdHJpbmcoMCwgMzApKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgaWYgKG1hdGNoQ291bnQgPiAwKSB7XG4gICAgICAvLyBDYWxjdWxhdGUgY29uZmlkZW5jZSBiYXNlZCBvbiBtYXRjaGVzIGFuZCB0ZXh0IGNoYXJhY3RlcmlzdGljc1xuICAgICAgbGV0IGNvbmZpZGVuY2UgPSAobWF0Y2hDb3VudCAvIHBhdHRlcm5zLmxlbmd0aCkgKiB3ZWlnaHQ7XG4gICAgICBcbiAgICAgIC8vIEJvb3N0IGZvciBzdHJ1Y3R1cmFsIG1hdGNoZXNcbiAgICAgIGlmICh0YWcgPT09ICdsaXN0JyAmJiBidWxsZXRzID49IDMpIHtcbiAgICAgICAgY29uZmlkZW5jZSA9IE1hdGgubWluKDEsIGNvbmZpZGVuY2UgKyAwLjMpO1xuICAgICAgfVxuICAgICAgaWYgKHRhZyA9PT0gJ2NvZGUnICYmIHRleHQuaW5jbHVkZXMoJ2BgYCcpKSB7XG4gICAgICAgIGNvbmZpZGVuY2UgPSBNYXRoLm1pbigxLCBjb25maWRlbmNlICsgMC40KTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gTm9ybWFsaXplIGJ5IHRleHQgbGVuZ3RoIChsb25nZXIgdGV4dCA9IG1vcmUgcmVsaWFibGUpXG4gICAgICBpZiAod29yZHMubGVuZ3RoIDwgMjApIHtcbiAgICAgICAgY29uZmlkZW5jZSAqPSAwLjc7XG4gICAgICB9IGVsc2UgaWYgKHdvcmRzLmxlbmd0aCA+IDEwMCkge1xuICAgICAgICBjb25maWRlbmNlID0gTWF0aC5taW4oMSwgY29uZmlkZW5jZSAqIDEuMSk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGNhbmRpZGF0ZXMucHVzaCh7XG4gICAgICAgIHRhZyxcbiAgICAgICAgY29uZmlkZW5jZTogTWF0aC5yb3VuZChjb25maWRlbmNlICogMTAwKSAvIDEwMCxcbiAgICAgICAgc2lnbmFsc1xuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIFxuICAvLyBTb3J0IGJ5IGNvbmZpZGVuY2UgZGVzY2VuZGluZ1xuICBjYW5kaWRhdGVzLnNvcnQoKGEsIGIpID0+IGIuY29uZmlkZW5jZSAtIGEuY29uZmlkZW5jZSk7XG4gIFxuICAvLyBJZiBubyBjYW5kaWRhdGVzLCByZXR1cm4gdW5rbm93blxuICBpZiAoY2FuZGlkYXRlcy5sZW5ndGggPT09IDApIHtcbiAgICBjYW5kaWRhdGVzLnB1c2goe1xuICAgICAgdGFnOiAndW5rbm93bicsXG4gICAgICBjb25maWRlbmNlOiAwLjUsXG4gICAgICBzaWduYWxzOiBbJ25vX3BhdHRlcm5zX21hdGNoZWQnXVxuICAgIH0pO1xuICB9XG4gIFxuICByZXR1cm4gY2FuZGlkYXRlcztcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBwcmltYXJ5IGludGVudCBmcm9tIGNhbmRpZGF0ZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQcmltYXJ5SW50ZW50KGNhbmRpZGF0ZXM6IEludGVudENhbmRpZGF0ZVtdKTogSW50ZW50VGFnIHwgbnVsbCB7XG4gIGlmIChjYW5kaWRhdGVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gIFxuICBjb25zdCB0b3AgPSBjYW5kaWRhdGVzWzBdO1xuICAvLyBPbmx5IHJldHVybiBpZiBjb25maWRlbmNlIGlzIHJlYXNvbmFibGVcbiAgaWYgKHRvcC5jb25maWRlbmNlID49IDAuMykge1xuICAgIHJldHVybiB0b3AudGFnO1xuICB9XG4gIFxuICByZXR1cm4gbnVsbDtcbn1cbiJdfQ==