UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio

122 lines 4.88 kB
/** * WordObfuscator — inserts zero-width characters into sensitive words so * that naive string-matching by upstream APIs cannot detect them. * * For example, "proxy" becomes "p\u200Broxy" (ZWS after the first character), * making the text visually identical to humans but different at the byte level. */ /** Unicode zero-width space (U+200B). */ const ZWS = "\u200B"; /** * Insert a zero-width space after the first character. * This defeats simple substring matching while preserving readability. */ function obfuscateWord(word) { if (word.length <= 1) { return word; } return word.charAt(0) + ZWS + word.slice(1); } function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Replace all case-insensitive occurrences of each sensitive word in `text` * with the obfuscated version, preserving original casing. * * Words are sorted longest-first so that longer matches take priority over * shorter substrings (e.g., "load balancer" matches before "load"). */ function obfuscateText(text, sortedWords) { let result = text; for (const word of sortedWords) { const pattern = new RegExp(escapeRegExp(word), "gi"); result = result.replace(pattern, (match) => obfuscateWord(match)); } return result; } /** Default sensitive words that might reveal proxy usage. */ const DEFAULT_SENSITIVE_WORDS = [ "proxy", "neurolink", "load balancer", "round-robin", "failover", "multi-account", ]; export function createWordObfuscator(customWords) { const words = customWords ?? [...DEFAULT_SENSITIVE_WORDS]; // Sort longest-first so longer matches take priority const sorted = [...words].sort((a, b) => b.length - a.length); return { name: "word-obfuscator", order: 40, enabled: true, async transformRequest(ctx) { const messages = ctx.request.body.messages.map((msg) => { if (typeof msg.content === "string") { return { ...msg, content: obfuscateText(msg.content, sorted) }; } if (Array.isArray(msg.content)) { const obfuscatedContent = msg.content.map((block) => { if (block.type === "text" && typeof block.text === "string") { return { ...block, text: obfuscateText(block.text, sorted), }; } // Obfuscate tool_result content (string or nested blocks) if (block.type === "tool_result") { if (typeof block.content === "string") { return { ...block, content: obfuscateText(block.content, sorted), }; } if (Array.isArray(block.content)) { const obfuscatedBlocks = block.content.map((inner) => { if (inner.type === "text" && typeof inner.text === "string") { return { ...inner, text: obfuscateText(inner.text, sorted), }; } return inner; }); return { ...block, content: obfuscatedBlocks }; } } return block; }); return { ...msg, content: obfuscatedContent }; } return msg; }); // Also obfuscate system prompt if present let system = ctx.request.body.system; if (typeof system === "string") { system = obfuscateText(system, sorted); } else if (Array.isArray(system)) { system = system.map((block) => { if (block.type === "text" && typeof block.text === "string") { return { ...block, text: obfuscateText(block.text, sorted) }; } return block; }); } return { ...ctx, request: { ...ctx.request, body: { ...ctx.request.body, messages, ...(system !== undefined ? { system } : {}), }, }, }; }, }; } //# sourceMappingURL=wordObfuscator.js.map