@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
112 lines • 6.04 kB
TypeScript
import type { Runtime } from '../../runtime/base.ts';
import type { RouteDecision } from '../../runtime/types.ts';
import type { MountRegistry } from '../mount/registry.ts';
import type { SessionState } from '../session/session.ts';
import { Consumer } from './types.ts';
/**
* Whether a command word is a tool the allow lists govern. Every named
* command is a subject, shell builtins included: an allow list stating
* `cat` leaves no `echo` and no `cd`. Two kinds of word are not,
* because neither is a name the list could hold: a path being executed
* (its lines are each checked as they run), and the agent's own
* function where the function is what runs, which in this shell means
* a name no builtin owns (builtins shadow functions), and its body's
* lines each pass the gate themselves.
*/
export declare function isTool(name: string, session: SessionState): boolean;
/** Whether routing explicitly refused the external runtime for `name`. */
export declare function runtimeRefused(name: string, session: SessionState, registry: MountRegistry, routing?: RouteDecision<Runtime>): boolean;
/**
* Route a command name to the layer that consumes it.
*
* Order mirrors dispatch precedence: shell builtins shadow functions,
* functions shadow installed CLIs, CLIs shadow mount commands, and a
* name nobody registers is UNKNOWN (command not found). Install-time
* collision rules keep the CLI arm honest: a CLI may not take a shell
* builtin's or a general command's name, so the only shadowing a CLI
* can actually exert is over a mount-specific custom command.
*
* The full landscape, in precedence order. The column to watch is what
* resolves the name: session or workspace state for the named layers,
* operand paths for mounts:
*
* Consumer Example Resolved by Words
* SESSION cd, echo, export name in SHELL_NAMES shell-expanded
* NAMESPACE ln -s, readlink NAMESPACE_COMMANDS shell-expanded
* FUNCTION deploy() {..} session.functions shell-expanded
* CLI slack message send registry.clis shell-expanded
* MOUNT grep, cat, du operand paths pushdown
* UNKNOWN bogus nobody untouched, 127
*
* Named process captures select EXTERNAL before mount commands.
* EXTERNAL_COMMANDS handles names no preceding layer owns.
*
* This is the winner only. A name can sit in more than one layer at once
* (a function shadowing an installed CLI); `lookupAll` reports them all,
* which is what `type -a` prints. Reading one item off the generator is
* what makes that sharing free: the lookups after the winner never run,
* so dispatch pays exactly what it did when this was a chain of `if`
* arms.
*/
export declare function lookup(name: string, session: SessionState, registry: MountRegistry, routing?: RouteDecision<Runtime>): Consumer;
/**
* Every layer holding the name, most-preferred first.
*
* Empty when nothing holds it, where `lookup` says UNKNOWN. Only
* introspection (`type -a`, `which -a`) needs this: dispatch runs the
* winner and never asks what it shadowed.
*/
export declare function lookupAll(name: string, session: SessionState, registry: MountRegistry): Consumer[];
/**
* The layer a name runs from as a program, null when it is none.
*
* A program is what a real system ships as a file on PATH, so it has one
* under `/usr/bin` here: every mount, namespace and CLI command, every
* name a runtime captures by name, and each builtin a real system also
* finds on disk (echo, test, xargs). The shell's own words (cd, export,
* history: `SHELL_ONLY_BUILTINS`), reserved words, functions and aliases
* have no file, and a shell word keeps none when a mount registers the
* same name, since the builtin is what runs. Nor does a name only the
* external fallback capture takes: it takes any word, so like bash's
* `command_not_found_handle` it runs a name without making it a program.
* An interpreter (python3, node) is a program only where a language
* runtime is bound to it: without one it answers 127, as it does on a
* system that never installed it. A function shadowing a program leaves
* the file in place, as it does on PATH.
*/
export declare function program(name: string, session: SessionState, registry: MountRegistry): Consumer | null;
/**
* Whether a builtin that execs its operand (xargs, timeout) finds it.
*
* GNU execs the name, so a shell word with no file on PATH (cd, export) is
* missing there, as is a name nothing provides. A function runs too, where it
* is what the name runs (a shell word shadows one): mirage runs the line in
* the shell, which is how these reach it. A path is left to the run, which
* reports on it.
*/
export declare function execs(name: string, session: SessionState, registry: MountRegistry): boolean;
/**
* What a program's `/usr/bin` file says about it, null when the name is no
* program.
*
* One line: what runs the name, and `--help` where the program's spec
* answers it, which a mount command's and a CLI's do; a builtin's answer
* varies (`ln --help` and `echo --help` print no help), so a builtin's
* line names none.
*/
export declare function programNote(name: string, session: SessionState, registry: MountRegistry): string | null;
/**
* The program a command word runs: a wrapper no mount registers (`egrep`)
* runs the program it names, any other word itself.
*/
export declare function runsAs(name: string, registry: MountRegistry): string;
/**
* Every program name the session can run, sorted: the `/usr/bin` listing.
*
* The names are gathered from each layer that can hold a program and
* kept only where `program` says the name runs as one, so the listing and
* a lookup never disagree. A name only the external fallback capture
* would take cannot be listed, since that capture takes any word.
*/
export declare function programs(session: SessionState, registry: MountRegistry): string[];
//# sourceMappingURL=lookup.d.ts.map