/**
 * rag/splitters — where a document gets cut, and why there.
 *
 * Pattern: Strategy family (factory functions), the same shape as the window
 *          and retrieval families. Not a `{ kind }` union: a splitter you write
 *          yourself is the same shape as these, unused ones stay out of a
 *          bundle, and adding one needs no switch edited anywhere.
 * Role:    rag/ layer.
 * Emits:   N/A.
 *
 * ── The defaults, and the measurement behind them ───────────────────────────
 *
 * `maxChars: 1000`, `overlapChars: 150`. Those numbers are chosen by
 * CONSTRAINT, not by fashion, and the constraint is measurable:
 *
 * **`localEmbedder`'s default model silently truncates at 512 wordpiece
 * tokens.** Measured directly — embed a long text, embed the same text with an
 * unrelated tail appended, and compare. At 508 base tokens the tail still
 * moves the vector (cosine 0.9965). At 596 it does not (cosine 0.999999): the
 * tail was discarded and nothing said so. 512 wordpiece tokens is roughly
 * 1,800–2,000 characters of English.
 *
 * A chunk of 1,000 characters is about 250 tokens. That sits comfortably
 * inside that cliff, inside the 256-token length the sentence-transformer
 * family was actually trained at, and trivially inside `openaiEmbedder`'s
 * 8,191. Raise it and you approach a limit whose failure mode is silence —
 * half your chunk embedded, full score reported.
 *
 * ── How this number composes with the INDEXER's ceiling ─────────────────────
 *
 * Two numbers bound one chunk and they are set in different places:
 * `maxChars` HERE decides how big a chunk is cut, and `maxChunkChars` at
 * `indexCorpus` / `indexFolder` / `indexDocuments` decides how much of it the
 * embedder actually reads. At the shipped defaults they compose safely —
 * 1,000 out of a ceiling of at least 2,000, so every chunk is embedded whole.
 *
 * **The trap opens when the splitter's ceiling is raised.** `byHeading({
 * maxChars: 2500 })` against an embedder whose ceiling is 2,000 produces
 * chunks that are stored WHOLE as the passage and indexed by their OPENING:
 * retrieval cannot find wording that is plainly visible in the block the model
 * is later shown, and no error is raised anywhere. Measured in a production
 * corpus: 6 of 26 chunks, against an embedder that would have read every one
 * of them in full.
 *
 * Since 9.1.0 the indexer reads the ceiling off the EMBEDDER
 * (`Embedder.maxInputChars`) rather than assuming the on-device cliff, and
 * says out loud — once, with the count — when anything was clipped. So raising
 * `maxChars` is safe up to what your embedder declares, and past it you are
 * told rather than left to discover it in a retrieval result.
 *
 * The 150-character overlap (15%) exists so a sentence spanning a boundary is
 * whole in one of the two neighbours. It is the smallest overlap that reliably
 * does that for English prose; there is nothing deeper claimed for it.
 *
 * **`minChars` (8.20.0): the floor, from a different measurement.** Short
 * chunks retrieve too WELL, not too badly — similarity is a density measure,
 * and a heading plus a preamble sentence concentrates a topic's vocabulary
 * with none of its substance. Measured in a production corpus: a 180-char
 * heading-and-preamble chunk outranked its own section's 1,032-char body, and
 * the model fabricated a citation to fill the promise the empty chunk made.
 * `byHeading` and `byParagraph` therefore merge sub-floor chunks FORWARD into
 * the next chunk (default floor `min(250, maxChars / 4)`; nothing is ever
 * dropped, and a heading with no body is never emitted alone regardless of
 * the floor). `fixedWithOverlap` does not have the failure shape — its chunks
 * are uniformly `chars` long BY REQUEST, and its only runt (the file tail) has
 * always folded backward — and `wholeDocument` is one-chunk-per-document by
 * definition, so neither takes the option.
 *
 * ── Which one to use ────────────────────────────────────────────────────────
 *
 * | splitter | cuts on | use when |
 * |---|---|---|
 * | `byHeading()` | Markdown `#` lines | the document declares its own sections — **not a heuristic** |
 * | `byParagraph()` | blank lines | prose with no headings |
 * | `fixedWithOverlap()` | character count | text with no structure at all (transcripts, OCR) |
 * | `wholeDocument()` | nothing | short documents that are already one idea |
 *
 * `byHeading` is the only one that is not guessing. The author already marked
 * where the sections are; the others are inferring boundaries from typography.
 * That is why it is the default for Markdown.
 */
export { byParagraph, type ByParagraphOptions } from './byParagraph.js';
export { byHeading, type ByHeadingOptions } from './byHeading.js';
export { fixedWithOverlap, type FixedWithOverlapOptions } from './fixedWithOverlap.js';
export { wholeDocument } from './wholeDocument.js';
export { DEFAULT_MAX_CHARS, DEFAULT_OVERLAP_CHARS, DEFAULT_MIN_CHARS } from './constants.js';
//# sourceMappingURL=index.d.ts.map