/**
 * File encoding + line-ending detection for the Read/Edit/Write band, ported from CC's
 * `utils/fileRead.ts` mechanism and hardened where CC is lossy:
 *
 *  - BOM detection: `FF FE` → utf16le, `EF BB BF` → utf8-with-BOM, else plain utf8. Detection is
 *    BOM-only; UTF-16BE / heuristic sniffing is deliberately NOT done — a wrong guess silently
 *    corrupts, and the BOM-less case stays a refusal at the Read layer.
 *  - The MODEL-FACING text is BOM-stripped and CRLF-normalized (what the model quotes in `old_string`
 *    must match what Read showed it). CRLF-normalize is parity on both of CC's read lanes; BOM-strip
 *    is parity on CC's READ lane only — CC's EDIT/WRITE lane hands the model text with the leading
 *    U+FEFF still in it and strips only inside its staleness/hash coordinate. sema strips in ONE
 *    shared decoder for every lane, so the model-facing view and the hash coordinate cannot drift
 *    apart: a registered delta, not parity.
 *  - Write-back re-encodes with the ORIGINAL encoding, PRESERVES the BOM (CC drops it on Write — a
 *    registered deliberate improvement), and restores the file's dominant line endings for Edit
 *    (Write keeps the model's endings as-is, CC decision).
 */
/** Detected byte-level encoding of a text file (BOM-driven; utf8 is the no-BOM default). */
export interface DetectedFileEncoding {
    encoding: "utf8" | "utf16le";
    hadBom: boolean;
}
export type DetectedLineEndings = "CRLF" | "LF";
export interface DecodedTextFile {
    /** Model-facing text: BOM stripped, `\r\n` normalized to `\n`. The staleness-hash coordinate. */
    text: string;
    encoding: DetectedFileEncoding;
    /** Dominant line ending of the ORIGINAL bytes (majority vote; CC's counting rule).
     *  Deliberately NOT per-line lossless: a mixed-endings file is unified to the dominant ending on
     *  the first edit (accepted non-goal — CC behaves the same way).
     *  The SAMPLE is a registered delta: CC votes on the first 4096 characters only, while
     *  {@link detectLineEndings} below votes on the whole file. The verdict decides what an Edit WRITES
     *  BACK across the entire file, so sampling a prefix is exactly the case where the cheap answer
     *  flips the remaining 99% of the lines. */
    endings: DetectedLineEndings;
    /** A utf16le body with an ODD byte count is TRUNCATED/corrupt — decoding would silently drop the
     *  dangling byte and a later write-back would destroy it permanently. Flagged so the tool layer
     *  fails closed instead of "repairing" the file. */
    malformed?: true;
}
/** BOM-only encoding detection (CC `detectEncodingForResolvedPath` parity — no content heuristics). */
export declare function detectFileEncoding(bytes: Uint8Array): DetectedFileEncoding;
/** Decode file bytes into the model-facing normalized form + the metadata needed to write back losslessly. */
export declare function decodeTextBytes(bytes: Uint8Array): DecodedTextFile;
/**
 * Re-encode text for writing back to a file that was decoded with {@link decodeTextBytes}.
 *
 * @param text normalized (`\n`) text when `endings` is CRLF/LF (Edit path — restore the file's
 *   dominant endings); pass `endings:"preserve"` to write the text's OWN line endings untouched
 *   (Write path — CC decision: the model sent explicit endings in `content` and meant them).
 * @returns a plain string for the no-BOM utf8 + LF-or-preserve fast path, else the exact bytes
 *   (BOM + encoded body).
 */
export declare function encodeTextForFile(text: string, encoding: DetectedFileEncoding, endings: DetectedLineEndings | "preserve"): string | Uint8Array;
/** Normalize model-supplied match/replacement text the same way the file text was normalized
 *  (CC FileEditTool parity: `old_string`/`new_string` are CRLF-normalized before matching).
 *  Deliberately does NOT strip a leading U+FEFF: an `old_string` starting with one may be quoting
 *  genuine file content — use {@link normalizeFileText} only where the string stands for a whole file. */
export declare function normalizeEditText(s: string): string;
/** Split a leading U+FEFF off MODEL-SUPPLIED whole-file text (CC parity). The BOM is a file-level
 *  byte marker, not text: decodeTextBytes strips it on the way in, so it can never live in the
 *  normalized coordinate. Only for strings that stand for a WHOLE file (Write `content`,
 *  readFileState seeding) — a decoded file text's leading U+FEFF is genuine content and must stay. */
export declare function splitLeadingBom(text: string): {
    hadBom: boolean;
    text: string;
};
/** CC parity (BOM-strip + CRLF-normalize): THE coordinate every readFileState hash lives in
 *  (Read/Edit/Write staleness all hash `decodeTextBytes(...).text`). A hash taken on raw model content
 *  with a leading U+FEFF can never agree with any later re-read. */
export declare function normalizeFileText(s: string): string;
