UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

158 lines • 5.3 kB
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= function findLongestMatch(a, b, alo, ahi, blo, bhi, b2j) { let besti = alo; let bestj = blo; let bestsize = 0; let j2len = new Map(); for (let i = alo; i < ahi; i++) { const newJ2len = new Map(); const indices = b2j.get(a[i] ?? '') ?? []; for (const j of indices) { if (j < blo) continue; if (j >= bhi) break; const k = (j2len.get(j - 1) ?? 0) + 1; newJ2len.set(j, k); if (k > bestsize) { besti = i - k + 1; bestj = j - k + 1; bestsize = k; } } j2len = newJ2len; } while (besti > alo && bestj > blo && a[besti - 1] === b[bestj - 1]) { besti -= 1; bestj -= 1; bestsize += 1; } while (besti + bestsize < ahi && bestj + bestsize < bhi && a[besti + bestsize] === b[bestj + bestsize]) { bestsize += 1; } return { a: besti, b: bestj, size: bestsize }; } function getMatchingBlocks(a, b) { const b2j = new Map(); for (let j = 0; j < b.length; j++) { const key = b[j] ?? ''; const arr = b2j.get(key) ?? []; arr.push(j); b2j.set(key, arr); } if (b.length >= 200) { const popular = Math.floor(b.length / 100) + 1; for (const [line, indices] of b2j) if (indices.length > popular) b2j.delete(line); } const matches = []; const queue = [[0, a.length, 0, b.length]]; while (queue.length > 0) { const entry = queue.shift(); if (entry === undefined) break; const [alo, ahi, blo, bhi] = entry; const m = findLongestMatch(a, b, alo, ahi, blo, bhi, b2j); if (m.size > 0) { matches.push(m); if (alo < m.a && blo < m.b) queue.push([alo, m.a, blo, m.b]); if (m.a + m.size < ahi && m.b + m.size < bhi) { queue.push([m.a + m.size, ahi, m.b + m.size, bhi]); } } } matches.sort((x, y) => x.a - y.a || x.b - y.b); // merge adjacent matches const merged = []; let i = 0; while (i < matches.length) { const cur = matches[i]; if (cur === undefined) break; const a1 = cur.a; const b1 = cur.b; let size = cur.size; while (i + 1 < matches.length && matches[i + 1]?.a === a1 + size && matches[i + 1]?.b === b1 + size) { const nxt = matches[i + 1]; if (nxt === undefined) break; size += nxt.size; i += 1; } merged.push({ a: a1, b: b1, size }); i += 1; } merged.push({ a: a.length, b: b.length, size: 0 }); return merged; } export function getOpcodes(a, b) { const matches = getMatchingBlocks(a, b); const opcodes = []; let i = 0; let j = 0; for (const m of matches) { if (i < m.a && j < m.b) opcodes.push(['replace', i, m.a, j, m.b]); else if (i < m.a) opcodes.push(['delete', i, m.a, j, m.b]); else if (j < m.b) opcodes.push(['insert', i, m.a, j, m.b]); if (m.size > 0) opcodes.push(['equal', m.a, m.a + m.size, m.b, m.b + m.size]); i = m.a + m.size; j = m.b + m.size; } return opcodes; } export function groupOpcodes(opcodes, n) { if (opcodes.length === 0) return []; const codes = opcodes.map((op) => [...op]); const first = codes[0]; const last = codes[codes.length - 1]; if (first?.[0] === 'equal') { const [, i1, i2, j1, j2] = first; first[1] = Math.max(i1, i2 - n); first[3] = Math.max(j1, j2 - n); } if (last?.[0] === 'equal') { const [, i1, i2, j1, j2] = last; last[2] = Math.min(i2, i1 + n); last[4] = Math.min(j2, j1 + n); } const groups = []; let current = []; for (const op of codes) { const [tag, i1, i2, j1, j2] = op; if (tag === 'equal' && i2 - i1 > 2 * n) { current.push(['equal', i1, Math.min(i2, i1 + n), j1, Math.min(j2, j1 + n)]); groups.push(current); current = [['equal', Math.max(i1, i2 - n), i2, Math.max(j1, j2 - n), j2]]; continue; } current.push([tag, i1, i2, j1, j2]); } if (current.length > 0 && !(current.length === 1 && current[0]?.[0] === 'equal')) { groups.push(current); } return groups; } //# sourceMappingURL=diff_format.js.map