UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

141 lines (140 loc) • 5.04 kB
/** * Buffer → string decoding with encoding detection (#362). * * Order of resolution: * 1. Explicit override (any iconv-lite label). * 2. Deterministic BOM sniff (UTF-8 / UTF-16 LE / UTF-16 BE). * 3. `chardet` statistical detection, mapped to an iconv-lite label. * 4. Fallback to UTF-8 (preserves the historical hard-coded default). * * Decoding always goes through `iconv-lite`, and any residual BOM is stripped * from the decoded string so it can't glue onto the first token. */ import chardet from "chardet"; import iconv from "iconv-lite"; import { logger } from "./logger.js"; /** Strip a leading BOM (U+FEFF) from an already-decoded string. */ export function stripBomString(text) { return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text; } /** Deterministic BOM detection from the raw bytes. Returns null when absent. */ function sniffBom(buffer) { if (buffer.length >= 3 && buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) { return "utf-8"; } if (buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe) { return "utf-16le"; } if (buffer.length >= 2 && buffer[0] === 0xfe && buffer[1] === 0xff) { return "utf-16be"; } return null; } /** * Map a chardet label to an iconv-lite-supported label. Returns null when the * label is unknown/unsupported so the caller falls back to UTF-8. */ function toIconvLabel(detected) { if (!detected) { return null; } const normalized = detected.toLowerCase().replace(/[^a-z0-9]/g, ""); const map = { utf8: "utf-8", utf16le: "utf-16le", utf16be: "utf-16be", ascii: "utf-8", // ASCII is a strict UTF-8 subset windows1252: "windows-1252", iso88591: "latin1", latin1: "latin1", iso88592: "iso-8859-2", windows1251: "windows-1251", koi8r: "koi8-r", gb18030: "gb18030", big5: "big5", shiftjis: "shift_jis", euckr: "euc-kr", eucjp: "euc-jp", }; const label = map[normalized] ?? detected; return iconv.encodingExists(label) ? label : null; } /** * Decode a buffer to text, detecting the encoding unless overridden. * * @param isCompleteBuffer - Whether `buffer` is the entire source (default * `true`). Pass `false` when `buffer` is only a peeked prefix (e.g. a * streaming head-sniff) — the ASCII fast path still commits to "utf-8" for * the peeked bytes (unchanged behavior), but reports a lower confidence * since later bytes not yet seen could still be non-ASCII (#1199). */ export function decodeBuffer(buffer, override, isCompleteBuffer = true) { // 1. Explicit override wins outright. if (override && iconv.encodingExists(override)) { return { text: stripBomString(iconv.decode(buffer, override)), encoding: override, confidence: 100, }; } if (override && !iconv.encodingExists(override)) { logger.warn(`[textEncoding] Unsupported encoding override "${override}"; falling back to detection.`); } // 2. BOM is authoritative when present. const bom = sniffBom(buffer); if (bom) { return { text: stripBomString(iconv.decode(buffer, bom)), encoding: bom, confidence: 100, }; } // 2b. Pure-ASCII fast path — chardet often reports ASCII as ISO-8859-1, but // ASCII is a strict UTF-8 subset and decodes identically, so report "utf-8" // to preserve the historical default for plain-ASCII files. let ascii = true; for (let i = 0; i < buffer.length; i++) { if (buffer[i] >= 0x80) { ascii = false; break; } } if (ascii) { return { text: stripBomString(iconv.decode(buffer, "utf-8")), encoding: "utf-8", // A partial peek being pure-ASCII only proves the peeked prefix is // ASCII, not the whole file — a later chunk could still switch to a // legacy encoding. Only report full certainty when `buffer` is known // to be the complete source. confidence: isCompleteBuffer ? 100 : 60, }; } // 3. Statistical detection. let detected = null; try { detected = chardet.detect(buffer); } catch (error) { logger.debug(`[textEncoding] chardet failed: ${String(error)}`); } const label = toIconvLabel(detected); if (label) { return { text: stripBomString(iconv.decode(buffer, label)), encoding: label, // chardet gives a winner but not a numeric score via detect(); treat a // confident non-UTF-8 hit as reasonably (not fully) certain. confidence: label === "utf-8" ? 100 : 80, }; } // 4. Fallback: historical UTF-8 default. return { text: stripBomString(iconv.decode(buffer, "utf-8")), encoding: "utf-8", confidence: 0, }; }