@ai-matrx/content-ir 0.22.6 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/convert.cjs +36 -292
- package/dist/convert.cjs.map +1 -1
- package/dist/convert.js +35 -291
- package/dist/convert.js.map +1 -1
- package/dist/core.cjs +3 -290
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +2 -289
- package/dist/core.js.map +1 -1
- package/dist/directives.cjs +3 -37
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.js +2 -36
- package/dist/directives.js.map +1 -1
- package/dist/index.cjs +235 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +227 -310
- package/dist/index.js.map +1 -1
- package/dist/json-extract.cjs +942 -0
- package/dist/json-extract.cjs.map +1 -0
- package/dist/json-extract.d.cts +176 -0
- package/dist/json-extract.d.ts +176 -0
- package/dist/json-extract.js +928 -0
- package/dist/json-extract.js.map +1 -0
- package/dist/source.cjs +199 -0
- package/dist/source.cjs.map +1 -1
- package/dist/source.d.cts +138 -1
- package/dist/source.d.ts +138 -1
- package/dist/source.js +193 -1
- package/dist/source.js.map +1 -1
- package/dist/surfaces.cjs +4 -40
- package/dist/surfaces.cjs.map +1 -1
- package/dist/surfaces.js +2 -38
- package/dist/surfaces.js.map +1 -1
- package/package.json +28 -7
- package/dist/text-case.cjs +0 -333
- package/dist/text-case.cjs.map +0 -1
- package/dist/text-case.d.cts +0 -87
- package/dist/text-case.d.ts +0 -87
- package/dist/text-case.js +0 -320
- package/dist/text-case.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../source/fence-nesting.ts","../source/code-ranges.ts","../json-extract/json-structural.ts","../json-extract/extract-json.ts","../json-extract/streaming-json-tracker.ts"],"names":["raw"],"mappings":"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","file":"json-extract.js","sourcesContent":["// ─────────────────────────────────────────────────────────────────────────\n// THE ONE NESTED-FENCE RULE for a ```markdown / ```md / ```mdx fence.\n//\n// Source of truth (moved here from matrx-frontend\n// components/markdown-core/fence-nesting.ts, 2026-09-25). Consumers: the\n// source tokenizer (source/tokenize.ts), matrx-frontend's static splitter and\n// live StreamBlockAccumulator, and — by conformance, since Python cannot\n// import this — aidream matrx-ai `processing/blocks/fence_nesting.py`, which\n// runs the SAME generated vectors (`__tests__/fence-nesting-vectors.json`,\n// byte-identical copy at packages/matrx-ai/tests/fixtures/).\n//\n// Models write a markdown document inside a ```markdown fence and put their\n// own ```python … ``` blocks inside it with the SAME three backticks. Under\n// strict CommonMark the first inner bare ``` closes the outer fence: the\n// document ends mid-way, the rest leaks out as prose, and the outer closing\n// ``` opens a phantom code block that swallows everything after it.\n//\n// The rule, for MARKDOWN-language fences only (every other language keeps\n// strict CommonMark — a ```bash heredoc is code, not a document):\n// - a fence line WITH an info string (```python) opens a nested fence;\n// - a bare fence line (``` with at least the opener's tick count) closes\n// the innermost nested fence while one is open, and closes the outer\n// fence only when none is;\n// - a longer outer fence (````markdown) keeps working exactly as before —\n// an inner ``` is shorter than the opener, so it is plain content;\n// - if the text ENDS with a nested fence still open, the extraction is\n// redone under strict CommonMark (an unclosed inner fence must not eat\n// the outer closer and the rest of the message).\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Fence languages whose body is itself a markdown document. */\nexport const NESTING_FENCE_LANGUAGES: ReadonlySet<string> = new Set([\n \"markdown\",\n \"md\",\n \"mdx\",\n]);\n\n/** True when a fence opened with this info-string language nests inner fences. */\nexport function fenceNestsInnerFences(language: string | undefined | null): boolean {\n return !!language && NESTING_FENCE_LANGUAGES.has(language.toLowerCase());\n}\n\nexport type InnerFenceLine =\n /** Not a fence line — ordinary content of the outer fence. */\n | \"content\"\n /** ```lang inside a markdown fence — content, and one level deeper. */\n | \"open-nested\"\n /** Bare ``` that closes the innermost nested fence — content, one level up. */\n | \"close-nested\"\n /** Bare ``` that closes the OUTER fence. */\n | \"close-outer\";\n\n/**\n * Classify one line inside an open backtick fence, already trimmed with\n * {@link trimFenceLine} (never a language's own `trim()`).\n *\n * @param trimmed the line with surrounding whitespace removed\n * @param openTicks backtick count of the outer fence's opener\n * @param nests whether the outer fence follows the nesting rule\n * @param nestedDepth how many nested fences are open right now\n */\n/**\n * The whitespace a fence line may carry around its backticks and info string:\n * CommonMark's ASCII whitespace — space, tab, LF, CR, form feed, vertical tab.\n * Defined HERE, not by a language's `trim()`: JavaScript's `trim()` also strips\n * U+FEFF, U+00A0 and the Unicode spaces, while Python's `strip()` also strips\n * U+0085 and U+001C–U+001F — which made the two twins disagree on lines such\n * as ```` ```\\uFEFF ```` (verify-RC-B3 residual R4). Every caller trims a line\n * with `trimFenceLine` before classifying it; the Python twin mirrors both.\n */\nexport const FENCE_WHITESPACE = \" \\t\\n\\r\\f\\v\";\n\nfunction isFenceWhitespace(ch: string | undefined): boolean {\n return ch !== undefined && ch !== \"\" && FENCE_WHITESPACE.includes(ch);\n}\n\n/** Strip {@link FENCE_WHITESPACE} (and nothing else) from both ends of a line. */\nexport function trimFenceLine(line: string): string {\n let start = 0;\n let end = line.length;\n while (start < end && isFenceWhitespace(line[start])) start++;\n while (end > start && isFenceWhitespace(line[end - 1])) end--;\n return start === 0 && end === line.length ? line : line.slice(start, end);\n}\n\n/**\n * The whitespace around a fence OPENER and inside its info string. The\n * renderer finds openers with JavaScript's `String#trim()` and splits the info\n * string on `/\\s/`; this set IS that definition, written out so the Python\n * twin can match it exactly — ECMAScript WhiteSpace + LineTerminator. It\n * differs from Python's `str.split()` on U+0085 and U+001C–U+001F (not JS\n * whitespace) and U+FEFF (JS whitespace) — verify-RC-B3 residual R4′.\n */\nexport const FENCE_OPENER_WHITESPACE =\n \"\\t\\n\\v\\f\\r \\u00a0\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff\";\n\nfunction isOpenerWhitespace(ch: string | undefined): boolean {\n return ch !== undefined && ch !== \"\" && FENCE_OPENER_WHITESPACE.includes(ch);\n}\n\n/**\n * Parse a backtick fence OPENER line the way the renderer does: trim the line,\n * count the backtick run (3+), trim the rest, and take the first\n * whitespace-separated word as the language. null when the line opens nothing —\n * including when the info string holds a backtick (GFM / CommonMark 4.5:\n * \"```` code ````\" and \"``` `x` | b\" are code spans, never fences).\n */\nexport function parseFenceOpener(line: string): { ticks: number; lang: string } | null {\n let start = 0;\n let end = line.length;\n while (start < end && isOpenerWhitespace(line[start])) start++;\n while (end > start && isOpenerWhitespace(line[end - 1])) end--;\n let ticks = 0;\n while (start + ticks < end && line[start + ticks] === \"`\") ticks++;\n if (ticks < 3) return null;\n if (line.slice(start + ticks, end).includes(\"`\")) return null;\n let infoStart = start + ticks;\n while (infoStart < end && isOpenerWhitespace(line[infoStart])) infoStart++;\n let langEnd = infoStart;\n while (langEnd < end && !isOpenerWhitespace(line[langEnd])) langEnd++;\n return { ticks, lang: line.slice(infoStart, langEnd) };\n}\n\nexport function classifyInnerFenceLine(\n trimmed: string,\n openTicks: number,\n nests: boolean,\n nestedDepth: number,\n): InnerFenceLine {\n let ticks = 0;\n while (ticks < trimmed.length && trimmed[ticks] === \"`\") ticks++;\n if (ticks < 3) return \"content\";\n const info = trimFenceLine(trimmed.slice(ticks));\n if (info === \"\") {\n if (ticks < openTicks) return \"content\";\n if (nests && nestedDepth > 0) return \"close-nested\";\n return \"close-outer\";\n }\n // A fence line with an info string never closes anything (CommonMark).\n // Inside a markdown fence it opens a nested one — unless the outer opener is\n // LONGER, in which case CommonMark already treats the inner fence as content\n // and its bare closer can never reach the outer fence.\n if (nests && ticks >= openTicks && !info.includes(\"`\")) return \"open-nested\";\n return \"content\";\n}\n","/**\n * THE ONE CODE-RANGE RULE — where code is in markdown source, for every surface.\n *\n * Ruling (RC-B10, 2026-09-25, REGISTER rulings ledger): the rule is the\n * RENDERER's rule — what the chat renderer's splitter, the source tokenizer\n * and the Python block detector already agree on — made container-aware only\n * where the renderer hands a block to remark:\n * - a BACKTICK fence opens on a line whose whitespace-trimmed text starts\n * with ``` at ANY indent (so a fence inside a list item opens at any\n * depth), after stripping blockquote `>` prefixes;\n * - a TILDE fence opens at ≤ 3 spaces relative to its container (a list\n * item's content column, inside any `>` prefixes);\n * - a backtick fence closes by THE nested-fence rule (`fence-nesting.ts`,\n * with the strict-CommonMark retry when a nested fence is left open) or by\n * the renderer's line-end closer (`code```` with nothing after it); inside\n * a ```json fence a backtick run inside a JSON string is text;\n * - a fence inside a blockquote ends where the blockquote ends;\n * - strict CommonMark's \"4+ spaces is not a fence\" is rejected on purpose:\n * users see what the renderer's splitter draws.\n * Inline code spans pair equal-length backtick runs inside one paragraph.\n *\n * Order is the renderer's: phase 1 is the splitter — every raw line whose\n * trimmed text starts with ``` opens a block, before remark sees anything\n * (so `- ```` can never close on a later raw ``` line; that line opens a\n * splitter block instead). Phase 2 is remark inside each prose segment the\n * splitter left: blockquote fences, fences on a list-marker line, tilde\n * fences, and code spans — none can run past its segment. A ``` line inside a\n * tilde fence is therefore drawn as code up to ITS closer (remark's reading\n * here in `findCodeRanges`); the tokenizer's tilde island ends at its closer.\n *\n * Consumers: `findCodeRanges` (math pairing, kit's delimiter guard, chat's\n * speakable text, print, every matrx-frontend walker), and the line-level\n * primitives `fenceOpenerOf` / `closeFence`, which the tokenizer and the\n * renderer's splitters drive line by line. A private copy of fence or\n * code-span detection anywhere fails `__tests__/one-code-range-rule.test.ts`.\n */\nimport { classifyInnerFenceLine, fenceNestsInnerFences, parseFenceOpener, trimFenceLine } from \"./fence-nesting\";\n\nexport interface CodeRange {\n /** UTF-16 offset of the first character (the fence line start, or the opening backtick run). */\n start: number;\n /** Offset just past the closing fence line's content / closing backtick run (the fence's last line when unclosed). */\n end: number;\n kind: \"fence\" | \"span\";\n}\n\nexport interface FenceOpener {\n char: \"`\" | \"~\";\n /** Length of the opening run. */\n ticks: number;\n /** The info string's first word (\"\" when none). */\n lang: string;\n}\n\n/**\n * THE opener rule for one line's content (container prefixes already\n * removed; for a tilde fence, `content` starts at the container's column).\n */\nexport function fenceOpenerOf(content: string): FenceOpener | null {\n const t = content.trimStart();\n if (t.startsWith(\"```\")) {\n // THE opener parse: a backtick in the info string opens nothing (CommonMark 4.5).\n const parsed = parseFenceOpener(t);\n if (!parsed) return null;\n return { char: \"`\", ticks: parsed.ticks, lang: parsed.lang };\n }\n if (content.length - t.length <= 3 && t.startsWith(\"~~~\")) {\n const open = /^(~{3,})(.*)$/.exec(t);\n if (!open) return null;\n return { char: \"~\", ticks: (open[1] as string).length, lang: (open[2] as string).trim().split(/\\s/)[0] ?? \"\" };\n }\n return null;\n}\n\n/**\n * Does this line START a fenced code block? THE opener rule (`fenceOpenerOf`),\n * which follows CommonMark 4.5: a `~~~` run, or a backtick run whose info string\n * holds no backtick. Kept as a named predicate for block-boundary readers (a\n * table's end, source/gfm-table.ts).\n */\nexport function opensStrictFence(line: string): boolean {\n return fenceOpenerOf(line) !== null;\n}\n\n/** The lines a fence is read from. */\nexport interface FenceLines {\n count: number;\n /** Line `k`'s content (no terminator), or null when the fence's container has ended before it. */\n line(k: number): string | null;\n /** Streaming: line `k` has not ended yet, so it closes nothing. */\n openTail?(k: number): boolean;\n /**\n * Streaming: more lines may still arrive. The strict-CommonMark retry\n * applies only while the nested reading ends inside a nested fence — a\n * later line can close that nested fence, so a retry's closer is\n * undecided and the fence stays open (verify-RC-B3 F3).\n */\n streaming?: boolean;\n}\n\nexport interface FenceEnd {\n /** The closing line when `closed`; otherwise the fence's last line (text end, or the line before its container ended). */\n line: number;\n closed: boolean;\n}\n\n/**\n * THE closer rule, read line by line — the one implementation behind\n * `closeFence` and every streaming walker. Feed each following line\n * (container prefixes removed); `feed` returns true on the line that closes\n * the fence. A backtick fence closes by the nested-fence rule or the\n * renderer's line-end closer (`code````), and inside ```json a backtick run in\n * a JSON string is text; a tilde fence closes on `~~~` (≥ its length, ≤ 3\n * spaces). `nesting: false` forces strict CommonMark (the retry `closeFence`\n * makes when a nested fence is left open at the end; a streaming reader\n * cannot look ahead, so it reads with nesting and never retries).\n */\nconst LINE_START = { inString: false, escaped: false } as const;\n\nexport class FenceReader {\n readonly opener: FenceOpener;\n private depth = 0;\n /** A nested fence was opened at some point. */\n sawNested = false;\n private readonly isJson: boolean;\n private readonly nesting: boolean;\n private readonly tildeCloser: RegExp | null;\n\n constructor(\n opener: FenceOpener,\n options: { nesting?: boolean } = {},\n ) {\n this.opener = opener;\n this.isJson = opener.char === \"`\" && opener.lang === \"json\";\n this.nesting = opener.char === \"`\" && (options.nesting ?? fenceNestsInnerFences(opener.lang));\n this.tildeCloser = opener.char === \"~\" ? new RegExp(`^ {0,3}~{${opener.ticks},}[ \\\\t]*$`) : null;\n }\n\n /** How many nested fences are open right now. */\n get nestedDepth(): number {\n return this.depth;\n }\n\n feed(line: string): boolean {\n if (this.tildeCloser) return this.tildeCloser.test(line);\n const trimmedLine = trimFenceLine(line);\n const at = line.indexOf(\"```\");\n if (at === -1) return false;\n // Inside ```json a backtick run in a JSON string is text. The string state\n // is read per line: a JSON string never holds a raw newline, so a line that\n // ends inside one (`{\\\"__kind\\\":…}`, a cut value) ends it — carrying it on\n // swallowed the closer and everything after (never-raw R11 H2).\n if (this.isJson && jsonStringState(line, 0, at, LINE_START).inString) return false;\n if (trimmedLine.startsWith(\"```\")) {\n const kind = classifyInnerFenceLine(trimmedLine, this.opener.ticks, this.nesting, this.depth);\n if (kind === \"close-outer\") return true;\n if (kind === \"open-nested\") {\n this.depth++;\n this.sawNested = true;\n }\n if (kind === \"close-nested\") this.depth--;\n } else {\n // The renderer's line-end closer: `code```` with nothing after the run.\n const closeTicks = backtickRunLength(line, at);\n const after = trimFenceLine(line.slice(at + closeTicks));\n if (closeTicks >= this.opener.ticks && after === \"\" && this.depth === 0) return true;\n }\n return false;\n }\n}\n\n/** Where the fence opened on line `open` ends. */\nexport function closeFence(src: FenceLines, open: number, opener: FenceOpener): FenceEnd {\n const first = readFence(src, open, new FenceReader(opener));\n if (first.closed || !first.reader.sawNested || first.reader.nestedDepth <= 0) return { line: first.line, closed: first.closed };\n if (src.streaming) return { line: first.line, closed: false };\n const strict = readFence(src, open, new FenceReader(opener, { nesting: false }));\n return { line: strict.line, closed: strict.closed };\n}\n\nfunction readFence(src: FenceLines, open: number, reader: FenceReader): FenceEnd & { reader: FenceReader } {\n for (let k = open + 1; k < src.count; k++) {\n // Streaming: a bare ``` on the unfinished last line may still grow into ```bash.\n if (src.openTail?.(k)) continue;\n const line = src.line(k);\n if (line === null) return { line: k - 1, closed: false, reader };\n if (reader.feed(line)) return { line: k, closed: true, reader };\n }\n return { line: src.count - 1, closed: false, reader };\n}\n\n/** JSON-string state after scanning `line[from, upTo)` from the given state. */\nexport function jsonStringState(\n line: string,\n from: number,\n upTo: number,\n state: { inString: boolean; escaped: boolean },\n): { inString: boolean; escaped: boolean } {\n let { inString, escaped } = state;\n for (let idx = from; idx < upTo; idx++) {\n const ch = line[idx];\n if (escaped) {\n escaped = false;\n continue;\n }\n if (ch === \"\\\\\" && inString) {\n escaped = true;\n continue;\n }\n if (ch === '\"') inString = !inString;\n }\n return { inString, escaped };\n}\n\nexport function backtickRunLength(str: string, pos: number): number {\n let n = 0;\n while (pos + n < str.length && str[pos + n] === \"`\") n++;\n return n;\n}\n\n// ── the whole-text scan ────────────────────────────────────────────────────\n\n/** Blockquote prefix: how many `>` markers open the line, and where its content starts. */\nfunction quotePrefix(line: string): { depth: number; offset: number } {\n let depth = 0;\n let offset = 0;\n for (;;) {\n const m = /^ {0,3}> ?/.exec(line.slice(offset));\n if (!m) return { depth, offset };\n depth++;\n offset += m[0].length;\n }\n}\n\n/** Strip exactly `depth` blockquote markers; null when the line has fewer (the blockquote ended). */\nfunction stripQuotes(line: string, depth: number): string | null {\n let offset = 0;\n for (let d = 0; d < depth; d++) {\n const m = /^ {0,3}> ?/.exec(line.slice(offset));\n if (!m) return null;\n offset += m[0].length;\n }\n return line.slice(offset);\n}\n\nconst LIST_ITEM = /^( *)([-*+]|\\d{1,9}[.)])( +|\\t|$)/;\n\nfunction leadingSpaces(s: string): number {\n let i = 0;\n while (i < s.length && s[i] === \" \") i++;\n return i;\n}\n\ninterface Scan {\n ranges: CodeRange[];\n /** Every fence as lines: [opener line, last line, closed]. */\n fences: Array<[number, number, boolean]>;\n /** Paragraph runs outside fences, [start, end), for code-span pairing. */\n paragraphs: Array<[number, number]>;\n /** Text ends inside an open fence. */\n endsInFence: boolean;\n /** Start of the final, still-growing paragraph (streaming rule), -1 if none. */\n pendingPara: number;\n}\n\nfunction scan(text: string): Scan {\n const starts: number[] = [];\n const ends: number[] = [];\n for (let pos = 0; ; ) {\n const nl = text.indexOf(\"\\n\", pos);\n const lineEnd = nl === -1 ? text.length : nl;\n starts.push(pos);\n ends.push(lineEnd > pos && text.charCodeAt(lineEnd - 1) === 13 ? lineEnd - 1 : lineEnd);\n if (nl === -1) break;\n pos = nl + 1;\n }\n const count = starts.length;\n const raw = (k: number) => text.slice(starts[k] as number, ends[k] as number);\n const out: Scan = { ranges: [], fences: [], paragraphs: [], endsInFence: false, pendingPara: -1 };\n\n // Phase 1 — the renderer's splitter: every line whose trimmed text starts\n // with ``` opens a code block at ANY indent, before remark sees anything.\n const rawLines: FenceLines = { count, line: raw };\n let segment = 0;\n for (let k = 0; k < count; k++) {\n const opener = fenceOpenerOf(raw(k));\n if (!opener || opener.char !== \"`\") continue;\n prose(text, starts, ends, raw, segment, k, out);\n const end = closeFence(rawLines, k, opener);\n out.ranges.push({ start: starts[k] as number, end: ends[end.line] as number, kind: \"fence\" });\n out.fences.push([k, end.line, end.closed]);\n out.pendingPara = -1;\n if (!end.closed && end.line === count - 1) out.endsInFence = true;\n k = end.line;\n segment = k + 1;\n }\n prose(text, starts, ends, raw, segment, count, out);\n return out;\n}\n\n/**\n * Phase 2 — remark, inside one prose segment [from, to) the splitter left:\n * fences in blockquotes, on a list-marker line, and tilde fences (relative to\n * their container), plus the paragraphs whose backtick runs pair as spans. A\n * fence here can never run past its segment: the splitter's block begins there.\n */\nfunction prose(\n text: string,\n starts: number[],\n ends: number[],\n raw: (k: number) => string,\n from: number,\n to: number,\n out: Scan,\n): void {\n let para = -1;\n let quoteDepth = 0;\n let lists: number[] = []; // content columns of the open list items (inside the quote prefix)\n const closePara = (at: number) => {\n if (para !== -1) out.paragraphs.push([para, at]);\n para = -1;\n };\n for (let k = from; k < to; k++) {\n const line = raw(k);\n const { depth, offset } = quotePrefix(line);\n if (depth !== quoteDepth) {\n quoteDepth = depth;\n lists = [];\n }\n let content = line.slice(offset);\n if (content.trim() === \"\") {\n closePara(starts[k] as number);\n // The empty \"line\" after a final newline is not a blank line: the next\n // line may still join this paragraph.\n if (!(k === starts.length - 1 && line === \"\")) out.pendingPara = -1;\n continue;\n }\n const indent = leadingSpaces(content);\n while (lists.length && indent < (lists[lists.length - 1] as number)) lists.pop();\n const item = LIST_ITEM.exec(content);\n let column = lists.length ? (lists[lists.length - 1] as number) : 0;\n if (item) {\n const gap = (item[3] as string).length;\n column = (item[1] as string).length + (item[2] as string).length + (gap >= 1 && gap <= 4 ? gap : 1);\n lists.push(column);\n content = content.slice(Math.min(column, content.length));\n } else {\n content = content.slice(Math.min(indent, column));\n }\n const opener = fenceOpenerOf(content);\n if (!opener) {\n if (para === -1) para = starts[k] as number;\n if (out.pendingPara === -1) out.pendingPara = starts[k] as number;\n continue;\n }\n closePara(starts[k] as number);\n out.pendingPara = -1;\n const col = column;\n const src: FenceLines = {\n count: to,\n line: (j) => {\n const inner = stripQuotes(raw(j), depth);\n if (inner === null) return null;\n if (opener.char === \"~\" && col > 0) {\n const ind = leadingSpaces(inner);\n if (inner.trim() !== \"\" && ind < col) return null; // the list item ended\n return inner.slice(Math.min(ind, col));\n }\n return inner;\n },\n };\n const end = closeFence(src, k, opener);\n out.ranges.push({ start: starts[k] as number, end: ends[end.line] as number, kind: \"fence\" });\n out.fences.push([k, end.line, end.closed]);\n if (!end.closed && end.line === starts.length - 1) out.endsInFence = true;\n k = end.line;\n }\n closePara(to < starts.length ? (starts[to] as number) : text.length);\n}\n\n/**\n * THE code-span pairing table for one paragraph, text[from, to): a backtick\n * run closes at the first LATER run of exactly its length; a run with none is\n * literal text. `findCodeRanges` pairs runs in order; the tokenizer's inline\n * scanner asks `next` in the renderer's leftmost-first inline order.\n */\nexport class BacktickRuns {\n /** Every run, in order: [start, length]. */\n readonly all: Array<[number, number]> = [];\n private readonly byLength = new Map<number, number[]>();\n private readonly indexOf = new Map<number, number>();\n\n constructor(text: string, from: number, to: number) {\n for (let k = from; k < to; ) {\n if (text.charCodeAt(k) !== 96) {\n k++;\n continue;\n }\n let len = 1;\n while (k + len < to && text.charCodeAt(k + len) === 96) len++;\n this.indexOf.set(k, this.all.length);\n this.all.push([k, len]);\n const list = this.byLength.get(len);\n if (list) list.push(k);\n else this.byLength.set(len, [k]);\n k += len;\n }\n }\n\n /** Start of the first run of exactly `n` backticks at or after `after`, or -1. */\n next(n: number, after: number): number {\n const list = this.byLength.get(n);\n if (!list) return -1;\n let lo = 0;\n let hi = list.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if ((list[mid] as number) < after) lo = mid + 1;\n else hi = mid;\n }\n return list[lo] ?? -1;\n }\n\n /** Index of the run starting at `start` in `all`. */\n index(start: number): number {\n return this.indexOf.get(start) ?? -1;\n }\n}\n\nfunction codeSpans(text: string, from: number, to: number, out: CodeRange[]): void {\n // Left to right, exactly as the renderer (remark) and the tokenizer's inline\n // scanner read: a backslash escapes the next character, so an escaped\n // backtick opens nothing; a run closes at the first LATER run of exactly its\n // length (inside code a backslash is literal, so a closer may follow one).\n let runs: BacktickRuns | null = null;\n for (let i = from; i < to; ) {\n const ch = text.charCodeAt(i);\n if (ch === 92) {\n i += 2;\n continue;\n }\n if (ch !== 96) {\n i++;\n continue;\n }\n const n = backtickRunLength(text, i);\n const len = Math.min(n, to - i);\n runs ??= new BacktickRuns(text, from, to);\n const close = runs.next(len, i + len);\n if (close === -1) {\n i += len;\n continue;\n }\n out.push({ start: i, end: close + len, kind: \"span\" });\n i = close + len;\n }\n}\n\n/**\n * Every code range in the text — fences (by the renderer's rule above) and\n * inline code spans — sorted by start. Linear: one pass over lines, one over\n * each paragraph's backtick runs.\n */\nexport function findCodeRanges(text: string): CodeRange[] {\n const s = scan(text);\n const ranges = [...s.ranges];\n for (const [from, to] of s.paragraphs) codeSpans(text, from, to, ranges);\n return ranges.sort((a, b) => a.start - b.start);\n}\n\n/**\n * Rewrite every code range (fences and spans, by THE rule) through `fn`; text\n * outside code is kept byte for byte. The one way to strip, replace or\n * placeholder code in markdown — never a private /```…```/ regex.\n */\nexport function mapCodeRanges(text: string, fn: (range: CodeRange, raw: string) => string): string {\n let out = \"\";\n let at = 0;\n for (const r of findCodeRanges(text)) {\n if (r.start < at) continue;\n out += text.slice(at, r.start) + fn(r, text.slice(r.start, r.end));\n at = r.end;\n }\n return out + text.slice(at);\n}\n\n/**\n * The code SPANS in one piece of INLINE content — a table cell, a heading's\n * text, a link label — where no block structure exists, so a line opening with\n * three or more backticks is a code span, never a fence (```` `` code `` ```` in a\n * GFM cell). Same scanner and escape rules as `findCodeRanges`' span pass.\n */\nexport function findInlineCodeSpans(text: string): CodeRange[] {\n const ranges: CodeRange[] = [];\n codeSpans(text, 0, text.length, ranges);\n return ranges.sort((a, b) => a.start - b.start);\n}\n\n/** Rewrite every code SPAN of inline content through `fn` (see `findInlineCodeSpans`); other text is kept byte for byte. */\nexport function mapInlineCodeSpans(text: string, fn: (range: CodeRange, raw: string) => string): string {\n let out = \"\";\n let at = 0;\n for (const r of findInlineCodeSpans(text)) {\n if (r.start < at) continue;\n out += text.slice(at, r.start) + fn(r, text.slice(r.start, r.end));\n at = r.end;\n }\n return out + text.slice(at);\n}\n\n/** A code span's text (CommonMark): the backtick runs off, then one padding space each side when both are there and the content is not all spaces. */\nexport function codeSpanText(raw: string): string {\n const ticks = backtickRunLength(raw, 0);\n const inner = raw.slice(ticks, raw.length - ticks);\n return inner.length >= 2 && inner.startsWith(\" \") && inner.endsWith(\" \") && inner.trim() !== \"\" ? inner.slice(1, -1) : inner;\n}\n\n/**\n * A fence range's parts: its opener, its body (the lines between the opener\n * and the closer, blockquote prefixes kept), and whether it closed. Reads\n * `raw` exactly as `findCodeRanges` returned it.\n */\nexport function fenceParts(raw: string): { opener: FenceOpener; body: string; closed: boolean } | null {\n const lines = raw.split(\"\\n\").map((l) => (l.endsWith(\"\\r\") ? l.slice(0, -1) : l));\n const { offset } = quotePrefix(lines[0] ?? \"\");\n const opener = fenceOpenerOf((lines[0] ?? \"\").slice(offset).replace(/^ *(?:[-*+]|\\d{1,9}[.)])(?= |\\t|$) ?/, \"\"));\n if (!opener) return null;\n const rest = lines.slice(1);\n const closed = rest.length > 0 && new FenceReader(opener, { nesting: false }).feed(rest[rest.length - 1] as string);\n if (!closed) return { opener, body: rest.join(\"\\n\"), closed };\n const last = rest[rest.length - 1] as string;\n // The renderer's line-end closer (`code````): the text before the run is code.\n const before = trimFenceLine(last).startsWith(\"```\") ? \"\" : last.slice(0, last.indexOf(\"```\"));\n return { opener, body: [...rest.slice(0, -1), ...(before.trim() ? [before] : [])].join(\"\\n\"), closed };\n}\n\nexport type FenceLineKind = \"prose\" | \"open\" | \"body\" | \"close\";\n\n/**\n * Where each line (the text split on \"\\n\") sits relative to the fences\n * `findCodeRanges` finds: its opener, its body, its closer, or prose. For a\n * line walker that must skip code — one rule, never a private `inFence` toggle.\n */\nexport function fenceLineKinds(text: string): FenceLineKind[] {\n const s = scan(text);\n let count = 1;\n for (let i = text.indexOf(\"\\n\"); i !== -1; i = text.indexOf(\"\\n\", i + 1)) count++;\n const kinds = new Array<FenceLineKind>(count).fill(\"prose\");\n for (const [open, last, closed] of s.fences) {\n kinds[open] = \"open\";\n for (let k = open + 1; k <= last; k++) kinds[k] = \"body\";\n if (closed && last > open) kinds[last] = \"close\";\n }\n return kinds;\n}\n\n/**\n * STREAMING: where the last, still-growing paragraph (no blank line or fence\n * after it) holds a backtick run that a later run could still close — a run\n * with no later run of its length, or the run touching the end of the text\n * (it may still lengthen). Such a code span can yet swallow any `$$` after it,\n * so a streaming tokenizer treats text from there as provisional. -1 if none.\n */\nexport function pendingCodeSpanStart(text: string): number {\n const n = text.length;\n if (n === 0 || /\\n[ \\t]*\\n[ \\t]*$/.test(text)) return -1;\n // An open last line that is only whitespace or blockquote markers SO FAR is\n // not a blank line yet: its next byte may continue the paragraph\n // (verify-RC-B3 F3: `\\n ` + `and\\``, `\\n>` + `<\\`\\`\\``).\n const lastLine = text.slice(text.lastIndexOf(\"\\n\") + 1);\n if (lastLine && /^(?: {0,3}>[ \\t]?)*[ \\t\\r]*$/.test(lastLine)) return pendingCodeSpanStart(`${text}x`);\n const s = scan(text);\n const para = s.pendingPara;\n if (s.endsInFence || para === -1) return -1;\n const runs: Array<[number, number]> = [];\n for (let k = para; k < n; ) {\n if (text.charCodeAt(k) !== 96) {\n k++;\n continue;\n }\n let len = 1;\n while (k + len < n && text.charCodeAt(k + len) === 96) len++;\n runs.push([k, len]);\n k += len;\n }\n // Pair runs the way findCodeRanges does, treating a run that touches the end\n // as still growing (it matches nothing yet); the first run left open is pending.\n const growing = (r: number) => {\n const [start, len] = runs[r] as [number, number];\n return start + len === n;\n };\n for (let r = 0; r < runs.length; ) {\n if (growing(r)) return (runs[r] as [number, number])[0];\n const len = (runs[r] as [number, number])[1];\n let j = r + 1;\n while (j < runs.length && ((runs[j] as [number, number])[1] !== len || growing(j))) j++;\n if (j >= runs.length) return (runs[r] as [number, number])[0];\n r = j + 1;\n }\n return -1;\n}\n","import { fenceParts, findCodeRanges } from \"../source\";\n/**\n * Layer 0 — Structural Primitives\n *\n * Pure character-level utilities that every higher layer depends on.\n * No JSON.parse calls live here — only scanning, balancing, and fence detection.\n */\n\n// =============================================================================\n// Brace / Bracket Balancing\n// =============================================================================\n\nexport interface BalanceResult {\n endIndex: number;\n isComplete: boolean;\n}\n\n/**\n * Starting *after* the opening character at `startIndex`, walk the string\n * tracking depth, string literals, and escape sequences. Returns the index\n * of the matching close character or the end of the string if incomplete.\n *\n * `startIndex` must point at the opening `{` or `[`.\n */\nexport function findBalancedEnd(\n text: string,\n startIndex: number,\n openChar: \"{\" | \"[\",\n closeChar: \"}\" | \"]\",\n): BalanceResult {\n let depth = 1;\n let inString = false;\n let escapeNext = false;\n\n for (let i = startIndex + 1; i < text.length; i++) {\n const ch = text[i];\n\n if (escapeNext) {\n escapeNext = false;\n continue;\n }\n\n if (ch === \"\\\\\") {\n if (inString) escapeNext = true;\n continue;\n }\n\n if (ch === '\"') {\n inString = !inString;\n continue;\n }\n\n if (inString) continue;\n\n if (ch === openChar) {\n depth++;\n } else if (ch === closeChar) {\n depth--;\n if (depth === 0) {\n return { endIndex: i, isComplete: true };\n }\n }\n }\n\n return { endIndex: text.length - 1, isComplete: false };\n}\n\n/**\n * Count how many unclosed openers remain in a partial JSON string.\n * Returns the sequence of close characters needed (e.g. `\"]}\"` ).\n *\n * Handles string literals and escape sequences correctly.\n */\nexport function computeClosingSequence(text: string): string {\n const stack: string[] = [];\n let inString = false;\n let escapeNext = false;\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n\n if (escapeNext) {\n escapeNext = false;\n continue;\n }\n\n if (ch === \"\\\\\") {\n if (inString) escapeNext = true;\n continue;\n }\n\n if (ch === '\"') {\n inString = !inString;\n continue;\n }\n\n if (inString) continue;\n\n if (ch === \"{\") stack.push(\"}\");\n else if (ch === \"[\") stack.push(\"]\");\n else if (ch === \"}\" || ch === \"]\") stack.pop();\n }\n\n return stack.reverse().join(\"\");\n}\n\n// =============================================================================\n// Fence Detection\n// =============================================================================\n\nexport interface FencedBlock {\n content: string;\n language: string;\n fenceStart: number;\n contentStart: number;\n fenceEnd: number;\n isComplete: boolean;\n}\n\n/**\n * Every fenced block in `text`, in document order — THE one code-range rule\n * (@ai-matrx/content-ir/source): a fence opens only where a line starts with\n * it (never a mid-sentence ```), closes by the renderer's closer, and an\n * unclosed fence runs to the end (`isComplete: false`).\n */\nexport function findAllFencedBlocks(text: string): FencedBlock[] {\n const blocks: FencedBlock[] = [];\n for (const range of findCodeRanges(text)) {\n if (range.kind !== \"fence\") continue;\n const parts = fenceParts(text.slice(range.start, range.end));\n const openerEnd = text.indexOf(\"\\n\", range.start);\n const contentStart = openerEnd === -1 || openerEnd >= range.end ? range.end : openerEnd + 1;\n blocks.push({\n content: parts?.body ?? text.slice(contentStart, range.end),\n language: (parts?.opener.lang ?? \"\").toLowerCase(),\n fenceStart: range.start,\n contentStart,\n fenceEnd: range.end,\n isComplete: parts?.closed ?? false,\n });\n }\n return blocks;\n}\n\n// =============================================================================\n// Bare JSON Scanning\n// =============================================================================\n\nexport interface BareJsonCandidate {\n startIndex: number;\n endIndex: number;\n openChar: \"{\" | \"[\";\n isComplete: boolean;\n}\n\n/**\n * Scan `text` for top-level `{` or `[` characters that are NOT inside\n * a fenced block. Returns all candidates with balanced-end info.\n *\n * `excludeRanges` is an array of [start, end) index pairs to skip\n * (typically the ranges covered by fenced blocks).\n */\nexport function findBareJsonCandidates(\n text: string,\n excludeRanges: Array<[number, number]> = [],\n): BareJsonCandidate[] {\n const candidates: BareJsonCandidate[] = [];\n let inString = false;\n let escapeNext = false;\n\n const isExcluded = (idx: number): boolean =>\n excludeRanges.some(([s, e]) => idx >= s && idx < e);\n\n for (let i = 0; i < text.length; i++) {\n if (isExcluded(i)) continue;\n\n const ch = text[i];\n\n if (escapeNext) {\n escapeNext = false;\n continue;\n }\n\n if (ch === \"\\\\\") {\n if (inString) escapeNext = true;\n continue;\n }\n\n if (ch === '\"') {\n inString = !inString;\n continue;\n }\n\n if (inString) continue;\n\n if (ch === \"{\" || ch === \"[\") {\n const closeChar = ch === \"{\" ? \"}\" : \"]\";\n const result = findBalancedEnd(text, i, ch, closeChar);\n candidates.push({\n startIndex: i,\n endIndex: result.endIndex,\n openChar: ch,\n isComplete: result.isComplete,\n });\n if (result.isComplete) {\n i = result.endIndex;\n } else {\n break;\n }\n }\n }\n\n return candidates;\n}\n","/**\n * Layer 1 — Core JSON Extractor\n *\n * Single source of truth for \"pull JSON from text / markdown.\"\n * Always returns an array. Supports streaming and non-streaming modes.\n * Never throws — failures are represented as empty results or warnings.\n */\n\nimport {\n findAllFencedBlocks,\n findBareJsonCandidates,\n computeClosingSequence,\n type FencedBlock,\n} from \"./json-structural\";\nimport JSON5 from \"json5\";\nimport { jsonrepair } from \"jsonrepair\";\n\n// =============================================================================\n// Public Types\n// =============================================================================\n\nexport type JsonValueType = \"object\" | \"array\" | \"primitive\";\nexport type JsonSource = \"fenced\" | \"bare-block\" | \"inline\" | \"whole-string\";\n\nexport interface ExtractedJson {\n value: unknown;\n type: JsonValueType;\n source: JsonSource;\n startIndex: number;\n endIndex: number;\n isComplete: boolean;\n repairApplied: boolean;\n warnings: string[];\n}\n\nexport interface ExtractionOptions {\n /** When true, only uses conservative strategies (fenced blocks). Default false. */\n isStreaming?: boolean;\n /** Enable bare-block / inline / whole-string fallbacks. Default false. */\n allowFuzzy?: boolean;\n /** Max number of results to return. Default Infinity. */\n maxResults?: number;\n /** Apply repair strategies (trailing commas, Python syntax, etc.). Default true. */\n repairEnabled?: boolean;\n}\n\n// =============================================================================\n// Repair Helpers (lightweight — heavier repair lives in json-utils.ts)\n// =============================================================================\n\nfunction tryParse(text: string): unknown | undefined {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction tryRepairAndParse(\n text: string,\n): { value: unknown; repaired: boolean } | undefined {\n const direct = tryParse(text);\n if (direct !== undefined) return { value: direct, repaired: false };\n\n let repaired = text;\n\n repaired = repaired.replace(/,(\\s*[}\\]])/g, \"$1\");\n\n const result = tryParse(repaired);\n if (result !== undefined) return { value: result, repaired: true };\n\n repaired = text;\n repaired = repaired.replace(/\\bTrue\\b/g, \"true\");\n repaired = repaired.replace(/\\bFalse\\b/g, \"false\");\n repaired = repaired.replace(/\\bNone\\b/g, \"null\");\n repaired = repaired.replace(/,(\\s*[}\\]])/g, \"$1\");\n\n const result2 = tryParse(repaired);\n if (result2 !== undefined) return { value: result2, repaired: true };\n\n // Model-generated \"JSON\" frequently arrives as JSON5: single-quoted\n // strings, unquoted keys, or comments. Keep this at the one shared repair\n // boundary so every structured-output consumer gets the same recovery.\n try {\n return { value: JSON5.parse(text), repaired: true };\n } catch {\n return undefined;\n }\n}\n\nfunction classifyValue(value: unknown): JsonValueType {\n if (Array.isArray(value)) return \"array\";\n if (value !== null && typeof value === \"object\") return \"object\";\n return \"primitive\";\n}\n\n// =============================================================================\n// Strategy: Fenced Blocks\n// =============================================================================\n\nfunction extractFromFencedBlocks(\n _text: string,\n blocks: FencedBlock[],\n opts: Required<ExtractionOptions>,\n): ExtractedJson[] {\n const results: ExtractedJson[] = [];\n\n const jsonBlocks = blocks.filter(\n (b) => b.language === \"json\" || b.language === \"\",\n );\n\n for (const block of jsonBlocks) {\n if (results.length >= opts.maxResults) break;\n\n const content = block.content.trim();\n if (!content) continue;\n\n if (block.isComplete) {\n const parsed = opts.repairEnabled\n ? tryRepairAndParse(content)\n : (() => {\n const v = tryParse(content);\n return v !== undefined ? { value: v, repaired: false } : undefined;\n })();\n\n if (parsed !== undefined) {\n results.push({\n value: parsed.value,\n type: classifyValue(parsed.value),\n source: \"fenced\",\n startIndex: block.fenceStart,\n endIndex: block.fenceEnd,\n isComplete: true,\n repairApplied: parsed.repaired,\n warnings: parsed.repaired\n ? [\"Repair applied (trailing comma or Python syntax)\"]\n : [],\n });\n }\n } else if (opts.isStreaming) {\n const attempted = attemptStreamingClose(content, opts.repairEnabled);\n if (attempted) {\n results.push({\n value: attempted.value,\n type: classifyValue(attempted.value),\n source: \"fenced\",\n startIndex: block.fenceStart,\n endIndex: block.fenceEnd,\n isComplete: false,\n repairApplied: attempted.repaired,\n warnings: [\n \"Incomplete fenced block — auto-closed for streaming preview\",\n ],\n });\n }\n }\n }\n\n return results;\n}\n\n/**\n * For streaming: try to close an incomplete JSON string and parse it.\n * Attempts multiple strategies to produce valid JSON from a partial string.\n */\nfunction attemptStreamingClose(\n content: string,\n repairEnabled: boolean,\n): { value: unknown; repaired: boolean } | undefined {\n const candidates = buildStreamingCloseCandidates(content.trim());\n\n for (const candidate of candidates) {\n if (repairEnabled) {\n const result = tryRepairAndParse(candidate);\n if (result) return { value: result.value, repaired: true };\n }\n const direct = tryParse(candidate);\n if (direct !== undefined) return { value: direct, repaired: true };\n }\n\n return undefined;\n}\n\n/**\n * Generate candidate strings by closing the partial JSON in different ways.\n * Handles: unclosed strings, dangling keys (no value), trailing commas, etc.\n *\n * Returned in best-effort priority order — the parser tries them in turn\n * and keeps the first one that round-trips through `JSON.parse`.\n */\nfunction buildStreamingCloseCandidates(text: string): string[] {\n const candidates: string[] = [];\n\n const inString = isInsideString(text);\n\n // Strategy 1: ends mid-string. Close the string first, then either let\n // it stand as the value of the current key or treat it as a dangling key\n // and add a placeholder value.\n if (inString) {\n const closedString = text + '\"';\n const closingForString = computeClosingSequence(closedString);\n\n // The closed string IS the value (most common case mid-stream).\n candidates.push(closedString + closingForString);\n\n // The closed string was actually a key with no value yet → add `: null`.\n candidates.push(closedString + \": null\" + closingForString);\n candidates.push(closedString + ': \"\"' + closingForString);\n }\n\n // Strategy 2: ends with a dangling key+colon (`\"foo\":` and nothing after).\n // Inject a neutral placeholder value so the structure parses. We try the\n // empty-string form first because the user-stated convention is to use\n // `\"\"` as the placeholder; `null` is the fallback when that fails.\n if (!inString && /:\\s*$/.test(text)) {\n const closingD = computeClosingSequence(text);\n candidates.push(text + ' \"\"' + closingD);\n candidates.push(text + \" null\" + closingD);\n }\n\n // Strategy 3: ends with a dangling comma inside an object/array. Drop\n // the trailing comma and close. (Repair also handles trailing commas,\n // but emitting an explicitly truncated candidate avoids depending on\n // repair being enabled.)\n if (!inString && /,\\s*$/.test(text)) {\n const truncated = text.replace(/,\\s*$/, \"\");\n const closingE = computeClosingSequence(truncated);\n candidates.push(truncated + closingE);\n }\n\n // Strategy 4: truncate at last clean boundary (`,`, `}`, `]`) and close.\n const lastClean = findLastCleanBreak(text);\n if (lastClean > 0 && lastClean < text.length) {\n const truncated = text.slice(0, lastClean);\n const closingB = computeClosingSequence(truncated);\n candidates.push(truncated + closingB);\n }\n\n // Strategy 5: raw close (whatever we have + just the closing chars). Last\n // resort — frequently produces invalid JSON when the input ends mid-value,\n // but useful when the input ends right after a complete value.\n const closingC = computeClosingSequence(text);\n if (closingC) {\n candidates.push(text + closingC);\n }\n\n // Strategy 6: if not in a string and no open structures, try as-is\n // (e.g. the input is already a complete value with trailing whitespace).\n if (!inString && !computeClosingSequence(text)) {\n candidates.push(text);\n }\n\n return candidates;\n}\n\n/**\n * Find the last position where truncating produces valid JSON context.\n * Looks backward for a comma, closing brace/bracket, or colon+value boundary.\n */\nfunction findLastCleanBreak(text: string): number {\n let inStr = false;\n let escapeNext = false;\n let lastBreak = 0;\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (escapeNext) {\n escapeNext = false;\n continue;\n }\n if (ch === \"\\\\\") {\n if (inStr) escapeNext = true;\n continue;\n }\n if (ch === '\"') {\n inStr = !inStr;\n continue;\n }\n if (inStr) continue;\n\n if (ch === \",\" || ch === \"}\" || ch === \"]\") {\n lastBreak = i + 1;\n }\n }\n\n return lastBreak;\n}\n\n/**\n * Heuristic: check if the string ends inside an unclosed JSON string literal.\n */\nfunction isInsideString(text: string): boolean {\n let inString = false;\n let escapeNext = false;\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (escapeNext) {\n escapeNext = false;\n continue;\n }\n if (ch === \"\\\\\") {\n if (inString) escapeNext = true;\n continue;\n }\n if (ch === '\"') {\n inString = !inString;\n }\n }\n\n return inString;\n}\n\n// =============================================================================\n// Strategy: Bare Blocks (JSON not inside fences)\n// =============================================================================\n\nfunction extractFromBareBlocks(\n text: string,\n fencedBlocks: FencedBlock[],\n opts: Required<ExtractionOptions>,\n): ExtractedJson[] {\n const results: ExtractedJson[] = [];\n\n const excludeRanges: Array<[number, number]> = fencedBlocks.map((b) => [\n b.fenceStart,\n b.fenceEnd,\n ]);\n\n const candidates = findBareJsonCandidates(text, excludeRanges);\n\n for (const candidate of candidates) {\n if (results.length >= opts.maxResults) break;\n\n if (candidate.isComplete) {\n const raw = text.slice(candidate.startIndex, candidate.endIndex + 1);\n const parsed = opts.repairEnabled\n ? tryRepairAndParse(raw)\n : (() => {\n const v = tryParse(raw);\n return v !== undefined ? { value: v, repaired: false } : undefined;\n })();\n\n if (parsed !== undefined) {\n results.push({\n value: parsed.value,\n type: classifyValue(parsed.value),\n source: \"bare-block\",\n startIndex: candidate.startIndex,\n endIndex: candidate.endIndex + 1,\n isComplete: true,\n repairApplied: parsed.repaired,\n warnings: parsed.repaired\n ? [\"Repair applied to bare JSON block\"]\n : [\"JSON found without code fence markers\"],\n });\n }\n continue;\n }\n\n // Incomplete candidate — only attempt streaming auto-close in streaming\n // mode. In non-streaming mode the JSON should be balanced; an unbalanced\n // candidate is almost always prose with a stray `{` or `[`.\n if (!opts.isStreaming) continue;\n\n const raw = text.slice(candidate.startIndex, candidate.endIndex + 1);\n const attempted = attemptStreamingClose(raw, opts.repairEnabled);\n if (attempted) {\n results.push({\n value: attempted.value,\n type: classifyValue(attempted.value),\n source: \"bare-block\",\n startIndex: candidate.startIndex,\n endIndex: candidate.endIndex + 1,\n isComplete: false,\n repairApplied: attempted.repaired,\n warnings: [\"Incomplete bare JSON — auto-closed for streaming preview\"],\n });\n }\n }\n\n return results;\n}\n\n// =============================================================================\n// Strategy: Whole-String\n// =============================================================================\n\nfunction extractFromWholeString(\n text: string,\n opts: Required<ExtractionOptions>,\n): ExtractedJson[] {\n const trimmed = text.trim();\n if (!trimmed) return [];\n\n const parsed = opts.repairEnabled\n ? tryRepairAndParse(trimmed)\n : (() => {\n const v = tryParse(trimmed);\n return v !== undefined ? { value: v, repaired: false } : undefined;\n })();\n\n if (parsed !== undefined) {\n return [\n {\n value: parsed.value,\n type: classifyValue(parsed.value),\n source: \"whole-string\",\n startIndex: 0,\n endIndex: text.length,\n isComplete: true,\n repairApplied: parsed.repaired,\n warnings: [\n \"Entire input parsed as JSON (no fences or structure detected)\",\n ],\n },\n ];\n }\n\n return [];\n}\n\n\n// =============================================================================\n// Strategy: Whole-Document Repair (parity with matrx-ai response_parser)\n// =============================================================================\n\n/**\n * Repair guard against FABRICATION — repair, never invention. Mirrors the\n * server's `_repair_is_faithful`: the text opens a JSON document, the repaired\n * value keeps that opening bracket's type, and the text carries key/value\n * evidence (a `:` or a quoted string). `\"{{{{ unbalanced\"` has none of that.\n */\nfunction repairIsFaithful(text: string, value: unknown): boolean {\n const first = text[0];\n if (first !== \"{\" && first !== \"[\") return false;\n if (first === \"{\" && !(value !== null && typeof value === \"object\" && !Array.isArray(value))) return false;\n if (first === \"[\" && !Array.isArray(value)) return false;\n return text.includes(\":\") || text.includes('\"');\n}\n\n/**\n * A WHOLE DOCUMENT WITH ONE TYPO IS STILL THE ANSWER. When the text is one\n * document opening with `{`/`[` that strict + JSON5 parsing rejects (a stray\n * `]` deep inside thousands of minified characters), the bare-block walker\n * would carve out an inner fragment — or nothing. A faithful `jsonrepair` of\n * the whole document outranks any fragment (describe box, 2026-10-08).\n */\n/**\n * Drop closers that match nothing on the open-bracket stack (a stray `]` where\n * `}` belongs). `jsonrepair` throws on these; the server's json-repair absorbs\n * them. Only strips — never adds a character.\n */\nfunction dropStrayClosers(text: string): string {\n const stack: string[] = [];\n let out = \"\";\n let inString = false;\n let escapeNext = false;\n for (const ch of text) {\n if (escapeNext) { escapeNext = false; out += ch; continue; }\n if (inString) {\n if (ch === \"\\\\\") escapeNext = true;\n else if (ch === '\"') inString = false;\n out += ch;\n continue;\n }\n if (ch === '\"') inString = true;\n else if (ch === \"{\" || ch === \"[\") stack.push(ch);\n else if (ch === \"}\" || ch === \"]\") {\n const top = stack[stack.length - 1];\n if (top === undefined || (top === \"{\") !== (ch === \"}\")) continue;\n stack.pop();\n }\n out += ch;\n }\n return out;\n}\n\nfunction extractWholeDocumentRepair(text: string): ExtractedJson | undefined {\n const trimmed = text.trim();\n if (trimmed[0] !== \"{\" && trimmed[0] !== \"[\") return undefined;\n if (tryRepairAndParse(trimmed) !== undefined) return undefined;\n let value: unknown;\n for (const attempt of [trimmed, dropStrayClosers(trimmed)]) {\n try {\n value = JSON.parse(jsonrepair(attempt));\n break;\n } catch {\n value = undefined;\n }\n }\n if (value === undefined) return undefined;\n if (!repairIsFaithful(trimmed, value)) return undefined;\n return {\n value,\n type: classifyValue(value),\n source: \"whole-string\",\n startIndex: text.indexOf(trimmed),\n endIndex: text.indexOf(trimmed) + trimmed.length,\n isComplete: true,\n repairApplied: true,\n warnings: [\n \"Whole document had malformed syntax; recovered via jsonrepair instead of a fragment\",\n ],\n };\n}\n\n// =============================================================================\n// Main Entry Point\n// =============================================================================\n\nconst DEFAULTS: Required<ExtractionOptions> = {\n isStreaming: false,\n allowFuzzy: false,\n maxResults: Infinity,\n repairEnabled: true,\n};\n\n/**\n * Extract all JSON values from a text / markdown string.\n *\n * Strategy order depends on mode:\n *\n * **Streaming (`isStreaming: true`)**:\n * 1. Fenced blocks (with auto-close for incomplete blocks)\n * 2. If `allowFuzzy` (or no fenced results): bare blocks (with auto-close)\n *\n * **Non-streaming (`isStreaming: false`)**:\n * 1. Fenced blocks (complete only)\n * 2. If `allowFuzzy` and still below `maxResults`: bare blocks\n * 3. If `allowFuzzy` and still no results: whole-string parse\n *\n * @returns Array of extracted JSON values, in document order. Empty if none found.\n */\nexport function extractAllJson(\n text: string,\n options?: ExtractionOptions,\n): ExtractedJson[] {\n if (!text || typeof text !== \"string\") return [];\n\n const opts: Required<ExtractionOptions> = { ...DEFAULTS, ...options };\n\n if (!opts.isStreaming && opts.repairEnabled) {\n const whole = extractWholeDocumentRepair(text);\n if (whole) return [whole];\n }\n\n const allFenced = findAllFencedBlocks(text);\n\n // Strategy 1: Fenced blocks (always runs)\n const fencedResults = extractFromFencedBlocks(text, allFenced, opts);\n\n if (fencedResults.length >= opts.maxResults) {\n return fencedResults.slice(0, opts.maxResults);\n }\n\n // Strategy 2: Bare blocks. Runs in both streaming and non-streaming when\n // fuzzy is allowed, OR when nothing was caught in fences (so plain bare\n // JSON like `{ \"x\": 1 }` without a fence still gets picked up). In\n // streaming mode `extractFromBareBlocks` will auto-close the trailing\n // candidate so the consumer sees a live preview.\n const remaining = opts.maxResults - fencedResults.length;\n let bareResults: ExtractedJson[] = [];\n\n if (opts.allowFuzzy || fencedResults.length === 0) {\n bareResults = extractFromBareBlocks(text, allFenced, {\n ...opts,\n maxResults: remaining,\n });\n }\n\n const combined = [...fencedResults, ...bareResults];\n if (combined.length >= opts.maxResults) {\n return combined.slice(0, opts.maxResults);\n }\n\n if (opts.isStreaming) {\n return combined;\n }\n\n // Strategy 3: Whole-string (non-streaming, fuzzy, still no results)\n if (opts.allowFuzzy && combined.length === 0) {\n const wholeResults = extractFromWholeString(text, opts);\n return wholeResults.slice(0, opts.maxResults);\n }\n\n return combined;\n}\n\n// =============================================================================\n// Convenience Helpers\n// =============================================================================\n\n/**\n * Extract the first JSON object from text. Returns `null` if none found.\n * This is the drop-in replacement for legacy `extractJsonFromText`.\n */\nexport function extractFirstJson(\n text: string,\n options?: ExtractionOptions,\n): ExtractedJson | null {\n const results = extractAllJson(text, { ...options, maxResults: 1 });\n return results[0] ?? null;\n}\n\n/**\n * Extract the first JSON object (not array, not primitive) from text.\n */\nexport function extractFirstObject(\n text: string,\n options?: ExtractionOptions,\n): ExtractedJson | null {\n const results = extractAllJson(text, options);\n return results.find((r) => r.type === \"object\") ?? null;\n}\n\n/**\n * Quick \"does this text contain extractable JSON?\" check.\n * Cheaper than full extraction when you only need a boolean.\n */\nexport function containsJson(\n text: string,\n options?: ExtractionOptions,\n): boolean {\n return extractAllJson(text, { ...options, maxResults: 1 }).length > 0;\n}\n","/**\n * Layer 3 — Streaming JSON Tracker\n *\n * Stateful wrapper around extractAllJson that tracks changes across\n * streaming chunks and avoids dispatching redundant updates.\n */\n\nimport {\n extractAllJson,\n type ExtractedJson,\n type ExtractionOptions,\n} from \"./extract-json\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface StreamingJsonState {\n results: ExtractedJson[];\n /** True when all detected structures have balanced braces/brackets */\n isAllComplete: boolean;\n /** True when we've detected an open ```json fence without a close */\n hasOpenFence: boolean;\n /** Monotonically increasing — bumped only when results actually change */\n revision: number;\n /** The accumulated text so far */\n textLength: number;\n}\n\nexport interface StreamingJsonTrackerOptions {\n /** Max results to track. Default Infinity. */\n maxResults?: number;\n /** Apply repair strategies. Default true. */\n repairEnabled?: boolean;\n /** Enable fuzzy matching on finalize. Default true. */\n fuzzyOnFinalize?: boolean;\n}\n\n// =============================================================================\n// Tracker\n// =============================================================================\n\nconst INITIAL_STATE: StreamingJsonState = {\n results: [],\n isAllComplete: true,\n hasOpenFence: false,\n revision: 0,\n textLength: 0,\n};\n\nexport class StreamingJsonTracker {\n private text = \"\";\n private state: StreamingJsonState = { ...INITIAL_STATE };\n private opts: Required<StreamingJsonTrackerOptions>;\n private lastResultsHash = \"\";\n\n constructor(options?: StreamingJsonTrackerOptions) {\n this.opts = {\n maxResults: options?.maxResults ?? Infinity,\n repairEnabled: options?.repairEnabled ?? true,\n fuzzyOnFinalize: options?.fuzzyOnFinalize ?? true,\n };\n }\n\n /**\n * Append a new chunk of text and re-extract. Returns the new state.\n * Only bumps `revision` if the extraction results actually changed.\n */\n append(chunk: string): StreamingJsonState {\n this.text += chunk;\n return this.extract(true);\n }\n\n /**\n * Run a final extraction pass with full strategies (including fuzzy).\n * Call once when the stream is complete.\n */\n finalize(): StreamingJsonState {\n return this.extract(false);\n }\n\n /** Replace the entire accumulated text (useful if you manage accumulation externally). */\n setFullText(text: string): StreamingJsonState {\n this.text = text;\n return this.extract(true);\n }\n\n /** Get the current state without re-extracting. */\n getState(): StreamingJsonState {\n return this.state;\n }\n\n /** Get the accumulated text. */\n getText(): string {\n return this.text;\n }\n\n /** Reset to initial state. */\n reset(): void {\n this.text = \"\";\n this.state = { ...INITIAL_STATE };\n this.lastResultsHash = \"\";\n }\n\n // ---------------------------------------------------------------------------\n // Internal\n // ---------------------------------------------------------------------------\n\n private extract(isStreaming: boolean): StreamingJsonState {\n const options: ExtractionOptions = {\n isStreaming,\n allowFuzzy: isStreaming ? false : this.opts.fuzzyOnFinalize,\n maxResults: this.opts.maxResults,\n repairEnabled: this.opts.repairEnabled,\n };\n\n const results = extractAllJson(this.text, options);\n const hash = this.computeHash(results);\n\n if (hash !== this.lastResultsHash) {\n this.lastResultsHash = hash;\n this.state = {\n results,\n isAllComplete: results.every((r) => r.isComplete),\n hasOpenFence: results.some(\n (r) => r.source === \"fenced\" && !r.isComplete,\n ),\n revision: this.state.revision + 1,\n textLength: this.text.length,\n };\n } else {\n this.state = {\n ...this.state,\n textLength: this.text.length,\n };\n }\n\n return this.state;\n }\n\n /**\n * Cheap hash of extraction results for change detection.\n * We hash on: count, types, completeness, and the stringified values.\n * This avoids deep-equality checks on every chunk.\n */\n private computeHash(results: ExtractedJson[]): string {\n if (results.length === 0) return \"empty\";\n\n const parts: string[] = [];\n for (const r of results) {\n parts.push(\n `${r.type}:${r.source}:${r.isComplete}:${r.startIndex}-${r.endIndex}`,\n );\n try {\n parts.push(JSON.stringify(r.value));\n } catch {\n parts.push(\"unstringifiable\");\n }\n }\n return parts.join(\"|\");\n }\n}\n"]}
|
package/dist/source.cjs
CHANGED
|
@@ -2884,6 +2884,198 @@ function resolveReferenceLinks(fragment, defs) {
|
|
|
2884
2884
|
return resolved.replace(new RegExp(`${PLACEHOLDER}(\\d+)${PLACEHOLDER}`, "g"), (_m, i) => spans[Number(i)] ?? "");
|
|
2885
2885
|
}
|
|
2886
2886
|
|
|
2887
|
+
// source/delimiter-guard.ts
|
|
2888
|
+
var ZWSP = "\u200B";
|
|
2889
|
+
var ESCAPED_DOLLARS = `${ZWSP}$${ZWSP}$`;
|
|
2890
|
+
var ESCAPED_BRACKET = `${ZWSP}[`;
|
|
2891
|
+
function protectedRanges(text) {
|
|
2892
|
+
return findCodeRanges(text).map((r) => [r.start, r.end]);
|
|
2893
|
+
}
|
|
2894
|
+
function isProtected(index, ranges) {
|
|
2895
|
+
return ranges.some(([start, end]) => index >= start && index < end);
|
|
2896
|
+
}
|
|
2897
|
+
function preview(text, max = 160) {
|
|
2898
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
2899
|
+
return flat.length > max ? `${flat.slice(0, max)}\u2026` : flat;
|
|
2900
|
+
}
|
|
2901
|
+
function guardMathDelimiters(text) {
|
|
2902
|
+
if (!text.includes("$$")) return { text, violations: [] };
|
|
2903
|
+
const ranges = protectedRanges(text);
|
|
2904
|
+
const tokens = [];
|
|
2905
|
+
for (let i = 0; i < text.length - 1; i++) {
|
|
2906
|
+
if (text[i] !== "$" || text[i + 1] !== "$") continue;
|
|
2907
|
+
if (!isProtected(i, ranges)) tokens.push(i);
|
|
2908
|
+
i++;
|
|
2909
|
+
}
|
|
2910
|
+
if (tokens.length === 0) return { text, violations: [] };
|
|
2911
|
+
const violations = [];
|
|
2912
|
+
const escapeAt = [];
|
|
2913
|
+
let j = 0;
|
|
2914
|
+
while (j < tokens.length) {
|
|
2915
|
+
const open = tokens[j];
|
|
2916
|
+
const close = tokens[j + 1];
|
|
2917
|
+
if (close === void 0) {
|
|
2918
|
+
violations.push({
|
|
2919
|
+
reason: "unpaired",
|
|
2920
|
+
index: open,
|
|
2921
|
+
spanLength: 0,
|
|
2922
|
+
// An unpaired `$$` is inert to remark-math (nothing closes it), so it
|
|
2923
|
+
// is reported but NOT escaped — it already renders as literal text.
|
|
2924
|
+
preview: preview(text.slice(open, open + 120))
|
|
2925
|
+
});
|
|
2926
|
+
break;
|
|
2927
|
+
}
|
|
2928
|
+
const inner = text.slice(open + 2, close);
|
|
2929
|
+
if (isMathPlaceholder(inner)) {
|
|
2930
|
+
escapeAt.push(open, close);
|
|
2931
|
+
violations.push({ reason: "prose-span", index: open, spanLength: inner.length, preview: preview(inner) });
|
|
2932
|
+
j += 2;
|
|
2933
|
+
continue;
|
|
2934
|
+
}
|
|
2935
|
+
if (looksLikeDisplayMath(inner, opensFlowBlock(text, open))) {
|
|
2936
|
+
j += 2;
|
|
2937
|
+
continue;
|
|
2938
|
+
}
|
|
2939
|
+
escapeAt.push(open);
|
|
2940
|
+
violations.push({
|
|
2941
|
+
reason: "prose-span",
|
|
2942
|
+
index: open,
|
|
2943
|
+
spanLength: inner.length,
|
|
2944
|
+
preview: preview(inner)
|
|
2945
|
+
});
|
|
2946
|
+
j += 1;
|
|
2947
|
+
}
|
|
2948
|
+
let guarded = text;
|
|
2949
|
+
for (const index of [...escapeAt].sort((a, b) => b - a)) {
|
|
2950
|
+
guarded = `${guarded.slice(0, index)}${ESCAPED_DOLLARS}${guarded.slice(index + 2)}`;
|
|
2951
|
+
}
|
|
2952
|
+
return { text: guarded, violations };
|
|
2953
|
+
}
|
|
2954
|
+
var MAX_LINK_LABEL = 200;
|
|
2955
|
+
var LABEL_BLOCK_STRUCTURE = /\n[ \t]*\n|(?:^|\n)[ \t]*[-*+][ \t]+|#{2,6}[ \t]/;
|
|
2956
|
+
function guardRunawayLinks(text) {
|
|
2957
|
+
if (!text.includes("[")) return { text, violations: [] };
|
|
2958
|
+
const ranges = protectedRanges(text);
|
|
2959
|
+
const violations = [];
|
|
2960
|
+
const escapeAt = [];
|
|
2961
|
+
const linkRe = /\[((?:[^[\]\\]|\\.)*)\]\(([^\s)]*)/g;
|
|
2962
|
+
let m;
|
|
2963
|
+
while ((m = linkRe.exec(text)) !== null) {
|
|
2964
|
+
const open = m.index;
|
|
2965
|
+
if (isProtected(open, ranges)) continue;
|
|
2966
|
+
const label = m[1] ?? "";
|
|
2967
|
+
const runaway = label.length > MAX_LINK_LABEL || LABEL_BLOCK_STRUCTURE.test(label);
|
|
2968
|
+
if (!runaway) continue;
|
|
2969
|
+
escapeAt.push(open);
|
|
2970
|
+
violations.push({
|
|
2971
|
+
reason: "runaway-link",
|
|
2972
|
+
index: open,
|
|
2973
|
+
spanLength: label.length,
|
|
2974
|
+
preview: preview(label)
|
|
2975
|
+
});
|
|
2976
|
+
}
|
|
2977
|
+
let guarded = text;
|
|
2978
|
+
for (const index of [...escapeAt].sort((a, b) => b - a)) {
|
|
2979
|
+
guarded = `${guarded.slice(0, index)}${ESCAPED_BRACKET}${guarded.slice(index + 1)}`;
|
|
2980
|
+
}
|
|
2981
|
+
return { text: guarded, violations };
|
|
2982
|
+
}
|
|
2983
|
+
function guardMarkdownDelimiters(text) {
|
|
2984
|
+
const math = guardMathDelimiters(text);
|
|
2985
|
+
const links = guardRunawayLinks(math.text);
|
|
2986
|
+
return {
|
|
2987
|
+
text: links.text,
|
|
2988
|
+
violations: [...math.violations, ...links.violations]
|
|
2989
|
+
};
|
|
2990
|
+
}
|
|
2991
|
+
function reportDelimiterViolations(violations, context) {
|
|
2992
|
+
if (violations.length === 0) return;
|
|
2993
|
+
try {
|
|
2994
|
+
const worst = violations.find((v) => v.reason !== "unpaired") ?? violations[0];
|
|
2995
|
+
if (!worst) return;
|
|
2996
|
+
const message = worst.reason === "prose-span" ? `Malformed math delimiters: a stray "$$" would have turned ${worst.spanLength} chars of prose into a math span (KaTeX would render it as red error text). Escaped it.` : worst.reason === "runaway-link" ? `Runaway markdown link: an unclosed "[" would have turned ${worst.spanLength} chars into one link label. Escaped it.` : `Malformed math delimiters: an unpaired "$$" reached the renderer.`;
|
|
2997
|
+
console.warn(`[markdown-delimiter-guard] ${message}`, {
|
|
2998
|
+
renderPath: context.renderPath,
|
|
2999
|
+
violations
|
|
3000
|
+
});
|
|
3001
|
+
context.capture?.({
|
|
3002
|
+
source: "markdown-delimiters",
|
|
3003
|
+
message,
|
|
3004
|
+
relation: `markdown:${context.renderPath}`,
|
|
3005
|
+
details: worst.preview,
|
|
3006
|
+
conversationId: context.conversationId,
|
|
3007
|
+
callSite: "guardMarkdownDelimiters",
|
|
3008
|
+
raw: { messageId: context.messageId, violations }
|
|
3009
|
+
});
|
|
3010
|
+
} catch {
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
|
|
3014
|
+
// source/thinking.ts
|
|
3015
|
+
function codeRanges2(text, live) {
|
|
3016
|
+
const ranges = findCodeRanges(text).map((r) => [r.start, r.end]);
|
|
3017
|
+
if (live) {
|
|
3018
|
+
const pending = pendingCodeSpanStart(text);
|
|
3019
|
+
if (pending >= 0 && !inCode(ranges, pending)) ranges.push([pending, text.length]);
|
|
3020
|
+
}
|
|
3021
|
+
return ranges.sort((x, y) => x[0] - y[0]);
|
|
3022
|
+
}
|
|
3023
|
+
function inCode(ranges, index) {
|
|
3024
|
+
return ranges.some(([a, b]) => index >= a && index < b);
|
|
3025
|
+
}
|
|
3026
|
+
function collapseGaps(text) {
|
|
3027
|
+
const ranges = codeRanges2(text, false);
|
|
3028
|
+
let out = "";
|
|
3029
|
+
let at = 0;
|
|
3030
|
+
for (const [a, b] of ranges) {
|
|
3031
|
+
out += text.slice(at, a).replace(/\n{3,}/g, "\n\n") + text.slice(a, b);
|
|
3032
|
+
at = b;
|
|
3033
|
+
}
|
|
3034
|
+
return out + text.slice(at).replace(/\n{3,}/g, "\n\n");
|
|
3035
|
+
}
|
|
3036
|
+
var OPEN_TAG = /<(thinking|reasoning)\b[^>]*>/gi;
|
|
3037
|
+
function removeClosedBlocks(input, live) {
|
|
3038
|
+
let text = input;
|
|
3039
|
+
for (; ; ) {
|
|
3040
|
+
const ranges = codeRanges2(text, live);
|
|
3041
|
+
OPEN_TAG.lastIndex = 0;
|
|
3042
|
+
let opener = null;
|
|
3043
|
+
for (let m = OPEN_TAG.exec(text); m; m = OPEN_TAG.exec(text)) {
|
|
3044
|
+
if (!inCode(ranges, m.index)) {
|
|
3045
|
+
opener = m;
|
|
3046
|
+
break;
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
if (!opener) return { text, openAt: -1 };
|
|
3050
|
+
const closeTag = new RegExp(`</${opener[1]}\\s*>`, "gi");
|
|
3051
|
+
closeTag.lastIndex = opener.index + opener[0].length;
|
|
3052
|
+
let closer = null;
|
|
3053
|
+
for (let m = closeTag.exec(text); m; m = closeTag.exec(text)) {
|
|
3054
|
+
if (!inCode(ranges, m.index)) {
|
|
3055
|
+
closer = m;
|
|
3056
|
+
break;
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
if (!closer) return { text, openAt: opener.index };
|
|
3060
|
+
text = text.slice(0, opener.index) + text.slice(closer.index + closer[0].length);
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
function stripThinking(input) {
|
|
3064
|
+
if (!input) return "";
|
|
3065
|
+
return collapseGaps(removeClosedBlocks(input, false).text).trim();
|
|
3066
|
+
}
|
|
3067
|
+
function hasThinkingTags(input) {
|
|
3068
|
+
if (!input) return false;
|
|
3069
|
+
return removeClosedBlocks(input, false).text !== input;
|
|
3070
|
+
}
|
|
3071
|
+
function stripThinkingStreaming(input) {
|
|
3072
|
+
if (!input) return { visible: "", isThinking: false };
|
|
3073
|
+
const { text, openAt } = removeClosedBlocks(input, true);
|
|
3074
|
+
const isThinking = openAt !== -1;
|
|
3075
|
+
const kept = isThinking ? text.slice(0, openAt) : text;
|
|
3076
|
+
return { visible: collapseGaps(kept).replace(/^\s+/, ""), isThinking };
|
|
3077
|
+
}
|
|
3078
|
+
|
|
2887
3079
|
// source/code-range-edits.ts
|
|
2888
3080
|
function unwrapCodeSpans(text) {
|
|
2889
3081
|
if (!text.includes("`")) return text;
|
|
@@ -3330,6 +3522,10 @@ exports.findLinkDefinitionLines = findLinkDefinitionLines;
|
|
|
3330
3522
|
exports.findTableEnd = findTableEnd;
|
|
3331
3523
|
exports.findTableStart = findTableStart;
|
|
3332
3524
|
exports.findWholeTableStart = findWholeTableStart;
|
|
3525
|
+
exports.guardMarkdownDelimiters = guardMarkdownDelimiters;
|
|
3526
|
+
exports.guardMathDelimiters = guardMathDelimiters;
|
|
3527
|
+
exports.guardRunawayLinks = guardRunawayLinks;
|
|
3528
|
+
exports.hasThinkingTags = hasThinkingTags;
|
|
3333
3529
|
exports.hasUnclosedBacktickRun = hasUnclosedBacktickRun;
|
|
3334
3530
|
exports.indexOutsideInlineCode = indexOutsideInlineCode;
|
|
3335
3531
|
exports.initialXmlBalance = initialXmlBalance;
|
|
@@ -3365,6 +3561,7 @@ exports.pendingDisplayMathOpener = pendingDisplayMathOpener;
|
|
|
3365
3561
|
exports.readXmlTag = readXmlTag;
|
|
3366
3562
|
exports.removeCodeSpans = removeCodeSpans;
|
|
3367
3563
|
exports.replaceFences = replaceFences;
|
|
3564
|
+
exports.reportDelimiterViolations = reportDelimiterViolations;
|
|
3368
3565
|
exports.resolveReferenceLinks = resolveReferenceLinks;
|
|
3369
3566
|
exports.rowCells = rowCells;
|
|
3370
3567
|
exports.singleDollarAfter = singleDollarAfter;
|
|
@@ -3377,6 +3574,8 @@ exports.splitsSurrogatePair = splitsSurrogatePair;
|
|
|
3377
3574
|
exports.startsHtmlBlock = startsHtmlBlock;
|
|
3378
3575
|
exports.startsLikeTableRow = startsLikeTableRow;
|
|
3379
3576
|
exports.startsPipelessTable = startsPipelessTable;
|
|
3577
|
+
exports.stripThinking = stripThinking;
|
|
3578
|
+
exports.stripThinkingStreaming = stripThinkingStreaming;
|
|
3380
3579
|
exports.tableContainerIndent = tableContainerIndent;
|
|
3381
3580
|
exports.tableStartsAt = tableStartsAt;
|
|
3382
3581
|
exports.toCodePointOffset = toCodePointOffset;
|