Source code for camel.interpreters.e2b_interpreter

# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
import os
from typing import Any, ClassVar, Dict, List, Optional

from camel.interpreters.base import BaseInterpreter
from camel.interpreters.interpreter_error import InterpreterError
from camel.logger import get_logger
from camel.utils import api_keys_required

logger = get_logger(__name__)


[docs] class E2BInterpreter(BaseInterpreter): r"""E2B Code Interpreter implementation. Args: require_confirm (bool, optional): If True, prompt user before running code strings for security. (default: :obj:`True`) """ _CODE_TYPE_MAPPING: ClassVar[Dict[str, Optional[str]]] = { "python": None, "py3": None, "python3": None, "py": None, "shell": "bash", "bash": "bash", "sh": "bash", "java": "java", "javascript": "js", "r": "r", } @api_keys_required( [ (None, "E2B_API_KEY"), ] ) def __init__( self, require_confirm: bool = True, ) -> None: from e2b_code_interpreter import Sandbox self.require_confirm = require_confirm self._sandbox = Sandbox(api_key=os.environ.get("E2B_API_KEY")) def __del__(self) -> None: r"""Destructor for the E2BInterpreter class. This method ensures that the e2b sandbox is killed when the interpreter is deleted. """ if ( hasattr(self, '_sandbox') and self._sandbox is not None and self._sandbox.is_running() ): self._sandbox.kill()
[docs] def run( self, code: str, code_type: str, ) -> str: r"""Executes the given code in the e2b sandbox. Args: code (str): The code string to execute. code_type (str): The type of code to execute (e.g., 'python', 'bash'). Returns: str: The string representation of the output of the executed code. Raises: InterpreterError: If the `code_type` is not supported or if any runtime error occurs during the execution of the code. """ if code_type not in self._CODE_TYPE_MAPPING: raise InterpreterError( f"Unsupported code type {code_type}. " f"`{self.__class__.__name__}` only supports " f"{', '.join(list(self._CODE_TYPE_MAPPING.keys()))}." ) # Print code for security checking if self.require_confirm: logger.info( f"The following {code_type} code will run on your " "e2b sandbox: {code}" ) while True: choice = input("Running code? [Y/n]:").lower() if choice in ["y", "yes", "ye"]: break elif choice not in ["no", "n"]: continue raise InterpreterError( "Execution halted: User opted not to run the code. " "This choice stops the current operation and any " "further code execution." ) if self._CODE_TYPE_MAPPING[code_type] is None: execution = self._sandbox.run_code(code) else: execution = self._sandbox.run_code( code=code, language=self._CODE_TYPE_MAPPING[code_type] ) if execution.text and execution.text.lower() != "none": return execution.text if execution.logs: if execution.logs.stdout: return ",".join(execution.logs.stdout) elif execution.logs.stderr: return ",".join(execution.logs.stderr) return str(execution.error)
[docs] def supported_code_types(self) -> List[str]: r"""Provides supported code types by the interpreter.""" return list(self._CODE_TYPE_MAPPING.keys())
[docs] def update_action_space(self, action_space: Dict[str, Any]) -> None: r"""Updates action space for *python* interpreter""" raise RuntimeError("E2B doesn't support " "`action_space`.")