UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

105 lines • 3.37 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. ========= import {} from "../../../files.js"; // What a create opens: a file made and never written still lands. const CREATE = Object.freeze({ readable: false, writable: true, truncate: false, append: false, create: true, exclusive: false, binary: true, }); export function createJournal() { const journal = []; let sealed = false; const record = (entry) => { if (!sealed) journal.push(entry); }; return { markCreate(path) { record({ kind: 'create', path }); }, takeCreate(path) { const last = journal.at(-1); if (last?.kind !== 'create' || last.path !== path) return false; journal.pop(); return true; }, markTruncate(path, length) { record({ kind: 'truncate', path, length }); }, markMkdir(path) { record({ kind: 'mkdir', path }); }, markUnlink(path) { record({ kind: 'unlink', path }); }, markRmdir(path) { record({ kind: 'rmdir', path }); }, markRename(src, dst) { record({ kind: 'rename', path: src, dst }); }, markSymlink(path, target) { record({ kind: 'symlink', path, target }); }, markSetattr(path, attrs) { record({ kind: 'setattr', path, attrs }); }, seal() { sealed = true; }, get sealed() { return sealed; }, reopen() { sealed = false; }, takeMutations() { return journal.splice(0, journal.length); }, }; } /** * Replay one recorded guest mutation against the mounts. * * Args: * files: the runtime's mount vocabulary to apply through. * mutation: the journal entry to apply. */ export async function applyMutation(files, mutation) { switch (mutation.kind) { case 'create': return files.close(await files.open(mutation.path, CREATE)); case 'truncate': return files.truncate(mutation.path, mutation.length); case 'mkdir': return files.mkdir(mutation.path); case 'unlink': return files.unlink(mutation.path); case 'rmdir': return files.rmdir(mutation.path); case 'rename': return files.rename(mutation.path, mutation.dst); case 'symlink': return files.symlink(mutation.path, mutation.target); case 'setattr': return files.setattr(mutation.path, mutation.attrs); } } //# sourceMappingURL=journal.js.map