UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

172 lines • 9.74 kB
import type { MountResolver } from '../runtime/resolver.ts'; import type { DispatchFn } from '../runtime/types.ts'; import type { ResolvedSource } from '../secrets/types.ts'; import { type JsonValue } from '../types.ts'; import type { Policy } from './base.ts'; import { SESSION_SCOPED, type SessionScopedMixin } from './mixin.ts'; import { type Ask, type CommandContext, type CommandResultContext, type Deny, type ExecuteResultContext, type NetworkContext, type NetworkResultContext, type PolicyMethod, type ProfileScript, type Route, type RouteContext, type ScriptMethod, type SessionContext, type SessionResultContext, type SessionScriptsQuery, type VfsContext, type VfsResultContext, type WorkspaceContext } from './types.ts'; /** * A policy context as a program reads it: every field a coded policy * reads, under the Python name, as plain data. The live handles become * data: the session its `cwd`, `env` and `profile`, the namespace the * `mounts` the session sees. The files are the program's own `open()`, * which reads as the session. Each of a line's `commands` also holds the * `env` it runs with, its own `NAME=value` prefix included. Mirrors the * Python `script_context`. */ export declare function scriptContext(ctx: CommandContext | RouteContext | VfsContext | SessionContext | WorkspaceContext | NetworkContext): Record<string, JsonValue>; /** * The answer a policy program printed at one method. * * Nothing (or `null`) is no opinion. Anything else is one JSON answer * (`Answer`): `{"kind": "deny", "reason": ...}`, `{"kind": "ask", * "reason": ...}`, or at `preExecute` `{"kind": "route", "runtime": ...}`. * A deny or an ask without a reason carries the document's default one. * Throws a plain Error whose message is a clause about "script", for the * caller to prefix with whose policy it is. Mirrors the Python * `script_action`. */ export declare function scriptAction(output: Uint8Array, method: PolicyMethod): Deny | Ask | Route | null; /** * The workspace's file calls, for the runtime a profile's programs run on. * * Some judgments are about what a file holds rather than what it is * called. The runtime is attached with these exactly as `Runtimes` * attaches an agent's, so a program's `open()` reads the mounts through * the same entry point an agent's program would, and a read from a policy * clears the dispatcher like any other. The dispatch is built for one * `issuer`, the policy's own token: every op it dispatches carries the * token to the dispatcher (`VfsContext.issuer`), which is how the * policy's `preVfs` tells its own read from anyone else's. The workspace * supplies them; a bare ScriptPolicy (outside a workspace) has none, and * its programs see no file. */ export interface ScriptWiring { dispatch: (issuer: symbol) => DispatchFn; resolver: MountResolver; } /** * Each profile's policy programs, run at the `pre` methods. * * The scripted twin of `PermissionsPolicy`, registered right after it: * where that policy evaluates the document's declarative rules, this one * runs the profile's programs. A profile names, per method, a list of * programs and the runtime each runs on; they are asked in order, up to * the first deny, and their answers reach the chain as one array, each * read as if its own policy had said it: an Ask from one program and a * Route from another both stand, and two routes that disagree refuse the * line. A method with no program is silence and costs nothing. It reads the * session's programs through the narrow `SessionScriptsQuery` by the * session id the entry point put in the context. * * A program runs as any program does on its runtime: never edited, in the * session's cwd, with the context as JSON (`scriptContext`) in `CTX_ENV` * and on stdin, and its answer printed on stdout (`scriptAction`). * Beside `CTX_ENV` it is passed only its entry's own `env`, a pointer read * from the workspace's sources on the entry's first run and kept: the * session's variables are in the context, so none the agent sets changes * how the program starts, * and on pyodide it runs with `-P` (`PROGRAM_FLAGS`), so no file the agent * writes stands in for a module it imports. Every failure fails closed: a * program that exits non-zero, runs past the timeout, prints something * else, or names a runtime that cannot be built refuses the action with a * reason naming the profile, and is logged. The workspace's `routePolicy` * program runs here too (`run`), outside any profile. * * The runtime is the policy's own, built from the name and settings the * profile gives, shared across sessions and never the agent's, and capped * at `PROGRAM_MEMORY` unless the settings name a `maxMemory`. It is * wired to the workspace's files the way an agent's runtime is * (`ScriptWiring`), so a program reads what an operand holds as the * session reads it. A read from a program clears the dispatcher like any * other, except this policy's own `preVfs`: the policy is the one * asking, and judging its own read would re-enter the run waiting on it. * It knows its own read by `issuer`, a token only its dispatch stamps and * that rides each op as an argument: a mark kept in ambient context would * be whatever op another task dispatched while a read was in flight on a * runtime with no task isolation. Runs on one runtime are serialized; runs * on two runtimes go at once. * * A program on monty may also call the host's `externalLookup` functions * by name, sync or async, with plain data in and out (a dict arrives as * an object, as the Python host's arrives as a dict); one that throws * raises in the program. Its runs go at once: monty runs each on a worker * of its own, and a function may be slow or reach the workspace again. No * other runtime sees them. `secretSources` is the workspace's declared * sources an `env` pointer is read from; absent reads each from its * source's ambient defaults. Mirrors the Python `ScriptPolicy`. */ export declare class ScriptPolicy implements Policy, SessionScopedMixin { readonly [SESSION_SCOPED]: true; private readonly sessions; private readonly wiring; private readonly engines; private readonly issuer; private readonly queues; private readonly unqueued; private readonly externalLookup; private readonly secretSources; private readonly envs; constructor(sessions: SessionScriptsQuery, wiring?: ScriptWiring | null, options?: { externalLookup?: Readonly<Record<string, (...args: never[]) => unknown>> | undefined; secretSources?: (() => Promise<Readonly<Record<string, ResolvedSource>>>) | undefined; }); preExecute(ctx: RouteContext): Promise<(Deny | Ask | Route)[] | null>; preCommand(ctx: CommandContext): Promise<(Deny | Ask | Route)[] | null>; preVfs(ctx: VfsContext): Promise<(Deny | Ask | Route)[] | null>; preSession(ctx: SessionContext): Promise<(Deny | Ask | Route)[] | null>; preWorkspace(ctx: WorkspaceContext): Promise<(Deny | Ask | Route)[] | null>; preNetwork(ctx: NetworkContext): Promise<(Deny | Ask | Route)[] | null>; postNetwork(ctx: NetworkResultContext): Promise<(Deny | Ask | Route)[] | null>; postExecute(ctx: ExecuteResultContext): Promise<(Deny | Ask | Route)[] | null>; postCommand(ctx: CommandResultContext): Promise<(Deny | Ask | Route)[] | null>; postVfs(ctx: VfsResultContext): Promise<(Deny | Ask | Route)[] | null>; postSession(ctx: SessionResultContext): Promise<(Deny | Ask | Route)[] | null>; /** Whether this session's profile names a program at `method`. */ wantsFor(method: PolicyMethod, sessionId: string): Promise<boolean>; /** * One program's answer at one method, outside any profile: the * workspace's `routePolicy`. * * @throws Error - the program failed: it exited non-zero, ran past the * timeout, printed something else, or names a runtime that cannot be * built. The message says what, as a clause for the caller to prefix * with whose program it is. */ run(entry: ProfileScript, method: ScriptMethod, ctx: CommandContext | RouteContext | VfsContext | SessionContext | NetworkContext): Promise<Deny | Ask | Route | null>; /** Close every runtime a program ran on. */ close(): Promise<void>; /** * Every program the session's profile names at one method, each answer * in order, up to the first deny. */ private judge; /** * The directory a program starts in: the session's, or `/` once the * session's has gone, since a runtime that enters it first cannot start * in a directory that is not there. */ private cwd; /** One program at one method; throws a clause about "script" when it fails. */ private answer; /** * The policy's own runtime for one program, built on first use and * shared by every program naming the same runtime and settings. Throws * a clause about "script" when the runtime is not one a policy program * runs on, or cannot be built here. */ private engine; /** * One program's `env` with every pointer read: one read per program, * shared by the runs waiting on it and kept once it answers, given the * program's timeout and retried by the next run after it fails or runs * out of time. Throws a clause about "script" when a source cannot * answer. */ private env; /** One read of a program's `env` pointers; throws a clause about "script" when a source cannot answer. */ private readEnv; /** `work` after every run on `engine` before it: two runs on one runtime would interleave. */ private serialized; } //# sourceMappingURL=script.d.ts.map