@sema-agent/core
Version:
Stateless, task-oriented AI agent core
74 lines (73 loc) • 5.37 kB
TypeScript
/**
* WRITE TARGETS — which words of a shell segment a program writes, under which names, and at which seat, read off the
* plan's text alone (no filesystem): the `>`-family redirections and a `sed` script's `w` files, the operands of the
* write commands ({@link SHELL_WRITE_COMMANDS}), a copy's or a move's destination children (GNU's argument grammar), an
* in-place `sed`'s backups, and the seat each is written at ({@link WriteSeat}: the directory entry, or where the path
* lands). The establisher (`shell-read-establish.ts`) places what this module names; the judge reads the result on the
* deny table's write face; the station's `writesPlaced` fact reads the option readers exported here.
*/
import type { ReadCandidate, ShellReadSegment } from "./shell-read-plan.js";
/**
* The commands whose operands are WRITE targets — the reference implementation's path-checked commands whose operation
* is a write or a create (`mkdir` / `touch` create; `rm` / `rmdir` / `mv` / `cp` / `tee` write; `sed` writes when it
* edits in place). Every operand counts (a `cp` source is judged as a write too, as the reference judges it): the write
* face only ever REFUSES, so a word read as a target it is not costs a refusal of a command that names a denied path.
*/
export declare const SHELL_WRITE_COMMANDS: readonly ["mkdir", "touch", "rm", "rmdir", "mv", "cp", "tee", "sed"];
/**
* Does an option WORD spell this option — the long name or any abbreviation of it GNU getopt accepts (`--in-p`, `--fi`,
* `--par`: an unambiguous prefix, `=value` allowed), or the short letter alone or inside a bundle (`-i`, `-ni`, `-i.bak`)?
* Read in the tightening direction: a prefix that another long option shares still counts (the program would refuse it).
*/
export declare function spellsOption(word: string, long: string, short: string): boolean;
/** A word of a program's argv: its raw spelling (the plan's candidates are keyed by it) and its folded spelling. */
export interface ArgWord {
readonly raw: string;
readonly spelled: string;
}
/** The words a segment hands its program — the argv after the program word (a launcher's own words are not the program's). */
export declare function programArgs(segment: ShellReadSegment): ArgWord[];
/** What a `sed` invocation's option words say about writing, under either grammar ({@link SED_GRAMMARS}): whether it edits
* in place (`-i` / `-I` / `--in-place`), the backup suffixes it is given (their values; an empty value keeps no backup),
* and whether GNU `--follow-symlinks` is on. */
export interface SedOptions {
readonly inPlace: boolean;
readonly suffixes: readonly string[];
readonly followsLinks: boolean;
}
export declare function sedOptionsOf(segment: ShellReadSegment): SedOptions;
/**
* The BACKUP names an in-place `sed` gives the file it knows as `name` — both readings a suffix has: GNU sed replaces every
* `*` in the suffix with the name (`bak/*` on `d/f` is `bak/d/f`, `/elsewhere/*` is `/elsewhere/d/f`) and appends a suffix
* without one (`d/f.bak`); the BSD and BusyBox seds append the suffix literally (`d/f` + `bak/*`). A name resolves against
* the working directory like the operand itself, so a suffix carrying a separator places the backup wherever it points.
*/
export declare function sedBackupNames(name: string, suffix: string): string[];
/**
* WHERE a write reaches a path it names. `landing` — the path followed through every link to where it lands: the program
* opens the path and writes through it. `entry` — the directory entry itself, the canonical parent joined with the last
* name: the program renames over the entry, unlinks it or replaces it, and a link there is not followed (a name ending in
* a separator, `.` or `..` resolves itself, so it lands).
*/
export type WriteSeat = "landing" | "entry";
/** One candidate handed to the judge. `seats`: where a write target is established ({@link WriteSeat}; absent ⇒ it lands —
* every read does). `written`: the seats among `seats` the program itself WRITES the target at (absent ⇒ all of them;
* `[]` ⇒ none — a copy's source, judged on the write face as a write path and read by the program); the write guards are
* asked about these alone. `child`: a copy's or a move's destination child, written only where the destination is a
* directory when the program runs. `followed`: a GNU sed `--follow-symlinks` backup — its names are {@link sedBackupNames}
* of the operand's FOLLOWED name, which only the filesystem answers (the candidate's own spelling is the operand's as
* written, the identity the pre-spawn re-check compares). */
export interface JudgedCandidate {
readonly candidate: ReadCandidate;
readonly seats?: readonly WriteSeat[];
readonly written?: readonly WriteSeat[];
readonly child?: true;
readonly followed?: {
readonly operand: ReadCandidate;
readonly suffix: string;
};
}
/** Every candidate a segment hands the judge: its reads minus the write targets, plus its `cd` target (the plan already
* lists it among the reads), plus its WRITE targets for the write face ({@link writeTargetsOf}), plus the deny-floor
* shadow of every unplaced home word ({@link denyFloorShadowsOf}) on both faces. */
export declare function judgedCandidatesOf(segment: ShellReadSegment): readonly JudgedCandidate[];