@sema-agent/core
Version:
Stateless, task-oriented AI agent core
60 lines (59 loc) • 4.58 kB
TypeScript
/**
* The ONE door between the shell read station's establisher and the execution environment's filesystem.
*
* The establisher answers "where does each word of this command land" by asking the environment (a resolution, a
* directory listing, a stat, a link read). An environment that does not give an answer — an error that is not a
* conclusive "not there", a lookup that came back inconclusive — and a bound the station itself stops at are the same
* fact for the verdict: the judge did not finish checking the command against the deny rows, so it cannot vouch for it. That
* fact is recorded HERE, at the door, once per judgment, not by each producer that happens to remember to mark it: the
* establisher and the write guards are handed an {@link ObservedFilesystem}, never the environment, so a lookup they make
* cannot escape the record.
*
* What is NOT a failure: a conclusive absence (`not_found`, `not_directory` — the answer is "nothing there") and an adapter
* that has no filesystem surface (`not_supported` — its answer that there is no file face: a chain it answers so keeps the
* lexical reading). Everything else is, and is recorded wherever it falls — a resolver that answered nothing at all in the
* command included: a lookup that failed (`permission_denied`, `timeout`, `unknown`, a throw) is a resolver failing, whose
* identity of the words cannot be judged, never an adapter without a file face.
*/
import type { ExecutionEnv } from "../../internal/harness-types.js";
/** One thing the station could not finish: an environment lookup that gave no answer, or a bound the station stopped at. */
export interface Incomplete {
/** The lookup (`canonicalPath`, `listDir`, `fileInfo`, `readLink`, `fileIdentity`) or `bound`. */
readonly op: string;
/** The sentence the card discloses ("… cannot be resolved (permission_denied)"). */
readonly detail: string;
}
/** Only {@link observeEnvironment} mints the brand: a bare environment is not assignable where a door is asked for. */
declare const OBSERVED: unique symbol;
/** The environment as the station's paths may use it: every path lookup the engine's resolvers make (`canonicalPath`,
* `listDir`, `fileInfo`, `readLink`, `exists`, `absolutePath`, `canonicalChain`, `fileIdentity`) goes through the door and is
* recorded when it gives no answer; everything else is the environment's own. It IS an `ExecutionEnv` to the resolvers
* (`canonicalizeTarget`, the home views, a deployment's guarded-row provider) — so none of them has to be narrowed — and
* nominal to the station: the establisher, the write guards, the write judgment and the home views are typed over it, so
* none of them can be handed the bare environment, nor a captured one. */
export type ObservedFilesystem = ExecutionEnv & {
readonly [OBSERVED]: true;
};
/** The observed door for one command. */
export interface ObservedEnvironment {
readonly fs: ObservedFilesystem;
/** Whether the environment DECLARES its `canonicalPath` the authority on where a path lands: a chain it does not answer at all
* is then not placed (the establishment's reading; the door records the lookups alike either way). */
readonly authoritative: boolean;
/** What the door recorded, in the order it happened; call it after the last lookup of the command. */
incomplete(): Incomplete[];
/** The station stopped at its own bound (more directories or names than it enumerates, a link chain past its hop bound). */
bound(detail: string): void;
/** Records that came from outside the door: the declared roots' own lookup and the home views a read could not be placed against. */
adopt(records: readonly Incomplete[]): void;
}
/** The declared roots, canonicalized ONCE per establisher (through the same door), with what that lookup could not finish —
* merged into every establishment. `known`: the caller already holds them as canonical identities and they are used verbatim
* (re-resolving one that was since swapped for a link would substitute the link's target for the root that was approved). */
export declare function canonicalRootsOnce(env: ExecutionEnv, readRoots: readonly string[], known: boolean): (signal?: AbortSignal) => Promise<{
readonly roots: readonly string[];
readonly incomplete: readonly Incomplete[];
}>;
/** Wrap `env` so every lookup that fails inconclusively is recorded; the result a caller sees is the environment's own. */
export declare function observeEnvironment(env: ExecutionEnv): ObservedEnvironment;
export {};