UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

72 lines • 4.48 kB
import type { Accessor } from '../../accessor/base.ts'; import type { FileStat, PathSpec } from '../../types.ts'; import { type DetectFn, type ScopeMatch } from './scope.ts'; export type Reader<A extends Accessor> = (accessor: A, match: ScopeMatch, path: PathSpec, entry: FileStat | null, parent: FileStat | null) => Promise<Uint8Array>; export interface ReadWindow { limit?: number | null; offset?: number | null; } export type WindowedReader<A extends Accessor> = (accessor: A, match: ScopeMatch, path: PathSpec, entry: FileStat | null, parent: FileStat | null, window: ReadWindow) => Promise<Uint8Array>; export interface HierarchyReadOptions<A extends Accessor> { /** * Readers for kinds whose content is windowed at the source (postgres rows * take a row limit/offset the backend pushes into the query); they receive * the caller's window, which every plain reader ignores, matching a * filesystem read that has no row notion. */ windowed?: Readonly<Record<string, WindowedReader<A>>>; /** * Every read first proves the file's parent directory exists, by the row * its listing names, so a container the listing refuses reads as absent * exactly as `ls` and `stat` report it. A backend whose readers address the * API by the ids in the path asks for it: without it, `cat` of a board * outside `boardIds` fetched that board by its id. The file itself stays * the reader's to prove, since a bounded listing need not name every file * that exists. */ parented?: boolean; } /** Proves the matched entity exists before its answer runs. */ export type Guard<A extends Accessor> = (accessor: A, match: ScopeMatch, virtual: string) => Promise<void>; /** * Build a call only some file kinds answer: classify, guard, dispatch, null * for the rest. * * The line calls (`firstLines`, `lastLines`, `lineCount`, `follow`) are * answered for a backend's data files (a table's rows, a collection's * documents) and not for its metadata files (a schema, a database.json), * which the caller reads the usual way. The table names the data kinds once, * so no answer repeats the check. Each answer is called as * `answer(accessor, match, path, ...args)`, after `guard`. Mirrors * `per_kind` in `mirage/core/hierarchy/read.py`. */ export declare function perKind<A extends Accessor, Args extends unknown[], T>(detect: DetectFn, answers: Readonly<Record<string, (accessor: A, match: ScopeMatch, path: PathSpec, ...args: Args) => Promise<T>>>, options?: { guard?: Guard<A>; }): (accessor: A, path: PathSpec, ...args: Args) => Promise<T | null>; /** * Build a hierarchy read: classify, dispatch, refuse the rest. * * Readers own their fetches, guards and rendering, handed what is at the path * (`entry`) and at its parent (`parent`) as the listings name them; the kit * owns the classification and the ENOENT funnel for every non-file shape. * `readers` holds one reader per leaf kind. Mirrors `make_read` in * `mirage/core/hierarchy/read.py`. */ export declare function makeRead<A extends Accessor>(detect: DetectFn, readers: Readonly<Record<string, Reader<A>>>, options?: HierarchyReadOptions<A>): (accessor: A, path: PathSpec, entry?: FileStat | null, parent?: FileStat | null, window?: ReadWindow) => Promise<Uint8Array>; export type RangedReader<A extends Accessor> = (accessor: A, match: ScopeMatch, path: PathSpec, entry: FileStat | null, parent: FileStat | null, offset: number, size: number | null) => Promise<Uint8Array>; export type ReadFn<A extends Accessor> = (accessor: A, path: PathSpec, entry?: FileStat | null, parent?: FileStat | null) => Promise<Uint8Array>; /** * Build a byte-ranged read over a hierarchy read. * * A rendered file has no remote range to ask for — its bytes do not exist * until the read renders them — so the window is sliced after the fact. A * stored blob does (discord and slack attachments serve HTTP range * requests), and downloading the whole file to keep a slice would defeat the * ranged read; those kinds name a ranged reader in `ranged` and push the * byte window to the source. */ export declare function makeReadRange<A extends Accessor>(detect: DetectFn, read: ReadFn<A>, ranged: Readonly<Record<string, RangedReader<A>>>): (accessor: A, path: PathSpec, entry?: FileStat | null, parent?: FileStat | null, options?: { offset?: number; size?: number | null; }) => Promise<Uint8Array>; //# sourceMappingURL=read.d.ts.map