UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

75 lines • 4.07 kB
import type { FileCacheMixin } from '../cache/file/mixin.ts'; import type { Evicted } from '../cache/index/config.ts'; import { FileStat } from '../types.ts'; import { BaseVFS } from '../vfs/base.ts'; import type { MountEntry } from './mount/mount.ts'; import type { Namespace } from './mount/namespace/namespace.ts'; /** * Keep the local view honest against backend truth. * * The single reconcile point every read path shares. Under a mount's * `read: fresh` a backend re-stat classifies a path as fresh, stale * (fingerprint mismatch), gone * (deletion), or unknown (no fingerprint to compare). One deletion signal * feeds both consumers with separate reactions: the file cache evicts and the * namespace GCs any orphaned attribute overlay. * * Three read paths call in, all at the dispatcher: its cached-read gate * (mayServeCached), its main-op catch (onEnoent), and its first lookup of a * path the running command's line names (reconcileRead). The re-stat goes * through the ops registry (not mount.call, whose op set omits stat). * Reconcile state follows each consumer's store (RAM local, Redis shared * across runtimes), so this is a thin coordinator holding references, not * config. * * The gate and reconcileRead both run for a warm named operand, once at the * command's first lookup of it and again at the gate, and they share one * scope: the command. The * first probe's backend answer is kept on the mount's CacheManager for the * rest of the command, so the gate, and the command's own stat of the * operand, reuse it instead of asking again. A write in the command, the * clear after an external program, or a re-list that finds the path gone * retires it, and a read outside any command (FUSE, the dispatcher) never sees * it. */ export declare class Reconciler { private readonly cache; private readonly namespace; constructor(cache: FileCacheMixin & BaseVFS, namespace: Namespace); private drop; private probe; private probeOrUnknown; mayServeCached(mount: MountEntry, path: string): Promise<boolean>; /** * Gate a cached listing: may it be served without re-listing? * * Under `bounded` the listing is trusted within its bound. Under `fresh` a * listing the running command fetched itself is served (a read outside any * command trusts one fetched within the last `LISTING_TRUST_WINDOW` * seconds instead, `CacheManager.listingTrusted`). Past that, a listing * stored at the mount's pin is served without asking: github pins a * full-sha ref and serves its listing unchecked when the stored version * equals that sha. It names a commit: github.com refuses a 40- or 64-hex * branch or tag name, and a GitHub Enterprise host is assumed to as well * (`pinOf` in vfs/github/github.ts). A mount that declares a * `listingVersion` then has its stored `version` checked against a stat of * the mount root (MOUNT) or of the folder (FOLDER), sent through a * throwaway index so no cached row answers it. One check answers for a * whole command, and concurrent callers share it * (`CacheManager.checkedVersion`). * * A match serves the listing. Anything else answers EXPIRED and keeps the * listing stored for the re-list to diff: a moved version, a path the * backend no longer has, a stat with no fingerprint, a mount with no stat * at all, and a backend that cannot answer, which is logged. The index is * never cleared here. A programming error propagates. */ mayServeListing(mount: MountEntry, folder: string, version: string | null): Promise<boolean>; private listingFingerprint; reconcileRead(mount: MountEntry, path: string): Promise<void>; onEnoent(mount: MountEntry, name: string, path: string, err: unknown): Promise<void>; onFreshStat(mount: MountEntry, path: string, row: FileStat | null): Promise<void>; onGone(gone: readonly Evicted[], excluded?: readonly string[]): Promise<void>; private onMissing; } //# sourceMappingURL=reconcile.d.ts.map