UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

50 lines (49 loc) • 3.85 kB
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;