UNPKG

aiwrapper

Version:

A Universal AI Wrapper for JavaScript & TypeScript

284 lines (283 loc) 8.75 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); function applyDiff_v4a(input, diff, mode = "default") { const diffLines = normalizeDiffLines(diff); if (mode === "create") { return parseCreateDiff(diffLines); } const { chunks } = parseUpdateDiff(diffLines, input); return applyChunks(input, chunks); } const END_PATCH = "*** End Patch"; const END_FILE = "*** End of File"; const END_SECTION_MARKERS = [ END_PATCH, "*** Update File:", "*** Delete File:", "*** Add File:", END_FILE ]; const SECTION_TERMINATORS = [ END_PATCH, "*** Update File:", "*** Delete File:", "*** Add File:" ]; function normalizeDiffLines(diff) { return diff.split(/\r?\n/).map((line) => line.replace(/\r$/, "")).filter((line, idx, arr) => !(idx === arr.length - 1 && line === "")); } function isDone(state, prefixes) { if (state.index >= state.lines.length) return true; if (prefixes.some((p) => { var _a; return (_a = state.lines[state.index]) == null ? void 0 : _a.startsWith(p); })) return true; return false; } function readStr(state, prefix) { const current = state.lines[state.index]; if (typeof current === "string" && current.startsWith(prefix)) { state.index += 1; return current.slice(prefix.length); } return ""; } function parseCreateDiff(lines) { const parser = { lines: [...lines, END_PATCH], index: 0, fuzz: 0 }; const output = []; while (!isDone(parser, SECTION_TERMINATORS)) { const line = parser.lines[parser.index]; parser.index += 1; if (!line.startsWith("+")) { throw new Error(`Invalid Add File Line: ${line}`); } output.push(line.slice(1)); } return output.join("\n"); } function parseUpdateDiff(lines, input) { const parser = { lines: [...lines, END_PATCH], index: 0, fuzz: 0 }; const inputLines = input.split("\n"); const chunks = []; let cursor = 0; while (!isDone(parser, END_SECTION_MARKERS)) { const anchor = readStr(parser, "@@ "); const hasBareAnchor = !anchor && parser.lines[parser.index] === "@@"; if (hasBareAnchor) parser.index += 1; if (!(anchor || hasBareAnchor || cursor === 0)) { throw new Error(`Invalid Line: ${parser.lines[parser.index]}`); } if (anchor.trim()) { cursor = advanceCursorToAnchor(anchor, inputLines, cursor, parser); } const { nextContext, sectionChunks, endIndex, eof } = readSection( parser.lines, parser.index ); const nextContextText = nextContext.join("\n"); const { newIndex, fuzz } = findContext( inputLines, nextContext, cursor, eof ); if (newIndex === -1) { if (eof) { throw new Error(`Invalid EOF Context ${cursor}: ${nextContextText}`); } throw new Error(`Invalid Context ${cursor}: ${nextContextText}`); } parser.fuzz += fuzz; for (const ch of sectionChunks) { chunks.push(__spreadProps(__spreadValues({}, ch), { origIndex: ch.origIndex + newIndex })); } cursor = newIndex + nextContext.length; parser.index = endIndex; } return { chunks, fuzz: parser.fuzz }; } function advanceCursorToAnchor(anchor, inputLines, cursor, parser) { let found = false; if (!inputLines.slice(0, cursor).some((s) => s === anchor)) { for (let i = cursor; i < inputLines.length; i += 1) { if (inputLines[i] === anchor) { cursor = i + 1; found = true; break; } } } if (!found && !inputLines.slice(0, cursor).some((s) => s.trim() === anchor.trim())) { for (let i = cursor; i < inputLines.length; i += 1) { if (inputLines[i].trim() === anchor.trim()) { cursor = i + 1; parser.fuzz += 1; found = true; break; } } } return cursor; } function readSection(lines, startIndex) { const context = []; let delLines = []; let insLines = []; const sectionChunks = []; let mode = "keep"; let index = startIndex; const origIndex = index; while (index < lines.length) { const raw = lines[index]; if (raw.startsWith("@@") || raw.startsWith(END_PATCH) || raw.startsWith("*** Update File:") || raw.startsWith("*** Delete File:") || raw.startsWith("*** Add File:") || raw.startsWith(END_FILE)) { break; } if (raw === "***") break; if (raw.startsWith("***")) { throw new Error(`Invalid Line: ${raw}`); } index += 1; const lastMode = mode; let line = raw; if (line === "") line = " "; if (line[0] === "+") { mode = "add"; } else if (line[0] === "-") { mode = "delete"; } else if (line[0] === " ") { mode = "keep"; } else { throw new Error(`Invalid Line: ${line}`); } line = line.slice(1); const switchingToContext = mode === "keep" && lastMode !== mode; if (switchingToContext && (insLines.length || delLines.length)) { sectionChunks.push({ origIndex: context.length - delLines.length, delLines, insLines }); delLines = []; insLines = []; } if (mode === "delete") { delLines.push(line); context.push(line); } else if (mode === "add") { insLines.push(line); } else { context.push(line); } } if (insLines.length || delLines.length) { sectionChunks.push({ origIndex: context.length - delLines.length, delLines, insLines }); delLines = []; insLines = []; } if (index < lines.length && lines[index] === END_FILE) { index += 1; return { nextContext: context, sectionChunks, endIndex: index, eof: true }; } if (index === origIndex) { throw new Error(`Nothing in this section - index=${index} ${lines[index]}`); } return { nextContext: context, sectionChunks, endIndex: index, eof: false }; } function findContext(lines, context, start, eof) { if (eof) { const endStart = Math.max(0, lines.length - context.length); const endMatch = findContextCore(lines, context, endStart); if (endMatch.newIndex !== -1) return endMatch; const fallback = findContextCore(lines, context, start); return { newIndex: fallback.newIndex, fuzz: fallback.fuzz + 1e4 }; } return findContextCore(lines, context, start); } function findContextCore(lines, context, start) { if (!context.length) { return { newIndex: start, fuzz: 0 }; } for (let i = start; i < lines.length; i += 1) { if (equalsSlice(lines, context, i, (s) => s)) return { newIndex: i, fuzz: 0 }; } for (let i = start; i < lines.length; i += 1) { if (equalsSlice(lines, context, i, (s) => s.trimEnd())) return { newIndex: i, fuzz: 1 }; } for (let i = start; i < lines.length; i += 1) { if (equalsSlice(lines, context, i, (s) => s.trim())) return { newIndex: i, fuzz: 100 }; } return { newIndex: -1, fuzz: 0 }; } function equalsSlice(source, target, start, mapFn) { if (start + target.length > source.length) return false; for (let i = 0; i < target.length; i += 1) { if (mapFn(source[start + i]) !== mapFn(target[i])) return false; } return true; } function applyChunks(input, chunks) { const origLines = input.split("\n"); const destLines = []; let origIndex = 0; for (const chunk of chunks) { if (chunk.origIndex > origLines.length) { throw new Error( `applyDiff: chunk.origIndex ${chunk.origIndex} > input length ${origLines.length}` ); } if (origIndex > chunk.origIndex) { throw new Error( `applyDiff: overlapping chunk at ${chunk.origIndex} (cursor ${origIndex})` ); } destLines.push(...origLines.slice(origIndex, chunk.origIndex)); origIndex = chunk.origIndex; if (chunk.insLines.length) { destLines.push(...chunk.insLines); } origIndex += chunk.delLines.length; } destLines.push(...origLines.slice(origIndex)); const result = destLines.join("\n"); return result; } export { applyDiff_v4a }; //# sourceMappingURL=applyDiff-v4a.js.map