@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
101 lines • 3.52 kB
TypeScript
import { type RuntimeFiles } from '../../../files.ts';
import type { SetAttrFields } from '../../../../types.ts';
/**
* One guest change to names or metadata, recorded in the order the script
* performed it. A file's bytes are not here: its stream writes through
* its core handle (`SyncVFS.pwrite`).
*/
export type MirageMutation = {
readonly kind: 'create';
readonly path: string;
} | {
readonly kind: 'truncate';
readonly path: string;
readonly length: number;
} | {
readonly kind: 'mkdir';
readonly path: string;
} | {
readonly kind: 'unlink';
readonly path: string;
} | {
readonly kind: 'rmdir';
readonly path: string;
} | {
readonly kind: 'rename';
readonly path: string;
readonly dst: string;
} | {
readonly kind: 'symlink';
readonly path: string;
readonly target: string;
} | {
readonly kind: 'setattr';
readonly path: string;
readonly attrs: SetAttrFields;
};
/**
* The write-ahead log a pyodide guest records into.
*
* Every mark is deliberately synchronous: the guest's os.mkdir() and
* os.rename() run inside sync WASM frames where awaiting a mount op
* needs JSPI stack switching, which most engines do not enable. The guest
* records here and the runtime replays after the script returns, where
* awaiting is free. This is the one thing pyodide needs that the other
* runtimes do not: quickjs suspends at the call and monty runs the op on
* its own worker.
*/
export interface MutationJournal {
markCreate(path: string): void;
/**
* Take back the create of `path` the journal ends with, which the open
* right after it makes instead; false when it ends with no such create.
*/
takeCreate(path: string): boolean;
/**
* Args:
* path: mount-prefixed path the mutation names.
* length: the length the file is left at.
*/
markTruncate(path: string, length: number): void;
markMkdir(path: string): void;
markUnlink(path: string): void;
markRmdir(path: string): void;
markRename(src: string, dst: string): void;
/**
* Args:
* path: guest-absolute path of the link.
* target: what it points at, stored verbatim.
*/
markSymlink(path: string, target: string): void;
/**
* Args:
* path: guest-absolute path whose metadata changed.
* attrs: only the fields the guest wrote, already in the op's own
* terms (ISO stamps), because the unit Emscripten passes is the
* caller's fact and not the journal's.
*/
markSetattr(path: string, attrs: SetAttrFields): void;
/** Drain the journal: every mutation in guest order, cleared. */
takeMutations(): MirageMutation[];
/**
* Record nothing more until `reopen`: the guest called `os._exit`, and
* a process that exited writes nothing after it, even when the guest
* catches the exit and runs on.
*/
seal(): void;
/** Whether the guest exited since the last `reopen`: its streams read and write nothing more either. */
readonly sealed: boolean;
/** Record again, for the next run. */
reopen(): void;
}
export declare function createJournal(): MutationJournal;
/**
* 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 declare function applyMutation(files: RuntimeFiles, mutation: MirageMutation): Promise<void>;
//# sourceMappingURL=journal.d.ts.map