/**
 * Bash - Bash Shell Environment
 *
 * A complete bash-like shell environment using a proper AST-based architecture:
 *   Input → Parser → AST → Interpreter → Output
 *
 * This class provides the shell environment (filesystem, commands, variables)
 * and delegates execution to the Interpreter.
 */
import "./timers.js";
import { EventEmitter } from "node:events";
import { AgenticHealer } from "./agentic/agentic-healer.js";
import { BashToolbox } from "./agentic/BashToolbox.js";
import type { AgenticHealerConfig } from "./agentic/types.js";
import { type CommandName } from "./commands/registry.js";
import { type CustomCommand } from "./custom-commands.js";
import type { DestructivePolicy } from "./execution/index.js";
import type { FileSystemSnapshot, IFileSystem, InitialFiles } from "./fs/interface.js";
import { MountableFs } from "./fs/mountable-fs/index.js";
import { type DebuggerBridge, type InterpreterState } from "./interpreter/index.js";
import { type ExecutionLimits } from "./limits.js";
import type { LSPManager } from "./lsp/LSPManager.js";
import { SemanticEngine } from "./lsp/semantic-engine.js";
import { WorkspaceIndexer } from "./lsp/WorkspaceIndexer.js";
import { type NetworkConfig, type SecureFetch } from "./network/index.js";
import type { OtelConfig } from "./observability/otel-types.js";
import type { DefenseInDepthConfig } from "./security/types.js";
import { PermissionManager } from "./services/PermissionManager.js";
import type { ServiceContainer } from "./services/ServiceContainer.js";
import { type BashDelta } from "./state-sync/index.js";
import type { OutputChunk, StreamExecOptions } from "./streaming/types.js";
import type { BashTransformResult, TransformPlugin } from "./transform/types.js";
import type { BashExecResult, Command, ExecResult, FeatureCoverageWriter, OutputSink, TraceCallback } from "./types.js";
/**
 * Metadata for tracking file state to detect staleness and provide suggestions.
 */
export interface FileState {
    content: string;
    timestamp: number;
    offset?: number;
    limit?: number;
    isPartialView?: boolean;
}
export type BashMode = "execute" | "plan";
export type { ExecutionLimits } from "./limits.js";
/**
 * Logger interface for Bash execution logging.
 * Implement this interface to receive execution logs.
 */
export interface BashLogger {
    /** Log informational messages (exec commands, stderr, exit codes) */
    info(message: string, data?: Record<string, unknown>): void;
    /** Log debug messages (stdout output) */
    debug(message: string, data?: Record<string, unknown>): void;
}
export interface JavaScriptConfig {
    /** Bootstrap JavaScript code to run before user scripts */
    bootstrap?: string;
}
/**
 * Interface for interactive permission approval.
 */
export interface PermissionHandler {
    /**
     * Ask the user for permission.
     * Returns true if granted, false otherwise.
     */
    ask(message: string): Promise<boolean>;
}
/**
 * Configuration for creating a Bash shell instance.
 *
 * @example
 * ```ts
 * const bash = new Bash({
 *   cwd: "/project",
 *   files: { "/project/hello.sh": "echo hello" },
 *   executionLimits: { maxOutputSize: 1024 * 1024 },
 * });
 * ```
 */
export interface BashOptions {
    /** Initial files to populate the virtual filesystem with. */
    files?: InitialFiles;
    /** Environment variables available to scripts (merged with defaults). */
    env?: Record<string, string>;
    /** Initial working directory. Defaults to "/". */
    cwd?: string;
    /** Custom filesystem implementation. Defaults to an in-memory FS. */
    fs?: IFileSystem;
    /** Which built-in command sets to register (e.g., "grep", "jq"). */
    commands?: CommandName[];
    /** User-defined commands added to the shell. */
    customCommands?: CustomCommand[];
    /** Resource limits (output size, execution time, recursion depth). */
    executionLimits?: ExecutionLimits;
    persistState?: boolean;
    sleep?: (ms: number) => Promise<void>;
    onCommandNotFound?: (command: string, args: string[]) => Promise<ExecResult | null>;
    persistence?: {
        root: string;
        mountPoint?: string;
    };
    /** WASM-based language runtimes (Python via CPython, JS via QuickJS). */
    runtimes?: {
        python?: boolean;
        javascript?: boolean | JavaScriptConfig;
    };
    /** Network access control: allowlists, transforms, and fetch overrides. */
    network?: NetworkConfig;
    fetch?: SecureFetch;
    /** Sandbox security hardening (defense-in-depth, process identity spoofing). */
    security?: {
        defenseInDepth?: DefenseInDepthConfig | boolean;
        processInfo?: {
            pid?: number;
            ppid?: number;
            uid?: number;
            gid?: number;
        };
    };
    /** AI agent integration: auto-healing, permission prompts, nesting control. */
    agentic?: {
        enabled?: boolean;
        healer?: AgenticHealerConfig;
        permissionHandler?: PermissionHandler;
        nestingDepth?: number;
    };
    parser?: {
        engine?: "legacy" | "tree-sitter";
        treeSitterConfig?: {
            webTreeSitterWasm: string | Uint8Array;
            bashGrammarWasm?: string | Uint8Array;
            grammars?: Record<string, string | Uint8Array>;
        };
    };
    debug?: {
        logger?: BashLogger;
        trace?: TraceCallback;
        coverage?: FeatureCoverageWriter;
        debugger?: DebuggerBridge;
        semanticEngine?: SemanticEngine;
    };
    /** Override default service implementations (dependency injection). */
    services?: Partial<ServiceContainer>;
    /**
     * Optional OpenTelemetry configuration for exec-level tracing.
     * When provided, an AgBashTracer is initialized and wraps each exec() call
     * in a span. If @opentelemetry/api is not installed, the tracer is a no-op
     * with zero overhead.
     */
    otel?: OtelConfig;
    /**
     * Default execution engine for exec() calls that do not specify execMode.
     * - "pipeline" (default, v6.0.0): the composable ExecutionPipeline.
     * - "monolith": preserved for backward type compatibility but now routes
     *   through the pipeline (the inline monolith code was removed in v6.0.0).
     * Defaults to "pipeline". Per-call `ExecOptions.execMode` overrides this.
     */
    execMode?: "monolith" | "pipeline";
    /**
     * Default policy for the AST-based destructive-command gate (E2). The gate is
     * a pipeline stage that runs after parse / before interpret and analyzes the
     * parsed AST so obfuscations (command substitution, $IFS, fork bombs,
     * decode-pipe-to-shell) are caught structurally.
     * - "warn" (DEFAULT): attach a typed Observation + stderr warning, then STILL
     *   execute (non-blocking — never breaks commands that ran before).
     * - "block": short-circuit with a non-zero result WITHOUT interpreting.
     * - "prompt": no in-process interactive prompt; falls back to block + a note.
     * - "allow": disable the gate.
     * Per-call `ExecOptions.destructivePolicy` overrides this.
     */
    destructivePolicy?: DestructivePolicy;
}
export interface ExecOptions {
    /**
     * Environment variables to set for this execution only.
     * These are merged with the current environment and restored after execution.
     */
    env?: Record<string, string>;
    /**
     * If true, start execution with an empty environment and then apply `env`.
     * If false/omitted, `env` is merged into the current environment.
     */
    replaceEnv?: boolean;
    /**
     * Working directory for this execution only.
     * Restored to original after execution.
     */
    cwd?: string;
    /**
     * If true, skip normalizing the script (trimming leading whitespace from lines).
     * Useful when running scripts where leading whitespace is significant (e.g., here-docs).
     * Default: false
     */
    rawScript?: boolean;
    /**
     * Standard input to pass to the script.
     * This will be available to commands via stdin (e.g., for `bash -c 'cat'`).
     */
    stdin?: string;
    /**
     * Abort signal for cooperative cancellation.
     * When aborted, the interpreter stops executing at the next statement boundary.
     */
    signal?: AbortSignal;
    /**
     * Additional argv entries appended to the first executed command at the interpreter level.
     * Values bypass shell parsing entirely — no escaping, splitting, or globbing.
     * Like child_process.spawnSync(cmd, args). These do not set or modify the shell's
     * positional parameters ($1, $2, "$@", etc.).
     */
    args?: string[];
    /**
     * If true, commit execution state back to the Bash instance after success.
     * Persists CWD, environment variables, and functions.
     */
    persistState?: boolean;
    /**
     * Optional debugger for statement-level control (specific to this call).
     */
    debugger?: DebuggerBridge;
    /**
     * Optional semantic engine for AST analysis (specific to this call).
     */
    semanticEngine?: SemanticEngine;
    /**
     * Optional agentic healer (specific to this call).
     */
    agenticHealer?: AgenticHealer;
    /**
     * Optional session ID for stateful REPLs (js-exec, python3).
     */
    sessionId?: string;
    /**
     * Execution engine to use for this call.
     * - "pipeline" (default, v6.0.0): the composable ExecutionPipeline.
     * - "monolith": preserved for backward type compatibility but now routes
     *   through the pipeline (the inline monolith code was removed in v6.0.0).
     * Overrides the instance-level `defaultExecMode`.
     */
    execMode?: "monolith" | "pipeline";
    /**
     * Per-call override for the AST-based destructive-command gate (E2).
     * - "warn" (default): attach an Observation + stderr warning but STILL execute.
     * - "block": short-circuit with a non-zero result without interpreting.
     * - "prompt": no in-process interactive prompt, so falls back to block.
     * - "allow": disable the gate for this call.
     * Overrides the instance-level `BashOptions.destructivePolicy`.
     */
    destructivePolicy?: DestructivePolicy;
    /**
     * Opt-in incremental output sink (true streaming). When provided, the
     * interpreter invokes it with stdout/stderr fragments as statements produce
     * them, preserving order. When OMITTED, exec() is byte-identical to the
     * buffered path with zero measurable overhead — the sink is never created or
     * invoked. Primarily used by {@link StreamingExecutor} / {@link Bash.execStream}.
     */
    onChunk?: OutputSink;
}
/**
 * A sandboxed bash shell with a virtual filesystem, built-in commands, and
 * optional WASM runtimes. Safe to run untrusted scripts — all I/O stays in-memory.
 *
 * @example
 * ```ts
 * import { Bash } from "@ag-bash/bash";
 *
 * const bash = new Bash({ cwd: "/app", files: { "/app/data.txt": "hello" } });
 * const result = await bash.exec("cat /app/data.txt | wc -c");
 * console.log(result.stdout); // "6\n"
 * ```
 */
export declare class Bash extends EventEmitter {
    readonly fs: MountableFs;
    private commands;
    private useDefaultLayout;
    readonly limits: Required<ExecutionLimits>;
    private secureFetch?;
    private sleepFn?;
    /**
     * Tracks the state of files read or written during the session.
     * Key is the absolute path to the file.
     */
    readonly fileState: Map<string, FileState>;
    /**
     * Creates a new Bash shell instance.
     */
    private traceFn?;
    private logger?;
    private defenseInDepthConfig?;
    private coverageWriter?;
    private jsBootstrapCode?;
    private onCommandNotFound?;
    private transformPlugins;
    private defaultPersistState;
    private readonly otelTracer?;
    private readonly defaultExecMode;
    /**
     * Instance-level default policy for the AST destructive-command gate (E2).
     * Defaults to "warn" (non-blocking). Per-call `ExecOptions.destructivePolicy`
     * overrides this inside the DestructiveStage.
     */
    private readonly defaultDestructivePolicy;
    /** Lazily-built pipeline for the "pipeline" execMode (cached per instance). */
    private executionPipeline?;
    /** Lazily-built streaming executor for execStream() (cached per instance). */
    private streamingExecutor?;
    private parserEngine;
    private treeSitterConfig?;
    private agentic;
    private debugger?;
    semanticEngine: SemanticEngine;
    indexer: WorkspaceIndexer;
    private agenticHealer?;
    toolbox: BashToolbox;
    permissionManager: PermissionManager;
    readonly nestingDepth: number;
    readonly services: ServiceContainer;
    private state;
    private snapshots;
    readonly options: BashOptions;
    constructor(options?: BashOptions);
    /**
     * Close a persistent session and terminate its worker.
     */
    closeSession(sessionId: string): Promise<void>;
    /**
     * Sets the current mode of the shell (execute or plan).
     */
    setMode(mode: BashMode): void;
    /**
     * Gets the current mode of the shell.
     */
    getMode(): BashMode;
    get cwd(): string;
    get env(): Record<string, string>;
    get lsp(): LSPManager;
    private initLsp;
    /**
     * Updates the tracked state for a file.
     */
    updateFileState(path: string, state: Partial<FileState>): void;
    /**
     * Gets the tracked state for a file.
     */
    getFileState(path: string): FileState | undefined;
    registerCommand(command: Command): void;
    private logResult;
    exec(commandLine: string, options?: ExecOptions): Promise<BashExecResult>;
    /**
     * Build (and cache) the ExecutionPipeline used by the "pipeline" execMode.
     *
     * The stages mirror the monolithic Bash.exec() body exactly:
     *   normalize → parse → transform → sandbox → destructive → interpret → persist
     * with error categorization + UTF-8 decode/log applied by the pipeline
     * runner (via the finalize callback and its internal catch).
     *
     * Parity-critical wiring:
     * - requireDefenseContext is computed from the REAL DefenseInDepthBox's
     *   isEnabled() (NOT inferred from the handle), matching Bash.ts monolith.
     * - The finalize callback is this.logResult (decode binary→UTF-8 + log),
     *   applied to every result leaving the pipeline (success AND error).
     * - The persist callback performs the exact 7-field commit-back the monolith
     *   does (cwd/env/functions/hashTable by reference; shoptOptions/options via
     *   spread; lastExitCode), gated on exit 0 inside PersistStage.
     * - execFn = this.exec.bind(this) so recursive execs re-enter exec() and hit
     *   the command-count guard (which lives in exec(), before this branch).
     * - this.services is passed so astCache + sharedBus are SHARED, matching
     *   the monolith's this.services usage.
     */
    private buildExecutionPipeline;
    /**
     * Execute a script through the composable ExecutionPipeline.
     *
     * The instance-coupled prologue (command-count guard, empty short-circuit,
     * PWD/cwd derivation, execEnv + execState construction) has ALREADY run in
     * exec() before this is called; we receive the finished execState and pass
     * the RAW commandLine so NormalizeStage performs (idempotent) normalization,
     * keeping the pipeline self-contained for AST-cache keying.
     *
     * NOTE on requireDefenseContext caching: the pipeline computes it once at
     * build time from the singleton DefenseInDepthBox. The box's isEnabled() is a
     * pure function of its (config.enabled, AsyncLocalStorage availability), which
     * cannot change for a given Bash instance, so caching is safe and matches the
     * monolith's per-call recomputation.
     */
    private execViaPipeline;
    /**
     * Execute a script and stream its output INCREMENTALLY as commands produce
     * it, yielding {@link OutputChunk} objects via an AsyncGenerator.
     *
     * Unlike {@link exec} (which buffers everything and returns once), this emits
     * stdout/stderr fragments in production order as each statement runs, then a
     * final `exit` chunk carrying the exit code. The concatenation of streamed
     * stdout chunks is byte-identical to `(await exec(script)).stdout`.
     *
     * Implemented atop the opt-in {@link ExecOptions.onChunk} sink; buffered
     * exec() is unaffected when execStream is not used.
     *
     * @example
     * ```ts
     * for await (const chunk of bash.execStream("echo a; echo b")) {
     *   if (chunk.type === "stdout") process.stdout.write(chunk.data);
     * }
     * ```
     */
    execStream(script: string, options?: StreamExecOptions): AsyncGenerator<OutputChunk, void, undefined>;
    /**
     * Create a snapshot of the current shell state, including filesystem changes.
     * Useful for "branching" execution in agentic workflows or reverting
     * to a known-good state after trial execution.
     */
    snapshot(): Promise<BashSnapshot>;
    /**
     * Creates a differential delta between a base snapshot and current state.
     */
    createDelta(base: BashSnapshot): Promise<BashDelta>;
    /**
     * Applies a differential delta to the current state.
     */
    applyDelta(delta: BashDelta): Promise<void>;
    /**
     * Restores the shell to a previously captured snapshot.
     */
    restore(snapshot: BashSnapshot): Promise<void>;
    /**
     * Save a named snapshot of the current state.
     */
    saveSnapshot(name: string): Promise<void>;
    /**
     * Restore a named snapshot.
     */
    restoreSnapshot(name: string): Promise<void>;
    /**
     * Fork the sandbox into an independent copy-on-write branch.
     *
     * Returns a NEW {@link Bash} instance that, at the moment of the call, is an
     * exact copy of this one (env, cwd, functions, shell options, and the entire
     * virtual filesystem) but shares NOTHING mutable with the parent. The child
     * is independently executable; mutations in the child — environment changes,
     * `cd`, function (re)definitions, and filesystem writes — are invisible to
     * the parent, and parent mutations after the fork are invisible to the child.
     *
     * This is the core primitive for fork-speculation: an agent forks N branches,
     * runs candidate command sequences in parallel, then keeps the winner and
     * discards the rest (discarding is just dropping the child reference).
     *
     * Forking is cheap because the underlying snapshot deep-copies state and the
     * copy-on-write VFS only materializes mutated entries.
     *
     * Note: host-backed mounts (e.g. {@link usePersistence} via `ReadWriteFs`)
     * write through to the real filesystem and are therefore NOT isolated by the
     * fork — only the in-VFS layers are copy-on-write. Use an in-memory sandbox
     * for fully isolated speculation.
     *
     * @returns A new, fully isolated `Bash` branch.
     */
    fork(): Promise<Bash>;
    /**
     * Speculatively run candidate branches in isolated forks and collect their
     * results, leaving this (parent) instance untouched.
     *
     * Each branch receives its own {@link fork} of the current sandbox and runs
     * concurrently. Results are returned in branch order so the caller can score
     * them and "keep the winner" (e.g. by re-applying the winning command on the
     * parent). Discarded branches require no cleanup — their references are simply
     * dropped.
     *
     * @typeParam T - The result type each branch produces.
     * @param branches - Candidate functions, each given an isolated child `Bash`.
     * @returns The branch results, in the same order as `branches`.
     */
    speculate<T>(branches: Array<(branch: Bash) => Promise<T>>): Promise<T[]>;
    /**
     * Save the workspace symbol index to disk.
     */
    saveIndex(): Promise<void>;
    /**
     * Load the workspace symbol index from disk.
     */
    loadIndex(): Promise<void>;
    /**
     * Mount a filesystem at the specified virtual path.
     */
    mount(mountPoint: string, filesystem: IFileSystem): void;
    /**
     * Configure persistent storage for a specific path.
     * In Node.js, this mounts a ReadWriteFs directly to the host filesystem.
     */
    usePersistence(root: string, mountPoint?: string): Promise<void>;
    /**
     * Unmount the filesystem at the specified path.
     */
    unmount(mountPoint: string): void;
    /**
     * Deep-clone the interpreter state to ensure isolation.
     */
    private cloneState;
    readFile(path: string): Promise<string>;
    writeFile(path: string, content: string): Promise<void>;
    readFileDirect(path: string): Promise<string>;
    writeFileDirect(path: string, content: string): Promise<void>;
    listDirDirect(path: string): Promise<string[]>;
    existsDirect(path: string): Promise<boolean>;
    mkdirDirect(path: string, recursive?: boolean): Promise<void>;
    rmDirect(path: string, recursive?: boolean): Promise<void>;
    getCwd(): string;
    getEnv(): Record<string, string>;
    registerTransformPlugin(plugin: TransformPlugin<any>): void;
    transform(commandLine: string): BashTransformResult;
    destroy(): void;
    [Symbol.asyncDispose](): Promise<void>;
}
/**
 * Snapshot of a Bash instance state.
 */
export interface BashSnapshot {
    state: InterpreterState;
    fs: FileSystemSnapshot;
}
