import type { EditInput } from './edit.js'; /** * The apply core `edit`'s tool definition calls at mutation time, pulled out * on its own so a second caller — the step-context projection that replays a * visible edit call to verify a claimed post-edit body — runs this exact * code instead of a parallel implementation that could drift from it (most * easily on the CRLF reconciliation below, which depends on the real file's * line-ending mix). * * Pure by construction: no filesystem access, no `ToolContext`. Everything * here is a function from strings to strings. */ export type NormalizedEditInput = { operation: 'replace'; oldString: string; newString: string; replace_all: boolean; } | { operation: 'insert'; insertLine: number | 'end'; newString: string; replace_all: boolean; }; /** * Turn one call into the ordered list of operations it stands for. * * A list rather than a single operation because the batch shape is not a * different kind of edit, only a longer one. Keeping ONE representation is * what stops the two shapes diverging: everything below this function — the * uniqueness check, the CRLF reconciliation, the identical-text refusal, the * atomic write — sees a list of length one for a single edit and never learns * which shape the caller used. */ export declare function normalizeEditInput(input: EditInput): { success: true; operations: NormalizedEditInput[]; } | { success: false; error: string; }; /** * Apply every operation in order, or none of them. * * "Or none" is the whole reason this takes a list. Four related changes sent * as four calls are four chances to stop halfway, and the file left behind * after the third succeeded and the fourth did not is in a state no one wrote * and no one is looking at. Here the fold runs entirely in memory and the * caller writes once, so a failure anywhere leaves the file exactly as it was. * * Each operation matches against the content as the ones before it left it, * not against the original. That is what lets a later edit target text an * earlier one produced — and it is also why a failure names the INDEX: by the * time hunk 3 fails, the string it was looking for may have been consumed by * hunk 1, and "old_string not found" without a position sends the model to * re-check the wrong hunk. */ export declare function applyEdit(content: string, operations: readonly NormalizedEditInput[]): { success: true; content: string; replacements: number; } | { success: false; error: string; }; /** * What a bounded replay did, and what it cost. * * A union rather than a throw because all three outcomes are ordinary answers * to a caller replaying somebody else's call: it applied, it would have built * more than the caller has room for, or it no longer applies to the content it * was handed. Only the first carries a body; the other two carry the charge so * the caller can settle the room the attempt actually used. */ export type BoundedReplay = { readonly outcome: 'replayed'; readonly content: string; readonly charged: number; readonly replacements: number; } | { readonly outcome: 'refused'; readonly charged: number; } | { readonly outcome: 'failed'; readonly charged: number; readonly error: string; }; /** * The single door a caller outside this module uses. * * Runs a visible call's arguments through the same normalize-then-apply path * `EditTool.execute` runs at mutation time, against a content string the * caller already has in hand — never the filesystem — and under an * `allowance`: the largest string the caller is willing to have built on its * behalf. * * The allowance is honoured one OPERATION at a time. Each operation's * post-image length is worked out exactly from the content it is about to be * applied to, compared against the allowance, and only then applied — so * nothing over the ceiling is ever materialised, and nothing under it is * refused for a bound that guessed high. An earlier shape predicted the whole * call up front, which meant folding operations after the first against a * string it had never seen: a rename hunk at index 1 was charged one match per * anchor-length window of the file, and batches that would have fitted were * turned away for a number nothing had built. * * `charged` is the longest string this call actually materialised, which is * the one the caller paid for holding. It is the post-image length exactly for * the single-operation shape almost every call has; for a batch it is the * largest intermediate the fold built rather than the body it ends on, because * a batch that grows a file to twenty megabytes and then deletes every * character has still built the twenty megabytes. An operation that is refused * or fails is charged nothing — it built nothing — while the ones before it in * the same batch are charged, having run. */ export declare function replayEditCallWithin(content: string, rawArguments: unknown, allowance: number): BoundedReplay; /** * The same walk, entered with the operations already normalized. * * Separate from the entry point above so the equivalence with {@link applyEdit} * can be exercised operation by operation — `replayOperationsWithin(c, [op], ∞)` * is `applyOne(c, op)` plus its exact predicted length — rather than only in * the aggregate, where a prediction that is wrong in two places by the same * amount would pass. */ export declare function replayOperationsWithin(content: string, operations: readonly NormalizedEditInput[], allowance: number): BoundedReplay; //# sourceMappingURL=edit-apply.d.ts.map