UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

112 lines • 6.04 kB
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