API
All public functions and types exported by `editkit` and `editkit/ai-sdk`.
parseEdits(input, options?)
Parse all edits from an LLM response. Returns a sorted array of ParsedEdits. No file I/O.
import { parseEdits } from "editkit";
const edits = parseEdits(llmOutput);
// [{ format: "search-replace", path: "src/util.ts", search: "...", replace: "...", range: {...} }]Pass { formats: ["search-replace"] } to restrict parsing to one format (useful when
you've prompted in one format and want hard-fails on the others).
applyEdits(input, files, options?)
Parse and apply in one async call. Returns one ApplyResult per parsed edit, in source
order.
import { applyEdits } from "editkit";
const results = await applyEdits(llmOutput, {
"src/util.ts": "export const x = 1;\n",
});files is either:
- A
Record<string, string>(path → current contents), or - An async function
(path: string) => Promise<string | null>.
Return null (or throw) for paths that don't exist; the applier treats the edit as a
"create" if the format and allowCreate (default true) permit.
applyEditsSync(input, files, options?)
Synchronous variant. Requires a Record<string, string> (no async file reader). Useful in
tests and in environments where you've pre-loaded everything into memory.
streamEdits(stream, files, options?) (in editkit/ai-sdk)
Async iterable that yields { edit, result } for each completed edit as soon as its
closing fence has streamed in.
import { streamEdits } from "editkit/ai-sdk";
for await (const { edit, result } of streamEdits(textStream, fileReader)) {
// ...
}See streaming concepts for what "complete" means per format.
fuzzyReplace(original, search, replace, options?)
Exposed as a primitive in case you want the matching logic without the parsing layer.
import { fuzzyReplace } from "editkit";
const out = fuzzyReplace(originalText, searchText, replaceText);
// { kind: "ok", text, strategy: "exact" | "indent-shift" | "trim-eol" }
// { kind: "ambiguous", count: number }
// { kind: "not-found" }detectFormats(input)
Heuristic detector. Returns the formats that appear in input, in priority order.
import { detectFormats } from "editkit";
detectFormats(llmOutput);
// ["search-replace"] or ["search-replace", "unified-diff"] etc.Types
type EditFormat = "search-replace" | "unified-diff" | "whole-file";
interface ParsedEdit {
format: EditFormat;
path: string;
// ...format-specific fields
range: { start: number; end: number };
}
type FileReader =
| Record<string, string>
| ((path: string) => Promise<string | null> | string | null);
type ApplyResult =
| { ok: true; path: string; before: string; after: string; edit: ParsedEdit }
| {
ok: false;
path: string;
reason: ApplyFailureReason;
message: string;
edit: ParsedEdit;
};
type ApplyFailureReason =
| "search-not-found"
| "ambiguous-match"
| "hunk-context-mismatch"
| "missing-original"
| "invalid-format";
interface ApplyOptions {
formats?: EditFormat[];
fuzzyWhitespace?: boolean; // default true
allowCreate?: boolean; // default true
}