UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

66 lines (65 loc) • 4.35 kB
/** * Directory ENTRIES for the model, and the one per-entry read-deny judge every traversal shares. * * The judge ({@link createEntryDenyJudge}) is the walk's (search.ts `walk`, the throat Glob, the Grep * fallback and the repo map traverse through): an entry path is judged as spelled and at its home view * (read-deny-home.ts), so a traversal that enters the home through an alias of it meets the * home-anchored rows where the home is. It answers; it does not count — each caller counts what its own * result has to disclose. * * The enumerator ({@link enumerateDirectory}) lists ONE level of a directory the way the upstream * at-mention lists one (a single readdir, at most {@link DIRECTORY_LISTING_MAX_ENTRIES} names, then * "… and N more entries"), with three differences that are this engine's facts: * · entries are files, directories AND symbolic links (kinds from the environment's listing, which does * not follow links); a link is listed by its own name and judged at its own path — its target is never * resolved or read here; * · every entry passes the per-entry read-deny judge; a withheld entry is neither named nor counted in * the remainder, and the withheld count is EXACT (one level, so every entry is judged); * · no ignore rules apply: the user named this directory, and ignore files are a search-noise filter, not * a read boundary. * Entries sort by code unit (a stable listing; the environment's own order is not one). Three counts stay * apart: `omitted` (withheld by the deny judge), `more` (kept entries past the cap), `incomplete` (the * judging was cut short by an abort — the listing is a prefix, not the directory). */ import type { ExecutionEnv } from "../../internal/harness-types.js"; import { FileError, type FileInfo, type FileKind, type Result } from "../../internal/harness.js"; import { type HomeViewEnv, type HomeViewsCarrier } from "./read-deny-home.js"; /** The upstream at-mention's cap on listed entries. */ export declare const DIRECTORY_LISTING_MAX_ENTRIES = 1000; /** The read-deny table as the traversals hold it. */ export type EntryDenyTable = { matchPath(path: string): { pattern: string; } | null; } & HomeViewsCarrier; /** Judge one entry path: the row that withholds it, or null. `leaf: "file"` asks the home view for a file * leaf (a directory entry is judged as a directory). */ export type EntryDenyJudge = (path: string, leaf?: "file") => Promise<{ pattern: string; } | null>; /** The per-entry judge over `deny` (literal spelling, then the home view). An entry whose home view nobody could read is not * an entry with no view: the judgment of the traversal did not finish, and the call is refused whole * ({@link HomeViewUnreadError}, thrown) — what the walk would serve was not judged, so neither it nor a partial result is. */ export declare function createEntryDenyJudge(env: HomeViewEnv, deny: EntryDenyTable, signal?: AbortSignal): EntryDenyJudge; export interface DirectoryEntry { name: string; kind: FileKind; } export interface DirectoryListing { /** At most {@link DIRECTORY_LISTING_MAX_ENTRIES}, sorted. */ entries: DirectoryEntry[]; /** Kept entries past the cap. */ more: number; /** Entries withheld by the read-deny judge (exact). */ omitted: number; /** The rows that withheld something, first-seen order. */ omittedPatterns: string[]; /** An abort cut the judging short: `entries` / `more` / `omitted` describe a prefix of the directory. */ incomplete: boolean; } /** List one level of `dir` (a canonical directory path). A listing the environment refuses is the error. `list` is how the * entries are read (default: the environment's `listDir`; a carrier bound to a judged directory passes its bound listing). */ export declare function enumerateDirectory(env: ExecutionEnv, dir: string, judge: EntryDenyJudge | undefined, signal?: AbortSignal, list?: (dir: string) => Promise<Result<FileInfo[], FileError>>): Promise<Result<DirectoryListing, FileError>>; /** The listing as text: one entry per line (a directory with a trailing "/"; a name that could break or * hide in its line is written as {@link quoteDataLabel}), then "… and N more entries" when capped. */ export declare function renderDirectoryListing(l: DirectoryListing): string;