UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

142 lines • 7.11 kB
import type { Claimant, HandOff, Occurrence } from '../../policy/types.ts'; import type { TSNodeLike } from '../../shell/types.ts'; import type { SessionState } from '../session/session.ts'; /** * What opens and closes a substitution's body, in the order the openers * are tried; the body between them is the text a nested line is parsed * from. A backtick region is not here: its body loses its backslashes * before it is parsed, so it is lexed into lines (`segmentFrames`) rather * than framed as one body. */ export declare const SUBSTITUTION_DELIMITERS: readonly (readonly [string, string])[]; /** * The text a walk reads commands from, as the line that evaluates it * will parse it. * * The pass walks one tree and computes for every command the occurrence * the gate will compute when it runs, and the gate may be running a * different parse of the same text: a substitution's body is parsed on * its own by the nested line, at offsets that start from zero, while * the pass reads it as a subtree of the outer line. The frame is what * makes the two agree: `text` is what the nested line parses, `base` is * where that text starts in the tree being walked, and `parent` is the * occurrence its commands stand under. Mirrors the Python Frame. */ export interface Frame { readonly text: string; readonly base: number; readonly parent: Occurrence | null; } /** * The frame of the tree a node belongs to: the text its parse read, at * that parse's own offsets. * * The one rule both readers share. The gate builds it from the node it * runs, and the pass from the tree it walks, so a stored function body * is placed relative to its definition. Reparsing that source in another * worker gives its commands the same approval locations. */ export declare function rootFrame(node: TSNodeLike, parent: Occurrence | null): Frame; /** * The frame of a function body as a pass walks its definition. The body * runs from its own parse of the stored source, so its commands stand at * offsets from the definition, under the definition's own place on the * line: two definitions of one text are two places, each needing a nod * of its own. Mirrors Python's definition_frame. */ export declare function definitionFrame(node: TSNodeLike, frame: Frame): Frame; /** * The place a function definition the executor runs stands on its line, * which the body's commands stand under when it is called; null outside * a line. Mirrors Python's defined_at. */ export declare function definedAt(node: TSNodeLike, handed: HandOff | null): Occurrence | null; /** * The frame a node's gate will read it in, for a pass that reads it ahead * of the gate: its own tree's, and for a node in a function body under the * place the call runs the body under. Mirrors Python's gate_frame. */ export declare function gateFrame(node: TSNodeLike, line: TSNodeLike, session: SessionState, handed: HandOff): Frame; /** * The frame of a line a word runs (`eval`, `sh -c`), which the pass * parses on its own exactly as the nested evaluation will. */ export declare function lineFrame(text: string, parent: Occurrence): Frame; /** * The frame of the line a command hands the evaluator for words it was * given already split (`command`, `env`, `timeout`, `xargs`), spelled * as those builtins spell it: joined with shellJoin, so an operand * holding a space survives the re-parse as one word. * * The nested gate parses that spelling, so the pass has to compute the * occurrence on it. Joined with a plain space, `cat '/data/secret * file'` was read as `cat /data/secret file` and the gate could not * find the grant claimed for it. */ export declare function argvFrame(argv: readonly string[], parent: Occurrence): Frame; /** Where a node stands, as a parse of the frame's text would place it. */ export declare function occurrenceIn(node: TSNodeLike, frame: Frame): Occurrence; /** * The occurrence of a frame's whole text, for words a command runs * without a parse of their own (`xargs cat`, `find -exec`). * * The end is the parser's own unit: it places a node here in UTF-16 * code units, which is what a string index counts, so no * measuring is needed here. The Python parser counts bytes, and that * side measures every span it computes from text (`byte_offset`). */ export declare function wholeOccurrence(frame: Frame): Occurrence; /** * The frame of a substitution's body, as the nested line that evaluates * it will parse it: `$( )`, `<( )` or `>( )`, with the whitespace * the parser folds into the opening token set aside as expansion sets * it aside. Null for a node that is not a substitution the evaluator * would run. */ export declare function bodyFrame(node: TSNodeLike, frame: Frame): Frame | null; /** * The occurrence of one span of a node's text, for a node whose line is * not its whole text: a backtick region, which the evaluator lexes * again. Each command is its own place on the line. */ export declare function partOf(occurrence: Occurrence, start: number, end: number): Occurrence; /** * The frames of the lines a backtick region runs, one per pair, each to * be parsed on its own under the pair's own place on the line; empty * for a node that is not a backtick region. * * The region's subtree is not what runs: bash removes a backtick body's * backslashes before it parses it, so the pass reads the region as the * evaluator does, split by the one lexer both share * (`splitBacktickRegion`), with the folded whitespace set aside first as * expansion sets it aside. */ export declare function segmentFrames(node: TSNodeLike, frame: Frame): Frame[]; /** * Where a node the executor runs stands, on the line it runs in: the * line's hand-off carries as `origin` the node the line's text was * evaluated from. `span` is the part of the node's text that runs, when * the node holds several lines. */ export declare function occurrenceOf(node: TSNodeLike, handed: HandOff, span?: readonly [number, number]): Occurrence; /** * The hand-off a line read from a node's text runs on. * * Every re-parse the executor runs is a line of its own: the body a * substitution expands, the words `eval` or `xargs` hand on, the line an * alias invocation rewrites to. It runs under the hand-off of the * subtree reading it and stands at the node whose text it is, so its * commands are placed where the outer pass placed them, and one text * read from two nodes (`c && c` under one alias) is two places on the * line, each needing a nod of its own. What its gates claim goes back * to that hand-off when it ends (`Decisions.handUp`). `span` is the part * of the node's text that runs, when the node holds several lines. * Mirrors the Python `evaluated_from`. */ export declare function evaluatedFrom(node: TSNodeLike, handed: HandOff, span?: readonly [number, number]): HandOff; /** * The reader of the ledger for one command the executor runs, null * outside a line. */ export declare function claimantFor(node: TSNodeLike, handed: HandOff | null | undefined): Claimant | null; //# sourceMappingURL=occurrence.d.ts.map