UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

139 lines • 7.44 kB
import { CommandSpec } from '../../../commands/spec/types.ts'; import { PathSpec, type Limit } from '../../../types.ts'; import type { ProcessView } from '../../../process/view.ts'; import type { CLI, CLIHandler } from '../../../commands/cli/types.ts'; import type { CommandFnResult, Context } from '../../../commands/config.ts'; import { type ShellFn } from '../../../runtime/types.ts'; import type { FollowOperands, SessionView } from '../../../view/types.ts'; import type { Files } from '../../files.ts'; import { type FlagValue } from '../../../commands/spec/types.ts'; import { IOResult, type ByteSource } from '../../../io/types.ts'; import type { CLIInstall } from '../../cli/types.ts'; import type { MountEntry } from '../../mount/mount.ts'; import type { SessionState } from '../../session/session.ts'; import { ExecutionNode } from '../../types.ts'; import type { RouteDecision } from '../../../runtime/types.ts'; import type { Runtime } from '../../../runtime/base.ts'; import type { IdSource } from '../../../utils/ids.ts'; /** * Workspace facts the dispatcher can offer but most CLIs do not want: an API * client needs no filesystem, while `git` is nothing but one. Forwarded whole * onto the leaf's opts bag, so a leaf that does not read them ignores them and * there is no allowlist of filesystem-aware CLIs to keep in step (the same rule * `links` follows for mount commands). */ export interface CLIContext { shell?: ShellFn; signal?: AbortSignal; commandLimits?: Readonly<Record<string, Limit>>; /** * The workspace's ordered runtime world, which a script leaf selects * its interpreter from; absent (outside a workspace) refuses script * installs. */ entries?: readonly Runtime[]; /** * The session's files, run as the line's session with the command's gate, * for a CLI whose subject is files rather than an API. */ vfs?: Files; session?: SessionView; processes?: ProcessView; /** The line's placement, which a script leaf runs its program under. */ routing?: RouteDecision<Runtime>; /** * Lands what a script leaf's runtime holds and drops the caches its * program may have gone past; absent outside a workspace. */ settle?: (runtime: Runtime) => Promise<void>; /** The workspace's source, which the leaf's `ctx.ids` draws from. */ ids?: IdSource; } /** * Whether this CLI reaches a service past the dispatcher. * * Its write verbs then go past the dispatcher's per-path invalidation, so the * mounts its client may reach drop their caches after one * (`MountRegistry.dropCaches`). Two roots do that: one with a `configModel` * (an account CLI, initialized from it) and a script root, whose config is * opaque by construction and whose program may reach anything. A root with * neither (`git`) has no service to reach; its writes go through the * dispatcher, which invalidates as it goes, so a blanket drop would only cost * every other mount a reload. Mirrors Python's `reaches_service`. */ export declare function reachesService(spec: CLI): boolean; /** * Execute a line whose head word is an installed CLI. * * Dispatch is by NAME: the install resolves the program tree and the * validated config; no mount is consulted and no operand path picks a * backend (the one executor divergence from mount commands). The walk * consumes subcommand words and group options; the leaf's own argv * uses the shared CommandSpec parser. The leaf gets the line's one Context, * built here and nowhere else: an fn leaf runs as * `fn(accessor, paths, texts, ctx)`, a script * leaf runs its embedded program on a workspace runtime * (scriptOutput), so usage refusals, limits, and classification all * happen in front of either tier. Help too, for every node that declared * a grammar to render it from (parseSpecFor). The workspace facts in * `context` reach a verb on its `ctx`, so a verb that never reads `ctx.vfs` * cannot touch a mount. */ export declare function handleCli(install: CLIInstall, parts: readonly (string | PathSpec)[], session: SessionState, stdin?: ByteSource | null, context?: CLIContext, dropCaches?: (() => Promise<void>) | null): Promise<[ByteSource | null, IOResult, ExecutionNode]>; /** * A line a command tree's walk resolved to one leaf, parsed and ready to * run. Mirrors Python's `LeafCall`. */ export interface LeafCall { /** The line's words as typed, for the record. */ cmdStr: string; /** The words after the head as typed. */ argv: readonly string[]; /** The head and the verb path, the name a message, a limit and the output guards read. */ prog: string; /** The canonical verb path below the head. */ path: readonly string[]; leaf: CommandSpec; handler: CLIHandler; /** The group and leaf flags, one bag. */ flags: Record<string, FlagValue>; paths: PathSpec[]; texts: string[]; /** What the parse warned about, said ahead of the leaf's own stderr. */ warnings: readonly string[]; } /** * Walk a line down a command tree to the leaf it names and parse the * leaf's words, or answer the line without running anything. * * The walk consumes subcommand words and group options; the leaf's own argv * uses the shared CommandSpec parser. Help, usage refusals and an operand * base that is no directory are answered here, for an installed CLI and a * tree a mount serves alike. Mirrors Python's `walk_leaf`. */ export declare function walkLeaf(name: string, cli: CLI, parts: readonly (string | PathSpec)[], session: SessionState, vfs: Files | undefined): Promise<LeafCall | [ByteSource | null, IOResult, ExecutionNode]>; /** * Execute a line whose head word names a command tree a mount serves. * * The tree a VFS was handed (or one registered on its mount) is walked * exactly as an installed CLI's is (`walkLeaf`: verbs, help, usage * refusals, the leaf's parse); the leaf then runs on the mount, on its * accessor and under its refusals (`MountEntry.runLeaf`), with its own * limit: the profile's, then the mount's and the workspace's entry for the * verb path, then the leaf's declared one. A tree runs on the mount serving * its name, never by operand path, and its leaf keys that mount's accessor by * each operand: the operands the leaf parse resolved are followed through the * link table as the router follows a mount command's (`follow`), and one * another mount holds (`owner`) is refused before the leaf runs. Mirrors * Python's `handle_mount_cli`. */ export declare function handleMountCli(mount: MountEntry, cli: CLI, parts: readonly (string | PathSpec)[], session: SessionState, stdin?: ByteSource | null, context?: CLIContext, owner?: (path: string) => MountEntry | null, follow?: FollowOperands, prepared?: LeafCall): Promise<[ByteSource | null, IOResult, ExecutionNode]>; /** * Run a walked leaf with the one Context a leaf gets, and record it. * * The leaf's declared limit caps its output, exactly like mount dispatch. * A failure the runner framed is recorded as it is; an answer gets the * parse's warnings ahead of its stderr. Mirrors Python's `run_walked`. */ export declare function runWalked(walked: LeafCall, session: SessionState, stdin: ByteSource | null, context: CLIContext, limit: Limit | null, run: (ctx: Context) => Promise<CommandFnResult>): Promise<[ByteSource | null, IOResult, ExecutionNode]>; //# sourceMappingURL=cli.d.ts.map