@sema-agent/core
Version:
Stateless, task-oriented AI agent core
50 lines (49 loc) • 3.85 kB
TypeScript
import { type ShellCommandShape } from "./shell-lexer.js";
import { type LineDescriptors } from "../tools/fs/shell-read-device.js";
/** The reader's answer: read-only, or not — with the first reason the reading stopped on (a sentence a
* trace or a card can show; never adjudication input). */
export type ReadOnlyShellVerdict = {
readonly readOnly: true;
} | {
readonly readOnly: false;
readonly reason: string;
};
/** The reference implementation's question for a compound that changes directory and runs git (2.1.280, `cd-git-compound`). */
export declare const CD_GIT_COMPOUND_SENTENCE = "This command changes directory before running a version-control command, which can pick up untrusted hooks or repository configuration from the target directory. Approve only if you trust it.";
/**
* Does this line change directory and run git — a `cd` beside a `git` — other than by ONE plain `cd <path>` that lands
* where the session stands (`cwd`)? The reference's no-op reading, lexical here: the path is `.` / `..`, starts `./` /
* `../` / `/`, carries no expansion, quote-removed text only, and resolves to `cwd` itself. No `cwd` ⇒ no no-op.
*/
export declare function changesDirectoryBeforeGit(shape: ShellCommandShape, cwd?: string): boolean;
/**
* Read `command` as the allow layer must: read-only, or the first reason it is not. A shape already read by
* the caller may be handed in (the gate reads every shell command once).
*
* @contract read_only_shell.every_segment — a command line is read-only iff the lexer reads it whole (no
* unreadable segment, no group/subshell/control structure, no background `&`), no word anywhere carries a
* variable, arithmetic or command substitution, and EVERY segment is read-only on its own: its
* redirections only read or discard (`<` family, `/dev/null`, a descriptor duplication), its leading
* assignments name only variables from {@link READ_ONLY_ENV_NAMES} with literal values, and its program
* with its arguments is admitted by exactly one of three readings in order — a segment carrying a GLOB is
* admitted only under {@link READ_ONLY_GLOB_PROGRAMS}; else the structural reading (the bare-program set,
* the exact forms, `echo`/`ls`/`cd`/`find`/`printf`/`history`/`arch`/`ifconfig`); else the flag-vetted
* table with its per-row danger predicates, and the `uniq`/`jq` forms. A `cd` beside a `git` in one line
* is never read-only (the git command's repository is then not the session's) unless the `cd` lands where the session
* stands ({@link changesDirectoryBeforeGit}). Anything the reading does not positively admit is NOT read-only — the
* answer is never a guess, and a `false` costs one question.
*/
export declare function readOnlyShellVerdict(command: string, shape?: ShellCommandShape, cwd?: string, bound?: LineDescriptors | (() => LineDescriptors)): ReadOnlyShellVerdict;
/**
* The reader's LINE-level objection to `command` — what makes no segment of it read-only in its place, whatever the
* segment reads on its own: the line's structure, or a `cd` beside a `git` ({@link changesDirectoryBeforeGit}). A caller
* that judges a compound's segments one by one ({@link readOnlyShellVerdict} over a segment's text) asks this of the
* line first.
*/
export declare function readOnlyLineObjection(command: string, cwd?: string): string | undefined;
/**
* What the whole text of `command` binds — every redirection of every segment (a single one, an `exec`'s, a `{name}` one included),
* read by the station's own computation ({@link descriptorsOfPlan}): the one binding map the shape tier's operand reading shares with
* the station's rebinding rule. The plan is read with no listed readers: the bindings do not depend on which programs read.
*/
export declare function lineDescriptorsOfText(command: string): LineDescriptors;