@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
720 lines • 31.2 kB
TypeScript
export type JsonValue = null | boolean | number | string | JsonValue[] | {
[k: string]: JsonValue;
};
export type PageFetch = (cursor: string | null) => Promise<Record<string, unknown>>;
/**
* What a mount lets commands do, a cumulative ladder. READ lists and
* reads. WRITE also creates, changes and deletes. EXEC also lets the
* interpreter commands (python3, js) run code: a script file named as
* their operand must sit on an EXEC mount, while inline code and -m need
* one somewhere in the workspace (imports are not checked by path).
* Shell scripts need no EXEC, since the shell checks each of their
* commands like a typed one; a ./script whose shebang names python3
* reaches python3, which does check.
*/
export declare const MountMode: Readonly<{
readonly READ: "read";
readonly WRITE: "write";
readonly EXEC: "exec";
}>;
export type MountMode = (typeof MountMode)[keyof typeof MountMode];
/**
* How a mount is exposed to the outside world.
*
* `workspace` is the default: the mount lives only inside mirage's own filesystem
* and is reached through the command surface, with nothing registered with
* the kernel. `fuse` and `fskit` additionally expose it as a real mountpoint.
*
* `fskit` is macOS 15.4+ only and needs no kernel extension. It has no
* `direct_io` equivalent, so it serves correct reads only for mounts that
* set `sizesAlwaysKnown`; the mount-time guard warns about mounts whose
* size-unknown files will read as empty. Writes are also limited: appends and
* metadata ops persist, but the macFUSE FSKit shim flushes pages a file did
* not already have (a new file, or truncate-then-write) as NUL bytes (pinned
* in `integ/fuse/truth_fskit.json`). There is deliberately no `auto`:
* auto-selecting fskit would silently degrade every API-backed mount.
*
* `nfs` mounts through the operating system's own NFS client, so nothing is
* installed: mirage serves NFSv3 on a local port and runs the system `mount`.
* Linux and macOS; Linux needs root to mount. It is read-only for now, and
* like fskit it reads only as far as the size a file reports, so it serves
* mounts that set `sizesAlwaysKnown`.
*/
export declare const MountBackend: Readonly<{
readonly WORKSPACE: "workspace";
readonly FUSE: "fuse";
readonly FSKIT: "fskit";
readonly NFS: "nfs";
}>;
export type MountBackend = (typeof MountBackend)[keyof typeof MountBackend];
/** Backends that register a real mountpoint with the kernel. */
export declare const KERNEL_BACKENDS: readonly MountBackend[];
export declare const MOUNT_MODE_RANK: Readonly<Record<MountMode, number>>;
/** The weaker of two mount modes on the READ < WRITE < EXEC lattice. */
export declare function weakerMode(a: MountMode, b: MountMode): MountMode;
/**
* What the dispatcher treats as nonexistent for one session.
*
* A sibling of `SessionState.mountModes`: per-session narrowing that the
* entry points enforce, null-on-the-session means unrestricted. Hiding is
* "does not exist", never "forbidden" — matching paths answer ENOENT
* and drop out of listings, which is what makes a hide the way a profile
* keeps a session away from a mount: naming mounts only narrows their
* modes, and a refusal would hand back the name.
*
* `paths` are exact virtual paths; hiding a path hides its whole
* subtree (a name you cannot see cannot be a parent you traverse), so
* a mount root entry hides the mount. `patterns` are globs: one with
* no `/` matches any single name component anywhere; one containing
* `/` is anchored to the full virtual path, with `*` crossing slashes
* exactly as GNU `find -path` does.
*/
export interface HiddenPaths {
readonly paths?: readonly string[];
readonly patterns?: readonly string[];
}
/**
* One `show` entry of a profile's path axis, compiled.
*
* `path` is the entry as written: an exact subtree or an anchored
* pattern, always absolute (a slashless name pattern is refused at
* validation, because a show anchors to a place and a name pattern
* names none). `mode` is what the entry states for its subtree; null
* for a list-form entry, which inherits the mount's.
*/
export interface ShowEntry {
readonly path: string;
readonly mode: MountMode | null;
}
/**
* The `show` half of one session's path axis.
*
* A sibling of `HiddenPaths`: per-session state the entry points read,
* null-on-the-session means the document states no show. An entry does
* two things, each on the one anchor-depth rule: it re-opens a subtree
* inside a hidden region when its anchor is deeper than the hide's,
* and it states the mode in force below its anchor when it carries
* one.
*/
export interface ShownPaths {
readonly entries: readonly ShowEntry[];
}
/**
* What the session view treats as unset for one session.
*
* Enforced where env leaves the session: `get` misses, `snapshot`
* omits, expansion sees unset. Field names differ from `HiddenPaths`
* on purpose — the planes' matching semantics differ, so the specs
* are not interchangeable.
*/
export interface HiddenVars {
readonly names?: readonly string[];
readonly patterns?: readonly string[];
}
export type ProcessScope = 'session' | 'workspace';
/**
* What exists for one session, compiled once from its profile.
*
* The one answer to "is this here?" for everything a session touches:
* paths (hides, re-opened by deeper shows), variables and processes.
* The views filter what they list through it and the op
* boundary answers a hidden path as absent from it; nothing else asks
* the profile what exists. `DEFAULT_VISIBILITY` hides nothing.
*
* `shown` re-opens a hidden subtree and states a subtree's mode;
* `processes` is whose processes the session sees.
*/
export interface Visibility {
readonly paths: HiddenPaths | null;
readonly shown: ShownPaths | null;
readonly vars: HiddenVars | null;
readonly processes: ProcessScope;
}
export declare const DEFAULT_VISIBILITY: Visibility;
/**
* Coerce a mount mode, accepting cumulative filesystem aliases.
*
* The mode ladder is cumulative (exec implies write implies read), so
* only the cumulative spellings `r`, `rw`, `rwx` alias the modes;
* bit-style forms like `w` or `x` are rejected.
*/
export declare function parseMountMode(value: string): MountMode;
/**
* How a mount decides whether cached bytes may be served.
*
* FRESH revalidates against the backend's content token before serving a
* cached copy; BOUNDED serves without revalidating, within the staleness
* bound the mount declares.
*
* PINNED names the content a commit's fingerprint records. There is no
* version layer to pin to, so a mount declaring it is refused at mount time
* rather than quietly degraded to head: the vocabulary is published, so
* someone will type it, and an informative refusal costs one branch over a
* generic invalid-value error.
*/
export declare const ReadPolicy: Readonly<{
readonly FRESH: "fresh";
readonly BOUNDED: "bounded";
readonly PINNED: "pinned";
}>;
export type ReadPolicy = (typeof ReadPolicy)[keyof typeof ReadPolicy];
/**
* Whether replacements carry the version they were based on. Unconditional
* existing-file rewrites are last-write-wins. Shared rewrites that observed
* a missing file require atomic create-only under either policy.
* Conditional writes also protect the version the mount last saw. Staged
* names a staging layer not implemented here and is refused at mount time.
* Mirrors Python's `WritePolicy`.
*/
export declare const WritePolicy: Readonly<{
readonly UNCONDITIONAL: "unconditional";
readonly CONDITIONAL: "conditional";
readonly STAGED: "staged";
}>;
export type WritePolicy = (typeof WritePolicy)[keyof typeof WritePolicy];
/**
* What a backend's cached listings can be checked against under fresh.
*
* NONE: nothing, so a listing the running command did not write itself is
* listed again. MOUNT: one version covers every listing of the mount, and a
* stat of the mount root answers it. FOLDER: each listing carries its own
* folder's version, and a stat of that folder answers it. The stored version
* and the stat's fingerprint must be the same kind of token, since the gate
* compares them with `===`.
*/
export declare const ListingVersion: Readonly<{
readonly NONE: "none";
readonly MOUNT: "mount";
readonly FOLDER: "folder";
}>;
export type ListingVersion = (typeof ListingVersion)[keyof typeof ListingVersion];
/** Maximum lifetime in seconds for cached bodies and listings. */
export declare const DEFAULT_READ_TTL = 600;
/**
* One mount's read policy and the bound that goes with it.
*
* The bound is set under FRESH too, so every cache entry carries one. Two
* workspaces sharing one Redis cache under different policies would otherwise
* write entries the other refuses to serve, and bounce them between cold reads
* indefinitely.
*
* It is stamped when the entry is written and enforced by the store, so the
* bound that applies is the writing mount's, not the reading mount's. Those are
* the same mount inside one workspace; they differ across a shared cache, a
* lowered `ttl` and a restored snapshot, and there the older bound stands until
* the entry expires. Making the reader authoritative needs a write timestamp
* every store can read back, which redis does not keep.
*/
export interface ReadSpec {
readonly policy: ReadPolicy;
readonly ttl: number;
}
/**
* The policy a mount takes when it declares none, and the one pinned onto the
* three synthetic anchors (`/dev`, the history view, the implicit `/` root).
*
* Those three are installed outside `normalizeMounts`, so they never meet the
* capability verdict; none of them caches reads, so inheriting a workspace-level
* `fresh` would stamp on them exactly the combination the verdict refuses.
*/
export declare const DEFAULT_READ_SPEC: ReadSpec;
/**
* What the cache write path needs to know about a path's mount.
*
* Answered per path against the mount table pinned at command start, so a
* fill that lands after the command is stamped with the bound of the mount
* that produced the bytes rather than whatever holds the prefix by then.
* `cacheable` is read first and short-circuits, so `ttl` is never consulted
* for a path that is not being cached.
*/
export interface CacheFacts {
readonly cacheable: boolean;
readonly ttl: number;
/** Whether the mount's writes are conditional, so a line keeps a path's version even where it keeps no bytes. */
readonly keepsVersions?: boolean;
}
/**
* Behaviour when a remote VFS's live fingerprint differs from the
* value recorded at snapshot time.
*/
export declare const DriftPolicy: Readonly<{
/** Raise ContentDriftError on first mismatch. */
readonly STRICT: "strict";
/** Skip drift checks entirely. */
readonly OFF: "off";
}>;
export type DriftPolicy = (typeof DriftPolicy)[keyof typeof DriftPolicy];
/**
* Behaviour when a command's output exceeds its limit cap.
* TRUNCATE returns the truncated bytes + a notice on stderr.
* ERROR returns no stdout and exits 1 with the same notice.
*/
export declare const OnExceed: Readonly<{
readonly ERROR: "error";
readonly TRUNCATE: "truncate";
}>;
export type OnExceed = (typeof OnExceed)[keyof typeof OnExceed];
/**
* A bound on a result: the policy layer's limit arm and the shape
* every cap config parses into. Carries its fields inline (the Deny
* precedent: an action is its payload). `kind` is the wire
* discriminant; `aggr` is the composition law (AND to the tightest
* per bound, ANY on error mode) and `layered` the resolution law (each
* field from the most specific layer that sets it). `walkLimit` caps the
* entries one walk lists on a mount, -1 for no cap.
*/
export declare class Limit {
readonly kind: "limit";
readonly maxBytes: number | null;
readonly maxLines: number | null;
readonly timeoutSeconds: number | null;
readonly walkLimit: number | null;
/** The fields the limit names, null among them; the rest inherit. Mirrors Python's model_fields_set. */
readonly fieldsSet: ReadonlySet<keyof NonNullable<ConstructorParameters<typeof Limit>[0]>>;
private readonly exceed;
constructor(init?: Partial<Pick<Limit, 'maxBytes' | 'maxLines' | 'timeoutSeconds' | 'walkLimit' | 'onExceed'>>);
get onExceed(): OnExceed;
/**
* Each field from the first limit that names it, most specific first: a
* layer naming one bound inherits the others from the layers below it, and
* one naming a bound as null lifts it. Returns null when nothing is
* configured. Mirrors Python's Limit.layered.
*/
static layered(limits: Iterable<Limit | null>): Limit | null;
private named;
/**
* Aggregate several limits using each field's declared rule.
*
* Reads the rules off LIMIT_AGGR rather than naming the fields here, so a
* new bound composes as soon as it is declared — the same property Python
* gets from walking `model_fields` for each field's `Aggr(rule)`. Returns
* null when nothing is configured. Used wherever bounds stack (policy
* composition, cross-mount fan-out, layered configs).
*/
static aggr(limits: Iterable<Limit | null>): Limit | null;
}
/**
* Provenance of a result: who produced it, and where.
*
* Rides the IO envelope from the dispatch site to the workspace
* boundary; merge keeps the rightmost producer, so this names the
* last command that ran; it does not describe every byte of a list. Post-layer policies
* (output caps today; budgets and attribution later) read it as
* context. Facts only: no policy reads a decision off the envelope;
* the one a chain hands down is written beside it as
* `IOResult.refusal` after the last method has spoken. `declared` is
* the bound the command's own registration declared,
* when the dispatch site knows it (e.g. a CLI leaf). `native` is set when
* a native program a runtime runs produced it, writing as it goes, so a
* redirect writes it as it arrives.
*/
export interface Producer {
readonly command: string;
readonly prefixes: readonly string[];
readonly declared: Limit | null;
readonly native?: boolean;
}
export type RefusalKind = 'deny' | 'pending' | 'failed';
/**
* Why a line did not run, for the caller that reads the result.
*
* stderr keeps bash's voice (`<cmd>: Permission denied`), which says
* nothing about who refused or why; this record carries that beside
* the envelope, so a host or an agent adapter can show the reason
* without the shell having to. null on every run that was not
* refused, and absent on the 127 `command not found` row, which must
* not reveal that the word names anything. `kind` is `deny` for a
* policy's refusal, `pending` for an ask the host has not answered,
* `failed` for a policy that raised and so refused by default;
* `policy` is the class name of the policy that spoke, empty for an
* ask, which belongs to the host; `askId` is the approval to quote,
* for `pending`. Mirrors the Python `Refusal`.
*/
export interface Refusal {
readonly kind: RefusalKind;
readonly reason: string;
readonly policy: string;
readonly askId: string | null;
}
export declare const VFSName: Readonly<{
readonly DISK: "disk";
readonly S3: "s3";
readonly RAM: "ram";
readonly GITHUB: "github";
readonly WANDB: "wandb";
readonly LINEAR: "linear";
readonly GCAL: "gcal";
readonly GDOCS: "gdocs";
readonly GSHEETS: "gsheets";
readonly GSLIDES: "gslides";
readonly GDRIVE: "gdrive";
readonly ONEDRIVE: "onedrive";
readonly SHAREPOINT: "sharepoint";
readonly DROPBOX: "dropbox";
readonly BOX: "box";
readonly AIRTABLE: "airtable";
readonly SLACK: "slack";
readonly DISCORD: "discord";
readonly GMAIL: "gmail";
readonly TRELLO: "trello";
readonly MONGODB: "mongodb";
readonly GRIDFS: "gridfs";
readonly NOTION: "notion";
readonly LANGFUSE: "langfuse";
readonly JAEGER: "jaeger";
readonly SSH: "ssh";
readonly REDIS: "redis";
readonly GCS: "gcs";
readonly OCI: "oci";
readonly R2: "r2";
readonly EMAIL: "email";
readonly OPFS: "opfs";
readonly SUPABASE: "supabase";
readonly POSTGRES: "postgres";
readonly LANCEDB: "lancedb";
readonly CHROMA: "chroma";
readonly DIFY: "dify";
readonly MEM0: "mem0";
readonly QDRANT: "qdrant";
readonly HF_BUCKETS: "hf_buckets";
readonly HF_DATASETS: "hf_datasets";
readonly HF_MODELS: "hf_models";
readonly HF_SPACES: "hf_spaces";
readonly NEXTCLOUD: "nextcloud";
readonly DATABRICKS_VOLUME: "databricks_volume";
readonly TIDB_FILESYSTEM: "tidb_filesystem";
readonly MINIO: "minio";
readonly CEPH: "ceph";
readonly SEAWEEDFS: "seaweedfs";
readonly WASABI: "wasabi";
readonly BACKBLAZE: "backblaze";
readonly DIGITALOCEAN: "digitalocean";
readonly TENCENT: "tencent";
readonly ALIYUN: "aliyun";
readonly SCALEWAY: "scaleway";
readonly QINGSTOR: "qingstor";
readonly HISTORY: "history";
readonly BIN: "bin";
}>;
export type VFSName = (typeof VFSName)[keyof typeof VFSName];
/**
* POSIX file type (the `st_mode` kind), the switch behavior branches on.
*
* One per entry, always present. Directory and symlink are their own
* kinds; every regular file is FILE and carries its content shape on
* `FileStat.content`. Distinct from ContentType, which is only a
* rendering hint for a FILE. Mirrors `FileType` in `mirage/types.py`.
*
* The full POSIX set is enumerated so the model is comprehensive.
* DIRECTORY, FILE, SYMLINK, CHAR_DEVICE (the /dev mount) and FIFO (a
* process substitution's /dev/fd/N) are produced today; BLOCK_DEVICE and
* SOCKET are declared but not yet emitted, and the render/derivation tables
* (find letter, st_mode bits, ls char) grow a row for one the moment a
* backend starts producing it.
*/
/** `ls` sort keys: name is the default, time `-t`, size `-S`, version
* `-v`, extension `-X`, width `--sort=width`, and none `-U`. */
export type LsSortBy = 'name' | 'time' | 'size' | 'version' | 'extension' | 'width' | 'none';
/** Which timestamp `ls` shows and sorts by: `-u`/`--time=atime`,
* `-c`/`--time=ctime`, `--time=birth`, else the modification time. */
export type LsTimeKind = 'mtime' | 'atime' | 'ctime' | 'birth';
export type LsIndicator = 'none' | 'slash' | 'file-type' | 'classify';
export type CopyDeref = 'always' | 'command_line' | 'never';
export type LsLinkMode = 'all' | 'directory' | 'none';
/**
* How a command resolves a command-line operand's last component when it is
* a symlink: never (lstat(2): `rm`, `stat`), always (open(2): `cat`,
* `stat -L`), or only once a stat shows it leads to a directory (`ls` with no
* option that settles it).
*/
export declare const Follow: Readonly<{
readonly NONE: "none";
readonly LAST: "last";
readonly DIRECTORY: "directory";
}>;
export type Follow = (typeof Follow)[keyof typeof Follow];
/**
* What one command line does, as its own command reads its options: the
* admission gate, the router and the fan-out ask this instead of reading the
* options themselves. `follows` is how its operands' last component
* resolves; `walks` that its traversal enters the mounts below its operands
* (`find`, `du`, `grep -r`; not `du -x`); `readsSubtree` that it reads below
* the paths it names, whether or not it crosses a mount (`du -x`, `tar -c`,
* `cp -r`); `writes` that it may change files, false only when its options
* leave a writing command nothing to change (`sort` without `-o`, `tar -t`);
* `subtree` that an operand is a whole subtree it moves or removes (`rm`,
* `rmdir`, `mv`); `moveTarget` the directory a move names by option
* (`mv -t DIR`), as typed, null when it names none. Mirrors Python's
* `LineFacts`.
*/
export declare class LineFacts {
readonly follows: Follow;
readonly walks: boolean;
readonly readsSubtree: boolean;
readonly writes: boolean;
readonly subtree: boolean;
readonly moveTarget: string | null;
constructor(init?: Partial<Omit<LineFacts, 'with'>>);
/** A copy with some fields replaced, the mirror of Python's `dataclasses.replace`. */
with(update: Partial<Omit<LineFacts, 'with'>>): LineFacts;
}
export declare const FileType: Readonly<{
readonly DIRECTORY: "directory";
readonly FILE: "file";
readonly SYMLINK: "symlink";
readonly CHAR_DEVICE: "char_device";
readonly BLOCK_DEVICE: "block_device";
readonly FIFO: "fifo";
readonly SOCKET: "socket";
}>;
export type FileType = (typeof FileType)[keyof typeof FileType];
/**
* A regular file's content shape: the rendering hint (file/ls color).
*
* Only meaningful for a FILE; a directory or symlink carries none. Not a
* node kind: nothing branches control flow on it. Mirrors `ContentType`
* in `mirage/types.py`.
*/
export declare const ContentType: Readonly<{
readonly TEXT: "text";
readonly BINARY: "binary";
readonly JSON: "json";
readonly CSV: "csv";
readonly IMAGE_PNG: "image/png";
readonly IMAGE_JPEG: "image/jpeg";
readonly IMAGE_GIF: "image/gif";
readonly ZIP: "application/zip";
readonly GZIP: "application/gzip";
readonly PDF: "application/pdf";
}>;
export type ContentType = (typeof ContentType)[keyof typeof ContentType];
export declare const LINK_TARGET_KEY = "link_target";
export declare const DEVICE_NUMBERS_KEY = "device_numbers";
export declare const LIVE_KEY = "mirage.live";
/**
* The metadata fields a `setattr` writes, all optional.
*
* Spelled the way the op, the Context bag and the guest bridge
* spell them, so one fact keeps one name from a shell line down to a
* guest's utime. `nofollow` is not a field but the AT_SYMLINK_NOFOLLOW
* bit: it writes the link entry's own attrs rather than its target's.
* Lives here rather than beside either consumer because `ws.vfs`
* and the runtime bridge both take it and neither may import the
* other.
*/
export interface SetAttrFields {
mode?: number;
uid?: number | string;
gid?: number | string;
atime?: string;
mtime?: string;
nofollow?: boolean;
}
export declare class FileStat {
readonly name: string;
readonly size: number | null;
readonly modified: string | null;
readonly fingerprint: string | null;
readonly revision: string | null;
readonly type: FileType;
readonly content: ContentType | null;
readonly mode: number | null;
readonly uid: number | string | null;
readonly gid: number | string | null;
readonly atime: string | null;
readonly ctime: string | null;
readonly birthtime: string | null;
readonly dev: number | null;
readonly extra: Record<string, unknown>;
constructor(init: Pick<FileStat, 'name' | 'type'> & Partial<Pick<FileStat, 'size' | 'modified' | 'fingerprint' | 'revision' | 'content' | 'mode' | 'uid' | 'gid' | 'atime' | 'ctime' | 'birthtime' | 'dev' | 'extra'>>);
with(update: Partial<NonNullable<ConstructorParameters<typeof FileStat>[0]>>): FileStat;
}
/**
* A directory's listing as a backend answers it, when one fetch proves more
* than the directory's own children.
*
* A backend's `readdir` answers a plain list of its children's stats, or this
* when the fetch says more: a day of messages that also lists its `files/`
* subdirectory, a board whose lists come with their cards. The dispatcher
* keeps every listing it is handed, so entering a seeded directory costs no
* second identical fetch.
*
* - `entries`: the listed directory's own children, each filled in as `stat`
* would fill it.
* - `seeds`: descendant listings the same fetch proved, keyed by path relative
* to the listed directory (`files`, `2026-01-05/Report__17`).
* - `partial`: the entries are a filtered or truncated view (a glob the
* backend narrowed, a fetch it did not finish), so they are kept as entries
* but not as the directory's listing. `seeds` stay full listings of the
* children it did report.
* - `window`: the fetch was capped (the newest N messages, the last N days),
* so the entries are everything to show but prove nothing absent: a child
* that drops out of the window has not been deleted. Kept as listings that
* evict nothing.
* - `version`: the version the listing was read at, for a backend that
* declares a `listingVersion`; a `fresh` mount checks it before serving the
* listing again.
*/
export declare class DirListing {
readonly entries: readonly FileStat[];
readonly seeds: ReadonlyMap<string, readonly FileStat[]>;
readonly partial: boolean;
readonly window: boolean;
readonly version: string | null;
constructor(init: {
entries: readonly FileStat[];
seeds?: ReadonlyMap<string, readonly FileStat[]>;
partial?: boolean;
window?: boolean;
version?: string | null;
});
}
export declare const FileChangeKind: Readonly<{
readonly CREATE: "create";
readonly UPDATE: "update";
readonly DELETE: "delete";
readonly MOVE: "move";
readonly UNKNOWN: "unknown";
}>;
export type FileChangeKind = (typeof FileChangeKind)[keyof typeof FileChangeKind];
export declare class FileMetadata {
readonly fingerprint: string | null;
readonly size: number | null;
readonly modified: string | null;
constructor(init?: Partial<Pick<FileMetadata, 'fingerprint' | 'size' | 'modified'>>);
}
export declare class FileEvent {
readonly kind: FileChangeKind;
readonly path: PathSpec;
readonly timestamp: Date;
readonly previousPath: PathSpec | null;
readonly metadata: FileMetadata | null;
constructor(init: Pick<FileEvent, 'kind' | 'path' | 'timestamp'> & Partial<Pick<FileEvent, 'previousPath' | 'metadata'>>);
}
export declare class Delta {
readonly changes: readonly FileEvent[];
readonly checkpoint: string | null;
constructor(init: Pick<Delta, 'changes' | 'checkpoint'>);
}
export declare const OverflowPolicy: Readonly<{
readonly COLLAPSE: "collapse";
readonly DROP_OLDEST: "drop_oldest";
readonly ERROR: "error";
}>;
export type OverflowPolicy = (typeof OverflowPolicy)[keyof typeof OverflowPolicy];
export declare const CapacityState: {
readonly QUOTA: "quota";
readonly ELASTIC: "elastic";
readonly NA: "na";
readonly UNKNOWN: "unknown";
};
export type CapacityState = (typeof CapacityState)[keyof typeof CapacityState];
export interface CapacityResult {
state: CapacityState;
total?: number | null;
used?: number | null;
available?: number | null;
inodes?: number | null;
inodesUsed?: number | null;
inodesFree?: number | null;
}
export type ReadStreamFn<Args extends unknown[] = [path: PathSpec]> = (...args: Args) => AsyncIterable<Uint8Array>;
export type CopyFn<Args extends unknown[] = [src: PathSpec, target: PathSpec]> = (...args: Args) => Promise<void>;
export type MoveFn<Args extends unknown[] = [src: PathSpec, target: PathSpec]> = (...args: Args) => Promise<void>;
/** Native copy only asks for files or directories; backend ops supply their full arguments. */
export type FindFn<Args extends unknown[] = [src: PathSpec, options: {
type: 'f' | 'd';
unreadable?: string[];
}]> = (...args: Args) => Promise<string[]>;
export type ReaddirFn<Args extends unknown[] = [path: PathSpec]> = (...args: Args) => Promise<string[]>;
export type StatFn<Args extends unknown[] = [path: PathSpec]> = (...args: Args) => Promise<FileStat>;
/**
* What proving a running command's `.` and `..` reads.
*
* The command tier reaches its backend past the dispatcher, so
* `Mount.runCommand` binds the dispatcher's facts for it: `stat` is the dispatcher's
* stat (throwing when nothing is there) and `follow` the namespace's link
* resolution, null while it holds none. The kernel walk (`followPaths`)
* rewrites an operand to its link's target before the handler runs;
* `follow` is how that operand is still known for the one its dotted
* spelling names. Mirrors Python's WalkProbe.
*/
export interface WalkProbe {
readonly stat: StatFn;
readonly follow: ((path: string) => string) | null;
}
export interface NativeCopy {
copy: CopyFn;
find: FindFn;
dirCopy?: CopyFn;
/**
* Lets the per-entry policy path (--update/--backup, which cannot use a
* whole-tree dirCopy) still materialize directories that hold no files.
*/
mkdir?: CopyFn<[path: PathSpec]>;
}
export interface PrimitiveCopy {
read: ReadStreamFn;
write: CopyFn<[target: PathSpec, data: Uint8Array | AsyncIterable<Uint8Array>]>;
mkdir: CopyFn<[path: PathSpec]>;
readdir: ReaddirFn;
/** A store-to-store copy between two mounts, tried before the bytes move;
* EXDEV or ENOTSUP from it says the stores cannot. */
copy?: CopyFn;
}
export type CopyStrategy = NativeCopy | PrimitiveCopy;
export interface NativeMove {
rename: MoveFn;
}
export interface PrimitiveMove {
read: ReadStreamFn;
write: MoveFn<[target: PathSpec, data: Uint8Array | AsyncIterable<Uint8Array>]>;
mkdir: MoveFn<[path: PathSpec]>;
readdir: ReaddirFn;
unlink: MoveFn<[path: PathSpec]>;
rmdir: MoveFn<[path: PathSpec]>;
/** Throws when the source's mount cannot condition its delete. */
checkUnlink?: (path: PathSpec) => void;
copy?: CopyFn;
}
export type MoveStrategy = NativeMove | PrimitiveMove;
/** A resource query and backend-specific arguments, validated by the backend. */
export interface SearchQuery {
readonly query: string;
readonly options?: Readonly<Record<string, JsonValue>>;
}
export type WalkErrno = 'ENOENT' | 'ELOOP';
export declare class PathSpec {
readonly virtual: string;
readonly directory: string;
readonly vfsPath: string;
readonly pattern: string | null;
readonly resolved: boolean;
readonly rawPath: string;
readonly dotted: string | null;
readonly walkError: WalkErrno | null;
constructor(init: Pick<PathSpec, 'virtual' | 'directory' | 'vfsPath'> & Partial<Pick<PathSpec, 'pattern' | 'resolved' | 'rawPath' | 'dotted' | 'walkError'>>);
get mountPath(): string;
get dir(): PathSpec;
child(name: string): string;
/** Join components for workspace dispatch, preserving the unproven walk. */
join(...parts: string[]): PathSpec;
/** Lexical parent with its spelled ancestors, for workspace dispatch. */
get parent(): PathSpec;
/**
* Wrap a resolved path, or resolve a supplied spelling against cwd.
* Existing specs retain their metadata; vfsPath can override the backend key.
* Supply cwd for relative strings, dotted walks and inherited walk errors;
* omit it for an already resolved virtual path.
*/
static fromStrPath(path: string | PathSpec, vfsPath?: string, cwd?: string | PathSpec): PathSpec;
}
export declare function wordText(word: string | PathSpec): string;
/** A JSON object received from a service, before its fields are checked. */
export type JsonObject = Record<string, unknown>;
/** An optional byte range requested by a file read. */
export interface ReadRange {
offset?: number;
size?: number;
}
//# sourceMappingURL=types.d.ts.map