import type { RuntimeFiles } from '../../files.ts';
import type { MontyFsBits } from './loader.ts';
import { type Clock } from '../../../utils/clock.ts';
/**
 * Monty's OS callbacks: every path a guest names is the workspace's.
 *
 * This is monty's tier of the interception taxonomy: the engine calls
 * one host callback per operation and takes back a value (or a promise
 * of one) or NOT_HANDLED, which the sandbox raises as the call's
 * default refusal. Every path goes to the file adapter, and nothing is
 * kept aside: structure is open (a listing, whether a name is a
 * directory or a link) and content goes only through the runtime's
 * view (`RuntimeFiles.serves`: the announced mounts and what a link
 * reaches), so a guest lists what a shell lists and reads and writes
 * nothing the view withholds. The python twin answers the same way.
 * Declining is reserved for an operation these callbacks do not implement.
 *
 * Monty hands the callbacks whole-file calls: an open, then reads of the
 * whole file and appends of each new write. So an open applies its
 * mode's effect on the mount (`RuntimeFiles.open`, closed again at once)
 * and nothing else, and each write after it ships only its own bytes.
 *
 * Args:
 *   bits: the loaded engine's callback pieces (NOT_HANDLED sentinel
 *     and the MontyFileHandle an `open` answer must be).
 *   env: the run's environment, readable both ways python's monty
 *     spells it (`os.getenv` and `os.environ`).
 *   files: the execution's file adapter, or null outside a workspace,
 *     where every path is out of view.
 */
export declare class MontyFs {
    private readonly bits;
    private readonly notHandled;
    private readonly fileHandle;
    private readonly env;
    private readonly files;
    /**
     * The workspace's system clock the run starts on, null for the host's:
     * the engine calls back from native code, which the line's binding does
     * not reach.
     */
    readonly clock: Clock | null;
    constructor(bits: MontyFsBits, env: Record<string, string>, files: RuntimeFiles | null);
    private wall;
    readonly handle: (name: string, args: unknown[], kwargs?: Record<string, unknown>) => unknown;
    /** Outside a workspace there is no filesystem: probes answer false, the rest refuse. */
    private unbound;
    private op;
    /**
     * The subtree under `path` in one call, for walk, scandir and glob.
     *
     * One listing per directory, each entry kinded by the stat that
     * listing already made, so a walk costs what `find` costs instead of
     * the three probes per entry monty's default asks. The glob's pattern
     * is only a hint, since monty filters the tree itself. A directory
     * below `path` that will not list reads as empty, as it does on
     * monty's own mounts; a tree past SCAN_MAX_ENTRIES raises
     * RuntimeError, because a walk would swallow an OSError.
     *
     * Args:
     *   path: the directory to scan, or a file to describe.
     *   kwargs: `max_depth` (the deepest level to return, none for the
     *     whole tree) and `follow_symlinks` (descend into linked
     *     directories).
     *   files: the execution's file adapter.
     */
    private scan;
    /**
     * Whether a listed entry is a directory and whether a regular file.
     * The listing's own stat answers for a path in the view, except for a
     * link, whose row is the link's and not what it reaches, and a row the
     * listing could not stat. Those, and every path outside the view, ask
     * the view as `Path.is_dir` would, so a file the view withholds (the
     * history beside the mounts) is not offered as one. A stat that fails
     * leaves the entry neither, CPython's rule inside `os.walk`.
     */
    private kind;
    /**
     * Whether the name plane holds a symlink at `path`, asked through
     * readlink. A refusal the backend did not mean as "no link here"
     * comes out as itself (NOT_A_LINK), which is what CPython's own
     * `Path.is_symlink` does.
     */
    private isLink;
    private open;
    /** Replace a file; the return is python's: characters for text, bytes for bytes. */
    private write;
    /**
     * Send only the appended bytes; monty hands an append nothing else.
     * Re-sending everything written so far turns a write loop quadratic,
     * so a mount with its own append op carries just these bytes, and the
     * adapter falls back to a whole-file write only for the mount without
     * one. The return is python's: characters for text, bytes for bytes.
     */
    private append;
    /**
     * Create a directory, keeping pathlib's flags: `parents` rides through
     * to the backend op, which takes it; `exist_ok` is answered here,
     * since the op has no such argument and backends differ on whether
     * creating an existing directory raises at all. `exist_ok` forgives
     * an existing directory only — a file at the target still raises,
     * pathlib's own rule.
     */
    private mkdir;
}
//# sourceMappingURL=fs.d.ts.map