UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

105 lines • 4.59 kB
"use strict"; /** * linearText — trims that cost one pass, where the regex they replace costs a * pass PER STARTING POSITION. * * Pattern: leaf utility (imports nothing). * Role: asked wherever a run of characters is trimmed from text the library * did not write — base URLs and prefixes from configuration, tokens * and replies from a model, words from a person. It lives here so * those doors share one implementation and one test. * Emits: N/A. * * ── Why these exist ───────────────────────────────────────────────────────── * `s.replace(/\/+$/, '')` reads as "drop the trailing slashes", but a * backtracking engine runs it as "at every position, take the slashes that * start there and see whether the string ends after them". On `'/' * n + 'x'` * that is n attempts of up to n steps each: 16,000 slashes take ~90 ms in V8, * a million take minutes, and the event loop is blocked the whole time. Any * `X+$` (or `[set]+$`) without a `^` has that shape. These functions walk in * from the end once instead — the work is the length of the run they remove, * plus one. * * ── The one rule ──────────────────────────────────────────────────────────── * Each function returns EXACTLY what the regex in its comment returns, for * every input; only the cost differs. The equivalence and the work bound are * both pinned by `test/security/linear-text.test.ts`. * * ```ts * import { isSlash, trimTrailing } from '../lib/linearText.js'; * * trimTrailing('https://api.example.com///', isSlash); // 'https://api.example.com' * ``` */ Object.defineProperty(exports, "__esModule", { value: true }); exports.trimBoth = exports.trimTrailing = exports.trimLeading = exports.either = exports.anyOf = exports.isLineBreak = exports.isRegExpWhitespace = exports.isHyphen = exports.isSlash = void 0; /** `/` — base URLs, object-key prefixes and paths. */ const isSlash = (code) => code === 0x2f; exports.isSlash = isSlash; /** `-` — slugs. */ const isHyphen = (code) => code === 0x2d; exports.isHyphen = isHyphen; /** * Exactly the code units `\s` matches in a JavaScript regular expression: * WhiteSpace (tab, vertical tab, form feed, space, no-break space, the * byte-order mark and every Unicode `Zs` space) plus LineTerminator (LF, CR, * U+2028, U+2029). */ const isRegExpWhitespace = (code) => { if (code <= 0x20) return code === 0x20 || (code >= 0x09 && code <= 0x0d); if (code < 0xa0) return false; return (code === 0xa0 || code === 0x1680 || (code >= 0x2000 && code <= 0x200a) || code === 0x2028 || code === 0x2029 || code === 0x202f || code === 0x205f || code === 0x3000 || code === 0xfeff); }; exports.isRegExpWhitespace = isRegExpWhitespace; /** * What a regex `.` does not match — and where `^` and `$` see a line end under * the `m` flag: LF, CR, U+2028, U+2029. A scanner that stands in for a regex * reads lines by this, never by `\n` alone. */ const isLineBreak = (code) => code === 0x0a || code === 0x0d || code === 0x2028 || code === 0x2029; exports.isLineBreak = isLineBreak; /** A test for any one of `chars` — a regex character class with no ranges. */ function anyOf(chars) { const codes = new Set(); for (let i = 0; i < chars.length; i++) codes.add(chars.charCodeAt(i)); return (code) => codes.has(code); } exports.anyOf = anyOf; /** Either test — `[ab]` built from `a` and `b`. */ function either(a, b) { return (code) => a(code) || b(code); } exports.either = either; /** `s.replace(/^[run]+/, '')`, walking forward once. */ function trimLeading(s, drop) { let start = 0; while (start < s.length && drop(s.charCodeAt(start))) start++; return start === 0 ? s : s.slice(start); } exports.trimLeading = trimLeading; /** `s.replace(/[run]+$/, '')`, walking back from the end once. */ function trimTrailing(s, drop) { let end = s.length; while (end > 0 && drop(s.charCodeAt(end - 1))) end--; return end === s.length ? s : s.slice(0, end); } exports.trimTrailing = trimTrailing; /** `s.replace(/^[run]+|[run]+$/g, '')` — both ends, each walked once. */ function trimBoth(s, drop) { return trimTrailing(trimLeading(s, drop), drop); } exports.trimBoth = trimBoth; //# sourceMappingURL=linearText.js.map