/** * executeCode — the top-level entry point that ties protocol + server + * stub generator + child-process lifecycle into one call. * * Flow: * 1. Generate the memi_tools stub for the per-call allowlist * 2. Write the stub + the user's script to a temp directory * 3. Open a fresh Unix-socket-backed ToolsRpcServer * 4. Spawn a child Bun (or Node) process with: * MEMI_TOOLS_SOCKET= * cwd= * scrubbed env (no API keys leaked into the script) * 5. Wait for the script to send `exit` or for stdout/stderr to close * 6. Tear everything down (kill the child if it's still running, remove * the socket file, remove the temp dir) * 7. Return { ok, result, error, logs, durationMs, stdout, stderr } * * Subprocess runtime is configurable so tests can use Node + a fake * script and production can use Bun (faster startup, native TS). */ import { type StubToolSpec } from "./stub-generator.js"; import { type ScriptLogEntry, type ToolRunner } from "./tools-rpc-server.js"; export interface ExecuteCodeRequest { /** TypeScript source the user (or LLM) wants to execute. */ readonly script: string; /** Tool surface the script may call. */ readonly tools: ReadonlyArray; /** Working directory for the child process. Defaults to process.cwd(). */ readonly cwd?: string; /** Wall-clock cap for the script. Defaults to 60s. */ readonly timeoutMs?: number; /** Memory cap (passed as --max-old-space-size for Node, ignored for Bun). */ readonly memoryMb?: number; /** * Subprocess runner. Defaults to "tsx" — works on Node 20+ and supports * TS natively without flags. Override with "bun" for faster startup or * "node" for Node 22+'s native --experimental-strip-types path. Tests * inject a custom value when needed. */ readonly runtime?: "tsx" | "bun" | "node" | { command: string; argsBefore?: readonly string[]; argsAfter?: readonly string[]; }; /** Whitelisted env keys forwarded to the child. Default: only PATH + TZ + LANG. */ readonly envAllowlist?: readonly string[]; /** Extra env entries injected before the child starts. */ readonly envExtra?: Readonly>; } export interface ExecuteCodeResult { readonly ok: boolean; readonly result?: unknown; readonly error?: string; readonly logs: ReadonlyArray; readonly stdout: string; readonly stderr: string; readonly exitCode: number | null; readonly signal: NodeJS.Signals | null; readonly durationMs: number; } export declare function executeCode(req: ExecuteCodeRequest, runner: ToolRunner): Promise;