langchainrust 0.5.0

A LangChain-inspired framework for building LLM applications in Rust. Supports OpenAI, Agents, Tools, Memory, Chains, RAG, BM25, Hybrid Retrieval, LangGraph, HyDE, Reranking, MultiQuery, and native Function Calling.
// src/tools/sandbox/e2b.rs
//! E2B cloud sandbox backend.
//!
//! Provides secure code execution via the [E2B](https://e2b.dev/) cloud sandbox API.
//! This backend requires the `sandbox-e2b` feature gate and an E2B API key.
//!
//! # Feature Gate
//!
//! Enable in `Cargo.toml`:
//! ```toml
//! langchainrust = { features = ["sandbox-e2b"] }
//! ```
//!
//! # Configuration
//!
//! Set the `E2B_API_KEY` environment variable with your E2B API key.
//!
//! # TODO
//!
//! This is a stub implementation. The actual E2B API integration requires:
//! - HTTP client calls to the E2B API (`https://api.e2b.dev/`)
//! - Sandbox creation and management (create, connect, execute, close)
//! - Proper error handling for API rate limits and network failures
//! - Support for file system operations within the sandbox

use async_trait::async_trait;

use super::{CodeSandbox, Language, RunResult, SandboxError};

/// E2B cloud sandbox backend.
///
/// Executes code in a secure cloud sandbox provided by E2B.
/// Requires `E2B_API_KEY` environment variable to be set.
pub struct E2BSandbox {
    api_key: String,
    /// Base URL for the E2B API (defaults to `https://api.e2b.dev`).
    base_url: String,
}

impl E2BSandbox {
    /// Create a new E2B sandbox, reading the API key from the `E2B_API_KEY` environment variable.
    ///
    /// # Errors
    ///
    /// Returns [`SandboxError::Runtime`] if the `E2B_API_KEY` environment variable is not set.
    pub fn new() -> Result<Self, SandboxError> {
        let api_key = std::env::var("E2B_API_KEY").map_err(|_| {
            SandboxError::Runtime("E2B_API_KEY environment variable is not set".to_string())
        })?;
        Ok(Self {
            api_key,
            base_url: "https://api.e2b.dev".to_string(),
        })
    }

    /// Create an E2B sandbox with a custom API key (e.g., from a secret manager).
    pub fn with_api_key(api_key: impl Into<String>) -> Self {
        Self {
            api_key: api_key.into(),
            base_url: "https://api.e2b.dev".to_string(),
        }
    }

    /// Use a custom base URL (e.g., for self-hosted E2B).
    pub fn with_base_url(mut self, url: impl Into<String>) -> Self {
        self.base_url = url.into();
        self
    }
}

#[async_trait]
impl CodeSandbox for E2BSandbox {
    async fn run(&self, code: &str, language: Language, timeout_ms: u64) -> Result<RunResult, SandboxError> {
        // TODO: Implement actual E2B API integration.
        //
        // Steps:
        // 1. Create a sandbox via POST /sandboxes
        //    - Headers: Authorization: Bearer {api_key}
        //    - Body: { "templateID": "base" }
        // 2. Execute code via POST /sandboxes/{sandboxID}/execute
        //    - Body: { "code": code, "language": language, "timeout": timeout_ms }
        // 3. Parse the response into RunResult
        // 4. Close the sandbox via DELETE /sandboxes/{sandboxID}
        //
        // For now, return an error indicating this is not yet implemented.
        let _ = (code, language, timeout_ms);
        Err(SandboxError::Runtime(
            "E2B sandbox backend is not yet implemented. \
             This is a stub behind the `sandbox-e2b` feature gate. \
             Contributions welcome!"
                .to_string(),
        ))
    }
}