UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

382 lines • 17.4 kB
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= import { CommandSpec, Argument } from "../types.js"; import { PATHS_OPERAND, REMAINDER_OPERAND, TEXTS_OPERAND, TEXT_OPERAND } from "../constants.js"; // CPython's own option table, minus four switches that describe a // process mirage does not have: -i (drop to an interactive prompt), -d // (parser debug, a debug-build-only switch), -v (trace every import to // stderr) and the --help-env/--help-xoptions/--help-all dumps, which // document a CPython build rather than this command. Everything else // CPython accepts, this accepts. // // The four groups differ in who answers them: -c/-m select the source // and end option parsing (their argument is a program, so trailing // words are that program's argv); -x also selects source, by dropping // the script file's first line, and is answered where the program is // resolved (resolveProgram) because every engine reads the same resolved // text; the init switches are handed to the runtime in its ctx.flags and honored // by whichever engine can; -u reaches a spawned CPython, the one engine // that buffers its output. Pinned against CPython 3.12.11. const PYTHON_OPTIONS = [ new Argument('-c', { help: 'Run the next argument as a program.' }), new Argument('-m', { help: 'Run the named module as __main__.' }), new Argument('-u', { action: 'store_true', help: 'Force the stdout and stderr streams to be unbuffered.', }), new Argument('-b', { action: 'count', help: 'Warn on str(bytes) and on comparing bytes with str; -bb raises instead.', }), new Argument('-B', { action: 'store_true', help: 'Do not write .pyc files on import.' }), new Argument('-E', { action: 'store_true', help: 'Ignore PYTHON* environment variables.' }), new Argument('-I', { action: 'store_true', help: 'Isolated mode: implies -E and -s.' }), new Argument('-O', { action: 'count', help: 'Remove assert and __debug__ blocks; -OO also strips docstrings.', }), new Argument('-P', { action: 'store_true', help: "Do not prepend the script's directory to sys.path.", }), new Argument('-q', { action: 'store_true', help: '(Ignored) Suppress the version banner. Mirage prints none.', }), new Argument('-s', { action: 'store_true', help: 'Do not add the user site directory to sys.path.', }), new Argument('-S', { action: 'store_true', help: "Do not run 'import site' on initialization." }), new Argument('-W', { action: 'append', help: 'Set a warning control filter.' }), new Argument('-x', { action: 'store_true', help: "Skip the script file's first line, for a non-Unix #! form.", }), new Argument('-X', { action: 'append', help: 'Set an implementation-specific option.' }), // CPython parses this one by hand and so rejects the --opt=value // spelling it accepts everywhere else; mirage's parser takes both, // which is the harmless direction to diverge in. new Argument('--check-hash-based-pycs', { choices: ['always', 'default', 'never'], help: 'How to validate hash-based .pyc files.', }), // -VV shares the concise version line; build details are not exposed. new Argument(['-h', '--help'], { action: 'store_true', help: 'Show this help message and exit.', }), new Argument(['-V', '--version'], { action: 'store_true', help: 'Show version information and exit.', }), ]; // CPython's own synopsis, `[-c cmd | -m mod | file | -] [arg] ...`: the // first operand is a file the interpreter reads, unless a -c or -m // already named the program, and the words after it are the program's // argv. The slot has to say so, because a runtime that reads the script // itself (a sandbox, a host process) is outside every dispatcher, so the // admission gate is the one place a path rule can see the file. const PYTHON_SCRIPT = new Argument('path', { metavar: '', type: 'path', nargs: '?', providedBy: ['-c', '-m'], }); // node's `[script.js | -e "script" | -] [arguments]`, the same shape. const JS_SCRIPT = new Argument('path', { metavar: '', type: 'path', nargs: '?', providedBy: ['-e'], }); const PYTHON = new CommandSpec({ description: "Run Python on the workspace's bound runtime.", arguments: [...PYTHON_OPTIONS, PYTHON_SCRIPT, REMAINDER_OPERAND], }); // js and node take the remainder for the same reason python does: the // first operand is a program, so the words after it are that program's // argv, not the interpreter's flags. `node - -e x` runs the piped // program and hands it `-e x`; `node s.js -m` hands s.js its own -m. // Pinned against node 22.8.0. const JS = new CommandSpec({ description: 'Run JavaScript on a sandboxed quickjs engine.', arguments: [ new Argument(['-v', '--version'], { action: 'store_true', help: 'Show runtime version information and exit.', }), new Argument('-e', { help: 'Evaluate the next argument as a script.' }), new Argument(['-m', '--module'], { action: 'store_true', help: 'Run as an ES module (top-level import/export/await); .mjs files select this automatically.', }), JS_SCRIPT, REMAINDER_OPERAND, ], }); export const SPECS = { bash: new CommandSpec({ description: 'Run a program in a nested Mirage shell: the text after `-c`, a script file, or standard input. `bash` and `sh` are aliases.', arguments: [ new Argument('-c', { help: 'Read commands from the next argument and execute them.' }), new Argument('-s', { action: 'store_true', help: 'Read commands from stdin instead of from an argument.', }), new Argument('-l', { action: 'store_true', help: '(Ignored) Login shell. Mirage does not source profile files.', }), new Argument('-i', { action: 'store_true', help: '(Ignored) Interactive flag. Mirage shells are non-interactive.', }), new Argument('-e', { action: 'store_true', help: 'Exit on first error.' }), new Argument('-u', { action: 'store_true', help: 'Treat unset variables as errors.' }), new Argument('-x', { action: 'store_true', help: 'Print commands as they execute.' }), new Argument('--debug', { action: 'store_true', help: '(Ignored) Debugging mode.' }), new Argument('--init-file', { help: '(Ignored) Read this file instead of ~/.bashrc.' }), new Argument('--login', { action: 'store_true', help: '(Ignored) Login shell.' }), new Argument('--noediting', { action: 'store_true', help: '(Ignored) No line editing.' }), new Argument('--noprofile', { action: 'store_true', help: '(Ignored) Skip profile files.' }), new Argument('--norc', { action: 'store_true', help: '(Ignored) Skip rc files.' }), new Argument('--posix', { action: 'store_true', help: '(Ignored) POSIX-conformant mode.' }), new Argument('--rcfile', { help: '(Ignored) Read this file instead of ~/.bashrc.' }), new Argument('--verbose', { action: 'store_true', help: 'Print input lines as they are read.', }), TEXTS_OPERAND, ], }), bc: new CommandSpec({ description: 'Arbitrary precision calculator language.', arguments: [ new Argument('-l', { action: 'store_true', help: 'Load the standard math library.' }), new Argument('-q', { action: 'store_true', help: 'Suppress the welcome banner.' }), PATHS_OPERAND, ], }), date: new CommandSpec({ description: 'Print or set the system date and time.', arguments: [ new Argument(['-d', '--date'], { help: 'Display the time described by the given date string.', }), new Argument(['-I', '--iso-8601'], { nargs: '?', attachedOnly: true, choices: ['hours', 'minutes', 'date', 'seconds', 'ns'], help: 'Output date/time in ISO 8601 format, to the given precision (default date).', }), new Argument(['-R', '--rfc-email'], { action: 'store_true', help: 'Output date in RFC 5322 email format.', }), new Argument('--rfc-3339', { choices: ['date', 'seconds', 'ns'], help: 'Output date/time in RFC 3339 format, to the given precision.', }), new Argument(['-u', '--utc'], { action: 'store_true', help: 'Use Coordinated Universal Time (UTC).', }), new Argument('--universal', { action: 'store_true', help: 'Use Coordinated Universal Time (UTC).', }), TEXT_OPERAND, ], }), expr: new CommandSpec({ description: 'Evaluate expressions.', arguments: [TEXTS_OPERAND], }), history: new CommandSpec({ description: 'Print or change the command history.\n\n' + 'With no options, prints the history with a number on each line, or only its last N lines.', epilog: '0 unless an option or OFFSET is invalid.', arguments: [ new Argument('-c', { action: 'store_true', help: 'clear the history' }), new Argument('-d', { metavar: 'offset', help: 'delete the entry at OFFSET; below 0, from the end', }), new Argument('-a', { action: 'store_true', help: 'accepted, with no effect: the history file is the list', }), new Argument('-n', { action: 'store_true', help: 'accepted, with no effect: the history file is the list', }), new Argument('-r', { action: 'store_true', help: 'accepted, with no effect: the history file is the list', }), new Argument('-w', { action: 'store_true', help: 'accepted, with no effect: the history file is the list', }), new Argument('-p', { action: 'store_true', help: 'print each ARG, with no history expansion', }), new Argument('-s', { action: 'store_true', help: 'add the ARGs to the history as one entry', }), TEXTS_OPERAND, ], }), js: JS, mktemp: new CommandSpec({ arguments: [ new Argument(['-d', '--directory'], { action: 'store_true' }), new Argument('-p', { type: 'path' }), new Argument('--tmpdir', { type: 'path', nargs: '?', attachedOnly: true }), new Argument('-t', { action: 'store_true' }), new Argument(['-u', '--dry-run'], { action: 'store_true' }), new Argument(['-q', '--quiet'], { action: 'store_true' }), new Argument('--suffix'), TEXT_OPERAND, ], }), node: JS, python: PYTHON, python3: PYTHON, uname: new CommandSpec({ description: 'Print certain system information.', arguments: [ new Argument(['-a', '--all'], { action: 'store_true', help: 'Print all information, omitting -p and -i if unknown.', }), new Argument(['-s', '--kernel-name'], { action: 'store_true', help: 'Print the kernel name.', }), new Argument(['-n', '--nodename'], { action: 'store_true', help: 'Print the network node hostname.', }), new Argument(['-r', '--kernel-release'], { action: 'store_true', help: 'Print the kernel release.', }), new Argument(['-v', '--kernel-version'], { action: 'store_true', help: 'Print the kernel version.', }), new Argument(['-m', '--machine'], { action: 'store_true', help: 'Print the machine hardware name.', }), new Argument(['-p', '--processor'], { action: 'store_true', help: 'Print the processor type.', }), new Argument(['-i', '--hardware-platform'], { action: 'store_true', help: 'Print the hardware platform.', }), new Argument(['-o', '--operating-system'], { action: 'store_true', help: 'Print the operating system.', }), TEXTS_OPERAND, ], }), hostname: new CommandSpec({ description: "Show or set the system's host name.", arguments: [ new Argument(['-a', '--alias'], { action: 'store_true', help: 'Alias names.' }), new Argument(['-A', '--all-fqdns'], { action: 'store_true', help: 'All long host names (FQDNs).', }), new Argument(['-b', '--boot'], { action: 'store_true', help: 'Set default hostname if none available.', }), new Argument(['-d', '--domain'], { action: 'store_true', help: 'DNS domain name.' }), new Argument(['-f', '--fqdn'], { action: 'store_true', help: 'Long host name (FQDN).' }), new Argument('--long', { action: 'store_true', help: 'Long host name (FQDN).' }), new Argument(['-F', '--file'], { help: 'Read host name or NIS domain name from given file.', }), new Argument(['-i', '--ip-address'], { action: 'store_true', help: 'Addresses for the host name.', }), new Argument(['-I', '--all-ip-addresses'], { action: 'store_true', help: 'All addresses for the host.', }), new Argument(['-s', '--short'], { action: 'store_true', help: 'Short host name.' }), new Argument(['-y', '--yp'], { action: 'store_true', help: 'NIS/YP domain name.' }), new Argument('--nis', { action: 'store_true', help: 'NIS/YP domain name.' }), TEXTS_OPERAND, ], }), id: new CommandSpec({ description: 'Print user and group information for each specified USER, or (when USER omitted) for the current process.', arguments: [ new Argument('-a', { action: 'store_true', help: 'Ignore, for compatibility with other versions.', }), new Argument(['-Z', '--context'], { action: 'store_true', help: 'Print only the security context of the process.', }), new Argument(['-g', '--group'], { action: 'store_true', help: 'Print only the effective group ID.', }), new Argument(['-G', '--groups'], { action: 'store_true', help: 'Print all group IDs.' }), new Argument(['-n', '--name'], { action: 'store_true', help: 'Print a name instead of a number, for -u,-g,-G.', }), new Argument(['-r', '--real'], { action: 'store_true', help: 'Print the real ID instead of the effective ID, with -u,-g,-G.', }), new Argument(['-u', '--user'], { action: 'store_true', help: 'Print only the effective user ID.', }), new Argument(['-z', '--zero'], { action: 'store_true', help: 'Delimit entries with NUL characters, not whitespace; not permitted in default format.', }), TEXTS_OPERAND, ], }), getconf: new CommandSpec({ description: 'Get the configuration value for variable VAR, or for variable PATH_VAR for path PATH.', arguments: [ new Argument('-a', { action: 'store_true', help: 'Print every variable and its value.' }), new Argument('-v', { help: 'Give values for compilation environment SPEC.' }), TEXTS_OPERAND, ], }), sleep: new CommandSpec({ description: 'Delay for a specified amount of time.', arguments: [TEXTS_OPERAND], }), }; //# sourceMappingURL=runtime.js.map