UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

70 lines (69 loc) • 4.26 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 type { FileError, FileKind, 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). */ 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. */ export declare function enumerateDirectory(env: ExecutionEnv, dir: string, judge: EntryDenyJudge | undefined, signal?: AbortSignal): Promise<Result<DirectoryListing, FileError>>; /** * A data label (a path, a file name) as a JSON string literal with every C0/C1 control, format character * and line / paragraph separator written as `\uXXXX` — lossless (JSON.parse gives the original back), and * one line whatever the name holds. JSON's own escaping alone leaves U+2028 / U+2029 / U+0085 and the * format characters raw. */ export declare function quoteDataLabel(label: string): string; /** 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;