/** * The interpreter contract: a model writes a snippet of code that calls the agent's tools, and the * snippet runs in one step, instead of one model round trip per call. A loop over fifty records, a * filter on a large result, or three calls at once become one tool call. * * The package ships the contract, a reference that runs code in a worker thread with time and memory * limits, a tool that puts an interpreter in front of a model, and a conformance suite. Like the * reference sandbox, the reference interpreter is not a security boundary: code in a worker can do * anything the process can. Run untrusted code in an interpreter behind a container or a VM. */ import type { ToolDefinition } from '../types/messages.js'; import type { PermissionPolicyLike } from './permissions.js'; /** A function the code calls as `await tools.(args)`. It runs outside the interpreter. */ export type InterpreterFunction = (args: Record) => Promise; /** Options for one run. */ export interface InterpreterRunOptions { /** The functions the code may call, by name. */ tools?: Readonly>; /** Stops the code after this many milliseconds. */ timeoutMs?: number; /** Stops the code when aborted. */ signal?: AbortSignal; } /** One call the code made. */ export interface InterpreterCall { /** The function's name. */ name: string; /** Its arguments. */ args: unknown; /** Whether it succeeded. */ ok: boolean; } /** What a run did. */ export interface InterpreterResult { /** True when the code returned; false when it threw, was stopped, or ran out of memory. */ ok: boolean; /** What the code returned, when it returned. */ value?: unknown; /** What it threw, or why it was stopped. */ error?: string; /** What it logged with `console`, one entry per call, cut to the interpreter's limit. */ logs: string[]; /** The calls it made, in the order it made them. */ calls: InterpreterCall[]; /** True when it was stopped by its timeout. */ timedOut: boolean; /** How long it ran, in milliseconds. */ durationMs: number; } /** Runs code. The application provides one, or uses `workerInterpreter()`. */ export interface Interpreter { /** Names the interpreter in reports. */ readonly name: string; /** The language its code is written in, for the model, such as `JavaScript`. */ readonly language: string; /** * Runs code: the body of an async function, which can `await tools.(args)` and `return` a * value. A run never throws; what went wrong is in the result. */ run(code: string, options?: InterpreterRunOptions): Promise; /** Releases the interpreter. */ dispose?(): Promise; } /** Options for `workerInterpreter()`. */ export interface WorkerInterpreterOptions { /** The timeout for a run that sets none. Defaults to 10 seconds. */ timeoutMs?: number; /** The heap one run may use, in megabytes. Defaults to 64. */ memoryMb?: number; /** What one run may log, in characters. Defaults to 64,000. */ maxLogChars?: number; /** The most calls one run may make. Defaults to 100. */ maxCalls?: number; } /** * A reference interpreter, for JavaScript: each run gets a fresh worker thread with a heap limit, * stopped at its timeout, so an endless loop or a runaway allocation ends the run, not the process. * Calls to `tools` cross back to the host and run there. It is not a security boundary: the code runs * with the process's own access. */ export declare function workerInterpreter(options?: WorkerInterpreterOptions): Interpreter; /** Options for `codeTool()`. */ export interface CodeToolOptions { /** The tools the code may call. A tool the agent should not call from code stays out of this list. */ tools: readonly ToolDefinition[]; /** * Decides each call the code makes, as an agent's policy decides a model's. A call it would ask a * person about is refused instead, since code cannot pause for one; the model can make that call * directly. Without one, every call runs. */ permissions?: PermissionPolicyLike; /** The tool's name. Defaults to `run_code`. */ name?: string; /** The timeout for one run. Defaults to the interpreter's. */ timeoutMs?: number; } /** * A tool that runs a model's code in an interpreter, with `tools` callable from it, and returns what * the code returned and logged, and the calls it made. It declares `code`, so a permission policy must * grant code before it runs at all; each call the code makes is then decided on its own. */ export declare function codeTool(interpreter: Interpreter, options: CodeToolOptions): ToolDefinition; /** What `runInterpreterConformance()` found. */ export interface InterpreterConformanceReport { /** The interpreter's name. */ interpreter: string; /** True when every check held. */ passed: boolean; /** Every check, in order. */ checks: Array<{ name: string; ok: boolean; detail?: string; }>; } /** * Checks a JavaScript interpreter against the contract, without a test framework: * * - code returns a value, logs, and calls tools, in order and at once; * - a tool's failure reaches the code as a rejection it can catch, and an unknown tool fails; * - code that throws is reported, and never throws out of `run()`; * - an endless loop is stopped at the timeout, and the interpreter runs again afterwards; * - a runaway allocation is stopped, and the interpreter runs again afterwards. */ export declare function runInterpreterConformance(interpreter: Interpreter): Promise;