UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

123 lines • 8.02 kB
import type { RedirectResult } from '../../context/session_context.ts'; import { type SharedInput } from '../../io/async_line_iterator.ts'; import type { ByteSource } from '../../io/types.ts'; import { IOResult } from '../../io/types.ts'; import { type Decisions } from '../../policy/decisions.ts'; import type { HandOff } from '../../policy/types.ts'; import { CallStack } from '../../shell/call_stack.ts'; import { Channel, JobConsole } from '../../shell/console/index.ts'; import { type JobTable } from '../../shell/job_table/index.ts'; import type { TSNodeLike } from '../../shell/types.ts'; import type { SessionView } from '../../view/types.ts'; import { type EvaluationContext } from '../evaluation.ts'; import type { SessionState } from '../session/session.ts'; import { ExecutionNode } from '../types.ts'; import type { ExecuteNodeFn } from './command/types.ts'; /** * Send a command's output to a console as chunks arrive. * * Consuming the stream piece by piece rather than materializing it whole * is what lets a reader watch a running job. A command that computes its * output eagerly still lands in one chunk, because there was nothing to * observe before it finished. A pipe is drained before the next chunk is * pulled, so a reader that closed stops the source before it fetches more. */ export declare function pump(console_: JobConsole, channel: Channel, stream: ByteSource | null): Promise<void>; /** * Write a finished statement's returned output to a sink, its stdout before * its stderr, since one command keeps no order between them; what it already * wrote there as it ran (a function body, a redirected group) came first. A * read its stream fails is the statement's own failure (`failedRead`). The * result carries no output, so nothing lands twice. Mirrors Python's drained. */ export declare function drained(sink: JobConsole, stdout: ByteSource | null, io: IOResult, execNode: ExecutionNode): Promise<[null, IOResult, ExecutionNode]>; export declare function handleBackground(executeNode: ExecuteNodeFn, left: TSNodeLike, right: TSNodeLike | null, context: EvaluationContext, jobTable: JobTable, stdin?: ByteSource | null, callStack?: CallStack | null, handed?: HandOff | null, decisions?: Decisions | null): Promise<RedirectResult>; /** * Run one statement of a compound body, as a job when it ends in `&`. * * The program loop and the subshell body read the `&` off the token * stream themselves; a loop body, an if/case arm, a brace group or a * function body holds named nodes only, so the statement is asked about * its own terminator. The launch is a statement in its own right and * answers with status 0, as in bash, so `false &` inside a body trips * neither `$?` nor `set -e`. A null `jobTable` means the caller wired no * job plane, which is a programming error once a `&` shows up, not a * reason to run it inline. `bound` is `fd0Binding` as the body started, * so an `exec <` in it replaces `stdin` for the statements after it; a * job still gets the body's own stdin. */ export declare function runStatement(executeNode: ExecuteNodeFn, node: TSNodeLike, context: EvaluationContext, stdin: ByteSource | null, bound: readonly [SharedInput | null, boolean], callStack: CallStack | null, jobTable: JobTable | null, handed?: HandOff | null, decisions?: Decisions | null): Promise<RedirectResult>; /** * Wait for background jobs, with bash's option surface. A job's output * went where its shell writes as it was written, so `wait` prints none, * as bash's does. Bare `wait` joins every job; `wait ID...` joins those * and answers the last one's status; `-n` joins the first of the given jobs * (or of all) to finish, 127 when there is nothing to wait for; `-p VAR` * stores the id of the job whose status is answered, unsetting VAR when * none is (which is the bare form, since it reports no one job); `-f` is * accepted, since a mirage job cannot stop, only end. * * `-p` stores the managed PID, matching `$!` and `jobs -p`. */ export declare function handleWait(jobTable: JobTable, parts: string[], session?: SessionState | null, view?: SessionView | null, signal?: AbortSignal): Promise<RedirectResult>; /** * Drop jobs from the table without stopping them. No operand means the * current job (the newest), `-a` every job, `-r` the running ones, and * `%N`/`N` specs name jobs; `-h` marks a job to survive SIGHUP and leaves * it in the table, a no-op here since no hangup is ever delivered. A spec * naming no job is `no such job`, exit 1, and the others still drop. */ export declare function handleDisown(jobTable: JobTable, parts: string[], session?: SessionState | null, _view?: SessionView | null): Promise<RedirectResult>; /** * Foreground a background job: print its command line, then block on it * and answer its exit code. Its output goes where it always went, as it * is written, so the command line goes out first: to `sink`, where the * statement writes, before the job's next bytes. With no operand it takes * the newest running job, which is bash's current job; when none runs, it * takes the newest finished one, as `fg %N` would. */ export declare function handleFg(jobTable: JobTable, parts: string[], session?: SessionState | null, _view?: SessionView | null, signal?: AbortSignal, sink?: JobConsole): Promise<RedirectResult>; /** * Signal managed runners with bash's kill surface. The signal comes from * `-s`/`-n`, or from the first `-sigspec`; `0` probes and every other * signal cancels the runner with it. Every operand is tried and each failure is * named in bash's words; the status is 0 when any operand was signalled, * as bash's is. A job spec is `%N`; a negative number is a process group, * which no managed runner leads. `owner:pid` names another workspace's * runner, as `ps` lists it: its owner stops it once it takes the stop. */ export declare function handleKill(jobTable: JobTable, parts: string[], session?: SessionState | null, _view?: SessionView | null): Promise<RedirectResult>; /** * List jobs, with bash's flags applied to mirage's row shape. * * `-p` prints the managed PID; `-s` lists nothing because suspended * processes are unsupported. `-r` keeps running jobs, `-l` adds the PID, and * `-n` lists only the jobs whose status changed since the last `jobs` * (which is every completed one not yet reaped, since reaping is what a * listing does). A jobspec operand (`%2` or `2`) filters to that job; * one that names no job is `no such job`, exit 1. `-x` is not carried, * and an unknown letter is GNU's usage line, exit 2. */ export declare function handleJobs(jobTable: JobTable, parts: string[], session?: SessionState | null, _view?: SessionView | null): Promise<RedirectResult>; /** * The shortest start of each owner's id, six characters at least, that no * other owner's begins with, as `ps` names their processes. */ export declare function ownerTags(owners: readonly string[]): Map<string, string>; /** * List managed runners with procps's selection and `-o` columns. A runner * has no CPU, RSS or TTY accounting, so without `-o` the rows stay mirage's * compact `PID<TAB>COMMAND` and never broaden the profile's view. `-o` lays * out procps-ng 4.0.4's columns, every key a runner can answer (PS_COLUMNS); * a header row prints unless every header is empty. Selecting nothing (`-p` * of an absent PID) exits 1, as procps does, and an option error is * procps's message and usage. * * The runners other workspaces on a shared store run follow this * workspace's, as `owner:pid` with the owner's id shortened as far as it * stays unique, within the same view. In the compact rows each runner is followed by the native runs * it has going, a host program by its host PID and a sandbox's by its * runtime and tag, each as `-<TAB>└ where: command`. */ export declare function handlePs(jobTable: JobTable, parts: string[], session?: SessionState | null, _view?: SessionView | null): Promise<RedirectResult>; //# sourceMappingURL=jobs.d.ts.map