@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
117 lines • 7.08 kB
TypeScript
import type { LinkView, ReaddirPath, StatPath } from '../../../view/types.ts';
import type { Files } from '../../../workspace/files.ts';
import type { DispatchFn } from '../../../runtime/types.ts';
import { FileStat, PathSpec, type StatFn } from '../../../types.ts';
import { type FsError } from '../../../errors/types.ts';
import type { FlagValue } from '../../spec/types.ts';
import type { FsCondition } from '../../../errors/types.ts';
/**
* Opt in by assigning a debug sink, as Python's module logger is off until
* configured: every failed read runs the probe, and stdout may carry data.
*/
export declare const logger: {
debug?: (message: string) => void;
};
export declare function resolvePathStat(dispatch: DispatchFn, path: PathSpec): Promise<FileStat | null>;
export declare function dispatchStat(dispatch: DispatchFn): StatFn;
export declare function vfsStatPath(files: Files | undefined): StatPath | undefined;
export declare function vfsReaddirPath(files: Files | undefined): ReaddirPath | undefined;
export declare function statOrEnoent(statPath: StatPath): StatFn;
/**
* `path` keyed by its whole virtual path, the shape a command's paths take:
* the dispatcher routes each one to its mount, so no command derives a mount
* from a path's key. Mirrors Python's virtual_key.
*/
export declare function virtualKey(path: PathSpec): PathSpec;
/**
* A command's flags with every path value keyed by its whole virtual path
* (`virtualKey`): a single path (awk -f) or a list of them (repeated grep -f).
* Everything else passes through unchanged. Mirrors Python's virtual_flags.
*/
export declare function virtualFlags(bag: Record<string, FlagValue>): Record<string, FlagValue>;
export declare function spelledFrom(path: PathSpec, operand: PathSpec): PathSpec;
export declare function descendantPath(root: PathSpec, virtual: string): PathSpec;
export declare function entryKind(stat: StatFn, path: PathSpec): Promise<{
exists: boolean;
isDir: boolean;
}>;
export declare function nearestAncestor(stat: StatFn, path: PathSpec): Promise<[string, boolean]>;
export declare function isImplicitDir(readdir: (path: PathSpec) => Promise<string[]>, path: PathSpec): Promise<boolean>;
/**
* Whether a failed or empty read was a read of a directory.
*
* Asked after failure or EOF without bytes: some drivers return an empty
* stream for directories. Nonempty reads need no extra probe. One that knows
* says so (gdrive, box, dropbox and disk throw EISDIR), a keyed store answers
* ENOENT because a directory there is a set of keys rather than an object,
* and sftp answers with an error carrying no errno at all.
*
* Three ways the answer can be yes, in probe-cost order. The code itself
* costs nothing. The stat is one call, and a stat that ANSWERS ends the
* cascade either way: a file is a file, and the later probe only makes
* sense for a path stat could not see. Reaching past a successful stat
* read a rule-refused file as a directory, because its parent's listing
* names it. The parent listing is one call and is the only thing that can
* tell a missing key from a prefix that exists only through deeper keys.
*
* A no leaves the original error untouched, so nothing is swallowed: the
* caller rethrows what the backend said. Both probes are broad for that
* same reason: a probe that fails is a negative probe, never an error to
* surface. Surfacing one would replace the read's error with one from a
* call the user never made, and it is the read that failed.
* `isImplicitDir` narrows to a miss because for its other caller the stat
* IS the operation; here it is a probe, so the wider catch belongs on this
* side of the call, and each failure it absorbs is logged. Mirrors Python's
* `read_hit_a_dir`.
*/
export declare function readHitADir(stat: (path: PathSpec) => Promise<FileStat>, readdir: (path: PathSpec) => Promise<string[]>, path: PathSpec, err: unknown): Promise<boolean>;
export declare function absentDestError(stat: StatFn, target: PathSpec): Promise<FsCondition | null>;
export declare function linkFollow(links: LinkView | null | undefined): ((path: string) => string) | null;
export declare function linkTarget(links: LinkView | null | undefined): ((path: string) => string | null) | null;
/**
* The typed spelling, links before `..`, while it names the path. Mirrors
* Python's walk_spelling.
*
* Without a trailing slash: that is a final `.`, which `dotRefusal` proves,
* and a store that keeps no directories reads a slashed key as one, so
* `cat reg/` there was ENOENT, not ENOTDIR.
*/
export declare function walkSpelling(path: PathSpec, follow: ((path: string) => string) | null): string;
/**
* ENOENT when the walk of a path's dots looks up a name the session cannot
* see, null when it sees every one.
*
* `virtual` simplified the dots away, so a hidden name in front of one
* (`secret/../f`, a hidden link's `lnk/../f`) is gone from the path the
* hides judge, while the walk still has to find it. It answers as a missing
* name does, and before `dotRefusal` proves anything a directory, so the
* refusal cannot tell a hide from an absence. The walk stops at the hidden
* name, so a link there is never followed. Mirrors Python's hidden_walk.
*/
export declare function hiddenWalk(path: PathSpec, follow: ((path: string) => string) | null, visible: (path: string) => boolean): FsError | null;
/**
* What a path's dot components answer, null when every one resolves.
*
* The kernel resolves `.` and `..` against the directory they sit in, so a
* walk through a missing name fails ENOENT and one through a plain file
* ENOTDIR (`cat nope/../f`, `cat f.txt/.`), where the textual simplification
* in `virtual` reached `f` regardless. Each name in front of a dot is proved
* a directory, in walk order, and one that is not is judged by its chain the
* way a create is, so a miss under a plain file is ENOTDIR on every store.
* A link in front of a dot is followed first, as the kernel walks (only
* bash's `cd` reads `link/..` logically). A trailing slash is a final `.`:
* an existing name in front of it has to be a directory too (`cat reg/`); a
* call that creates that name (`creates`: mkdir, symlink) answers EEXIST
* instead (`mkdir reg/`), however the store keeps the name.
*
* Only the path the spelling names is walked: a path derived from it (a
* child a walker builds, a respelled match) carries the field along but no
* longer spells it, while the operand the kernel walk followed through a
* link (`lnk/nope/../f`) still does, which `follow` recognizes. The error
* names the operand as typed and is a DotWalkError, final for every layer
* that re-reads a miss. Mirrors Python's dot_refusal.
*/
export declare function dotRefusal(stat: StatFn, path: PathSpec, follow?: ((path: string) => string) | null, creates?: boolean): Promise<FsError | null>;
export declare function resolveTarget(o: string | PathSpec, cwd: string): PathSpec;
export declare function defaultPaths(paths: PathSpec[], cwd: string): PathSpec[];
//# sourceMappingURL=paths.d.ts.map