/**
 * InterpretStage - Interpreter creation and script execution.
 *
 * Creates the Interpreter instance with appropriate options and
 * runs the parsed AST, producing a BashExecResult. If a defense
 * handle is active, execution runs inside its sandboxed context.
 */
import { Interpreter } from "../../interpreter/index.js";
export class InterpretStage {
    name = "interpret";
    config;
    constructor(config) {
        this.config = config;
    }
    async execute(context) {
        const { ast, options, execState, defenseHandle, metadata } = context;
        if (ast === undefined) {
            // Should never happen if parse stage ran, but guard defensively
            const fallback = {
                stdout: "",
                stderr: "bash: internal error: no AST available\n",
                exitCode: 2,
                env: Object.create(null),
            };
            return { continue: false, result: fallback };
        }
        const interpreterOptions = {
            fs: this.config.fs,
            commands: this.config.commands,
            limits: this.config.limits,
            exec: this.config.execFn,
            fetch: this.config.secureFetch,
            sleep: this.config.sleepFn,
            trace: this.config.traceFn,
            coverage: this.config.coverageWriter,
            requireDefenseContext: this.config.requireDefenseContext,
            jsBootstrapCode: this.config.jsBootstrapCode,
            onCommandNotFound: this.config.onCommandNotFound,
            agentic: this.config.agentic,
            getRegisteredCommands: () => Array.from(this.config.commands.keys()),
            debugger: options?.debugger ?? this.config.debugger,
            semanticEngine: options?.semanticEngine ?? this.config.semanticEngine,
            agenticHealer: options?.agenticHealer ?? this.config.agenticHealer,
            sharedBus: context.services.sharedBus,
            bash: this.config.bash,
            // Per-call opt-in streaming sink (threaded from ExecOptions.onChunk).
            // Undefined for normal buffered execs => byte-identical behavior.
            sink: options?.onChunk,
        };
        const interpreter = new Interpreter(interpreterOptions, execState);
        const executeScript = async () => {
            const result = await interpreter.executeScript(ast);
            const execResult = result;
            if (metadata) {
                execResult.metadata = metadata;
            }
            return execResult;
        };
        const execResult = await (defenseHandle
            ? defenseHandle.run(executeScript)
            : executeScript());
        context.result = execResult;
        return { continue: true, context };
    }
}
