@sema-agent/core
Version:
Stateless, task-oriented AI agent core
69 lines (68 loc) • 5.47 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, and the words the
* segment's program writes by the program read model's ROLES (`writeReadings`: an operand or option value whose role
* writes, the operands an option made edited in place, a copy's destination and its children, an in-place edit's
* backups), at the seats the role and the selected options name ({@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 write face (the write deny rows, then the write roots). No table of programs or options lives here: what a
* program writes is its row's.
*/
import type { ReadCandidate, ShellReadSegment } from "./shell-read-plan.js";
import { type LineDescriptors } from "./shell-read-device.js";
import { type WriteSeat } from "./program-read-model.js";
export type { WriteSeat } from "./program-read-model.js";
/** 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[];
/**
* 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[];
/** 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`: an in-place edit's backup where the operand is edited where it LANDS — 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). `onlyIfExists`: written only under
* SOME implementation's reading of the command, and only by editing an existing file — the program edits nothing that is
* not there, so where the filesystem confirms this candidate missing nothing is written (a lexical establishment cannot
* confirm it, and keeps the write). */
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;
};
readonly onlyIfExists?: ReadCandidate;
}
/** Is any of these words an option word (one starting with `-`)? The reference implementation's reading of a copy or a move: a
* command with flags is not one whose paths it can validate (`--target-directory`, `--remove-destination`, a backup suffix
* all change what is written where). */
export declare const anyOptionWord: (words: readonly string[]) => boolean;
/**
* Does this invocation write ONLY standard devices — what the shape tier reads as "writes nothing durable" for a PROGRAM (a
* redirection is the reader's own)? Every word any implementation's reading of the row writes ({@link writeReadings}; a word the
* reading names written at no seat, a copy's source, is read) is one the program writes THROUGH ({@link writesThrough}) and
* is a standard device no redirection of the line rebinds ({@link standardDeviceUnrebound}) — the station's own predicate
* (`passesUnasked`) over the same row facts, for the one entry a text-only reader has: `tee /dev/tty`, `cp a.txt /dev/stdout`.
* No program is named here: which programs may ask this is the caller's.
*/
export declare function writesOnlyStandardDevices(program: string, args: readonly string[], line: LineDescriptors): boolean;
/** 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. A word the program only writes keeps
* its read copy for the read deny rows alone (`denyOnly`): whether it lands inside the write roots — or cannot be placed
* at all — is the write face's question, never a read's. */
export declare function judgedCandidatesOf(segment: ShellReadSegment): readonly JudgedCandidate[];