@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
154 lines • 8.22 kB
TypeScript
import type { Context } from '../../config.ts';
import type { FollowOperands, LinkView, MountView } from '../../../view/types.ts';
import type { DispatchFn } from '../../../runtime/types.ts';
import type { FileStat, Limit } from '../../../types.ts';
import { PathSpec } from '../../../types.ts';
import type { ByteSource } from '../../../io/types.ts';
import { type Files } from '../../../workspace/files.ts';
/**
* Where a name stands as lstat reaches it: every link above its final name
* followed, the name itself kept.
*
* The walk the kernel gives a path before a call that does not follow its
* final name, and the key the table files a link under, since every link is
* keyed by its resolved parent. A path ending in a slash resolves whole:
* POSIX reads `dlink/` as `dlink/.`. Throws CycleError on a loop. Mirrors
* Python's link_location.
*/
export declare function linkLocation(links: LinkView, virtual: string): string;
/**
* Where the name an operand was typed as stands, as lstat reaches it.
*
* Every component but the last resolves through the links, as the kernel
* walks any path, so `dl/tl.gz` with `dl` a link to `dir` stands at
* `dir/tl.gz`: the table keys every link by that resolved parent. Null where
* the last component resolves as well, which is a name typed with a trailing
* slash or ending in a dot, and where the walk already failed. Mirrors
* Python's name_location.
*/
export declare function nameLocation(links: LinkView, path: PathSpec, cwd: string): string | null;
/**
* The link standing at the name an operand was typed as, its own row.
*
* The router follows an operand through its link before the command runs,
* which leaves `virtual` at the target and the name in `rawPath`; a command
* that acts on the name itself (cp -P, gzip's O_NOFOLLOW open) asks here.
* Null where no link stands at the name. Mirrors Python's typed_link.
*/
export declare function typedLink(links: LinkView, path: PathSpec, cwd: string): FileStat | null;
/**
* The namespace's links as a command meets a name, and the dispatcher past them.
*
* A link is invisible to every backend, so a command bound to one mount needs
* the links to tell a name that stands on one, and the dispatcher to act where
* the link leads or where it stands: the target may live on any mount, and so
* may the link. Mirrors Python's LinkResolver.
*/
export declare class LinkResolver {
readonly links: LinkView;
readonly dispatch: DispatchFn;
readonly cwd: string;
constructor(links: LinkView, dispatch: DispatchFn, cwd: string);
/** Where the link standing at an operand's name sits, null where no link
* stands there. */
linkAt(path: PathSpec): string | null;
/**
* Whether the link the router followed an operand through is gone.
*
* The router follows every operand before the command runs, so an earlier
* operand that removed the link (`gunzip -f l.gz l.gz`) leaves a later one
* at the old target: GNU opens each name when it reaches it, and finds
* nothing there.
*/
vanished(path: PathSpec): boolean;
/**
* Where a link leads, every link on the way followed. A chain that loops
* throws ELOOP, an error a walker reports as it reports any failed stat.
*/
target(link: string): string;
/** What a name leads to, its stat through the dispatcher, on any mount. */
stat(virtual: string): Promise<FileStat>;
/** A directory's entries through the dispatcher, links among them. */
readdir(virtual: string): Promise<string[]>;
/** A name's own stat through the dispatcher: a link's, not its target's. */
lstat(path: PathSpec): Promise<FileStat>;
/** What a name leads to, read through the dispatcher, which follows it. */
read(virtual: string): AsyncIterable<Uint8Array>;
/** Write a file on the mount that owns the name. */
write(virtual: string, data: ByteSource): Promise<void>;
/** Remove the name itself, a link rather than what it leads to. */
unlink(virtual: string): Promise<void>;
}
/** Whether the mount at `prefix` is the one serving `virtual`; every path is
* where no mount table says otherwise. Mirrors Python's serves. */
export declare function serves(mounts: MountView | undefined, prefix: string, virtual: string): boolean;
/**
* The mount a walked path lands on, every link on it followed. A mount is
* mirage's filesystem, so this stands for the device stat(2) reports, which
* `find -xdev` compares with the start point's: a link onto another mount
* leaves it as a mount root does (findutils 4.10). `virtual` is a directory
* the walk reached, which resolves. Mirrors Python's landing_root.
*/
export declare function landingRoot(mounts: MountView, links: LinkView | null, virtual: string): string;
/**
* The symlink facts a walk goes by, read off the session's files, or
* undefined outside a workspace.
*
* The dispatcher's reader answers (`NamespaceReader`), filtered by the rule
* it refuses a call by: a hidden link, or one that leads where the session
* cannot see, has no row, no listing entry and no target. Resolving a hidden
* path leaves it as typed, for the dispatcher to refuse; a visible one
* resolves, so a walker judges where it lands. Mirrors Python's link_view.
*/
export declare function linkView(files: Files | undefined): LinkView | undefined;
/**
* Where the mount boundaries are, read off the session's files, or undefined
* outside a workspace. Every mount below a path, hidden or not, is a boundary
* a backend's own walk stops at; only the visible ones are ever named. A walk
* through the dispatcher (`crossing`) has no boundary to stop at
* (`NamespaceReader.mounts`). Mirrors Python's mount_view.
*/
export declare function mountView(files: Files | undefined, crossing?: boolean, command?: string | null, profile?: Readonly<Record<string, Limit>>): MountView | undefined;
/**
* The names a directory holds only as namespace structure, as the session
* sees them: the mounts below it and its links, each by its first segment
* under the directory.
*
* No backend can list either, and the first may be one no backend serves at
* all (a link made below a directory chain that holds no key); these are the
* names the dispatcher merges into its own listing, from the same tables.
* Mirrors Python's owed_names.
*/
export declare function owedNames(files: Files | undefined, directory: string): string[];
/** The workspace's links as the command's session sees them, read off its
* files; undefined outside a workspace. Mirrors Python's links_of. */
export declare function linksOf(ctx: Context): LinkView | undefined;
/**
* Whether the command walks across mounts: it runs on the session's files
* with no mount's command scope bound, as a cross-mount run does, so every
* call it makes reaches whichever mount serves the path. Mirrors Python's
* crosses_mounts.
*/
export declare function crossesMounts(ctx: Context): boolean;
/**
* The prefix of the mount the command runs on, without its trailing slash:
* what a path the command makes up (an output name, a file a list names) is
* keyed below. '' for a run across mounts, which keys every path by its
* whole virtual path, and outside a workspace. Mirrors Python's mount_root.
*/
export declare function mountRoot(ctx: Context): string;
/**
* Where the mount boundaries are for the command's walk, read off its files;
* undefined outside a workspace. A run across mounts (`crossesMounts`) has
* the dispatcher descend into every mount, so it has no boundary to stop at.
* Mirrors Python's mounts_of.
*/
export declare function mountsOf(ctx: Context): MountView | undefined;
/** The link resolver an invocation carries: null outside a workspace.
* Mirrors Python's link_resolver. */
export declare function linkResolver(ctx: Context): LinkResolver | null;
/** The dispatcher a command's files run on. Mirrors Python's dispatch_of. */
export declare function dispatchOf(ctx: Context): DispatchFn | undefined;
/** The line's operand resolution its files carry. Mirrors Python's follow_of. */
export declare function followOf(ctx: Context): FollowOperands | undefined;
//# sourceMappingURL=links.d.ts.map