UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

51 lines (50 loc) • 3.4 kB
/** * The READ station of the file tools (Read / Grep / Glob) — the read face's twin of the shell read station, one gate * input shape ({@link ShellReadCheck}) so the gate, the approved-edit re-judge and the resumed leg's belt read both: * before approval, where the call's declared path target lands is resolved exactly as the tool will resolve it * (`resolveKey` over the same spelling, base, roots, deny table and containment face), and a target OUTSIDE the read * roots is an ORDINARY question — a person answers it, a persisted `Read(//dir/**)` row or the auto-mode classifier * may, a permission mode arbitrates it — with the directory whose grant clears it on the card. The deny table and * every other refusal stay the tool's own: this station judges containment only, after the deny judgment. * * A call whose out-of-root read the gate put to a question is ADMITTED for that one target when the gate applies the * verdict ({@link ShellReadVerdict.admit}): the tool reads it once ({@link FileReadStation.admitted}), on the canonical * key the station judged — a target that resolves elsewhere by then is refused by the tool's own fence, and a verdict * the gate never received (its wait elapsed, the judgment threw) admits nothing. */ import type { ExecutionEnv } from "../../internal/harness-types.js"; import type { ContainmentFace } from "./containment-face.js"; import { type ReadDenyMatcher } from "./read-deny.js"; import { type ShellReadCheck } from "./shell-read-check.js"; export interface FileReadStation { readonly check: ShellReadCheck; /** The station's membership: the tool names whose declared read target it judges. */ readonly tools: ReadonlySet<string>; /** Did the gate put THIS call's read of `canonicalKey` outside the roots to a question it then let through? Consumed * on a match: the admission covers one read of one target. */ readonly admitted: (toolCallId: string | undefined, canonicalKey: string) => boolean; } export interface FileReadStationOptions { readonly env: ExecutionEnv; readonly rootCanonical: string; /** The extra read roots, read per call (a grant widens the live set). */ readonly roots: () => readonly string[]; readonly readDeny?: ReadDenyMatcher; readonly readFace?: ContainmentFace; readonly homeDir?: string; /** The file tools this leg mounts (their catalog path target is the one judged). */ readonly tools: ReadonlySet<string>; /** A target no answer may admit (the store-isolation rule's judgment, `rootAdmittingArtifactStore`): it is left to * the tool's own refusal, no question is raised for it. */ readonly excluded?: (canonicalKey: string) => boolean; /** A target the tools' own fence admits without the roots (the engine's background output file, * `backgroundOutputReadExemption`): no question is put for it. */ readonly exempt?: (canonicalKey: string) => boolean; } export declare function createFileReadStation(opts: FileReadStationOptions): FileReadStation; /** One gate input over the leg's read stations: each call is judged by the station whose membership holds the first of * its names any station holds (the spelling first). */ export declare function composeReadChecks(stations: ReadonlyArray<{ readonly check: ShellReadCheck; readonly tools: ReadonlySet<string>; }>): ShellReadCheck | undefined;