import { Context } from '@deepseek-ai/cordis'; import { FileSystem, FsTarget, FsInfo, FsPathInfo, FsDirEntry, FsWriteIntent, FsWriteOutcome, FsEditRequest, FsVersion, FsEditOutcome } from '@deepseek-ai/dsh-fs'; type SandboxPolicy = Parameters[4]; /** Configuration for the mirage filesystem backend. */ interface MirageFsConfig { /** Virtual base directory for relative paths. Defaults to `/`. */ cwd?: string; /** Exclusive byte limit on each overwrite-diff side. Defaults to 10 MiB. */ diffBasisMaxBytes?: number; } /** * Mirage-backed implementation of `ctx.fs`. Targets are canonical virtual * paths (namespace symlinks followed), every operation walks the workspace * op door — session grants, admission policies, cache read-through and * post-write invalidation all fire exactly as they do for a shell command — * and `processPath` answers in the same virtual path space the mirage shell * executes in, so the two providers share one execution world. * * One limit worth stating: mirage's op facade takes no `AbortSignal`, so * cancellation is honored at this adapter's own boundaries (before a * dispatch, between listing entries) and not inside a single op. A long * read from a remote backend therefore runs to completion after the * signal fires, and the caller learns of the abort when it returns. */ declare class MirageFileSystem extends FileSystem { static readonly inject: string[]; private fsOps; private readonly cwd; private readonly diffBasisMaxBytes; private readonly locks; constructor(ctx: Context, config?: MirageFsConfig); private ops; private get links(); /** * The same confinement claim `MirageShellExecutor` makes, off the same * fact and for the same reason: with every runtime reaching only the * vfs, a mutation cannot land anywhere but a mount, under its mode. * * The two seams sit over one world, so answering differently here * would let dsh fence a bash write and wave an identical `ctx.fs` * write straight through. */ get sandboxMode(): FileSystem['sandboxMode']; /** * Refuse a mutation the call's sandbox policy does not allow. * * `workspaceRoot` is deliberately not consulted: it is a directory on * the harness's own machine, so containment against it says nothing * about this world. The mounts and their modes are the boundary, and * `read-only` is the one mode that narrows them further. Wording and * code mirror `dsh-fs-sandbox`, so the tool layer renders one denial * marker whichever backend refused. * * @param policy the per-call policy, absent for an unguarded mutation. * @param displayPath the path to name in the refusal. */ private assertMutable; /** * The base a relative path resolves against. * * dsh hands `ctx.fs` either the calling session's cwd or the sandbox * policy's workspace root, and both are directories on the harness's * own machine that name nothing here. Resolving `notes.txt` against * one yields `/Users/.../notes.txt`, which every read then reports as * absent. So a base that is not a directory in this world falls back * to the configured one, the same rule the shell executor applies to * a workdir. * * An absolute path ignores its base, so it never pays for the probe. * * @param path the path being resolved. * @param cwd the caller's base, if any. * @returns the base to resolve against. */ private resolveBase; private normalize; private follow; private withLock; resolve(path: string, opts?: { cwd?: string; signal?: AbortSignal; }): Promise; processPath(target: FsTarget): string; fileUrl(target: FsTarget): string; contains(parent: FsTarget, child: FsTarget): boolean; stat(target: FsTarget, signal?: AbortSignal): Promise; lstat(path: string, opts?: { cwd?: string; }, signal?: AbortSignal): Promise; readText(target: FsTarget, signal?: AbortSignal): Promise; streamText(target: FsTarget, signal?: AbortSignal): Promise>; readBytes(target: FsTarget, signal: AbortSignal | undefined, maxBytes: number): Promise; listDir(target: FsTarget, signal?: AbortSignal): Promise; private dirEntry; writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal, sandboxPolicy?: SandboxPolicy): Promise; private diffBasis; private versionAfterWrite; editText(target: FsTarget, edit: FsEditRequest, expected?: { version: FsVersion; }, signal?: AbortSignal, sandboxPolicy?: SandboxPolicy): Promise; } export { MirageFileSystem as M, type MirageFsConfig as a };