/** * Reading the workspace: a tree to browse, and a file to look at. * * Every path arrives from a URL, so every path is resolved and checked against the workspace root * before anything is opened. That check is the whole of this module's security, and it is done once * in one function rather than at each call site — `..` is the obvious attack and a symlink pointing * out of the tree is the one that gets forgotten, so the resolved real path is what gets compared. * * Read-only. Editing from the browser is a different feature with a different risk, and mixing the * two would mean a traversal bug wrote instead of leaked. */ /** A file this size is shown by its head, because nothing reads a megabyte in a browser panel. */ export declare const MAX_VIEW_BYTES: number; /** Entries per directory. A folder with ten thousand files is not a tree to browse. */ export declare const MAX_ENTRIES = 500; export interface TreeEntry { name: string; /** Relative to the workspace root, always with forward slashes. */ path: string; dir: boolean; size: number; mtimeMs: number; } /** * The resolved absolute path, or null when it would leave the workspace. * * Symlinks are resolved first, so a link inside the workspace pointing at /etc is caught. A path * that does not exist yet cannot be realpath'd, so the parent is resolved instead and the last * segment appended — which is what a browser asking for a file it saw a moment ago needs. */ export declare function resolveInside(root: string, rel: string): Promise; /** One directory, folders first then files, both alphabetical. */ export declare function listDir(root: string, rel?: string): Promise; export interface FileView { path: string; size: number; text: string | null; truncated: boolean; binary: boolean; /** When it was last written, so a save can tell whether it moved on since. */ mtimeMs: number; } /** One file, as text where that means anything. */ export declare function viewFile(root: string, rel: string): Promise; /** * Writing a file back. * * The Files tab could open a file and not change it, which makes it a viewer. Editing a line and * saving is the smallest useful thing a person does to a file, and going through the agent to do * it — asking a model to please change one character — is slower, less certain, and costs tokens. * * Guarded by what was read rather than by a lock. The agent may be writing the same file while it * is open in a browser tab, and a save that silently discarded the agent's work would be worse than * refusing: so a save carries the size and modification time it was opened with, and a file that * has moved on since is reported instead of overwritten. Cheap, and it cannot be wrong in the * direction that loses work. */ export interface SaveOutcome { ok: boolean; error?: string; /** Set when the file changed under the editor, so the interface can offer to reload. */ stale?: boolean; size?: number; mtimeMs?: number; } /** A file is not editable here past this, because the editor was never given all of it. */ export declare const MAX_EDIT_BYTES: number; export declare function saveFile(root: string, rel: string, text: string, expect?: { size?: number; mtimeMs?: number; }): Promise; //# sourceMappingURL=files.d.ts.map