-
Notifications
You must be signed in to change notification settings - Fork 2.3k
added isolated code executor #3225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
f98c652
b3cdd32
a77b0c2
8fbd73b
9cf3ef0
98e5a83
ff06b44
ba5dbbd
b0f3f6c
1e49154
5d01c91
6424fc4
c1e3487
039b9b9
0dc3c26
6a9ee6b
1cc3a2e
7603e57
bf19756
8f12cc6
453e786
f742aea
ec4d631
1c07fa0
f64a8ab
5840c02
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,66 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| from contextlib import redirect_stdout | ||||||||||||||||||||||||||||||||||||||||||||||
| import io | ||||||||||||||||||||||||||||||||||||||||||||||
| import re | ||||||||||||||||||||||||||||||||||||||||||||||
| from typing import Any | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| from pydantic import Field | ||||||||||||||||||||||||||||||||||||||||||||||
| from typing_extensions import override | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| from ..agents.invocation_context import InvocationContext | ||||||||||||||||||||||||||||||||||||||||||||||
| from .base_code_executor import BaseCodeExecutor | ||||||||||||||||||||||||||||||||||||||||||||||
| from .code_execution_utils import CodeExecutionInput | ||||||||||||||||||||||||||||||||||||||||||||||
| from .code_execution_utils import CodeExecutionResult | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import sys | ||||||||||||||||||||||||||||||||||||||||||||||
| import subprocess | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| #Don't think this is needed anymore but keeping it around just in case. | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| # def _prepare_globals(code: str, globals_: dict[str, Any]) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||
| # """Prepare globals for code execution, injecting __name__ if needed.""" | ||||||||||||||||||||||||||||||||||||||||||||||
| # if re.search(r"if\s+__name__\s*==\s*['\"]__main__['\"]", code): | ||||||||||||||||||||||||||||||||||||||||||||||
| # globals_['__name__'] = '__main__' | ||||||||||||||||||||||||||||||||||||||||||||||
AlexFierro9 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| class IsolatedCodeExecutor(BaseCodeExecutor): | ||||||||||||||||||||||||||||||||||||||||||||||
| """A code executor that safely executes code in an isolated environment through | ||||||||||||||||||||||||||||||||||||||||||||||
| the current local context.""" | ||||||||||||||||||||||||||||||||||||||||||||||
AlexFierro9 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| # Overrides the BaseCodeExecutor attribute: this executor cannot be stateful. | ||||||||||||||||||||||||||||||||||||||||||||||
| stateful: bool = Field(default=False, frozen=True, exclude=True) | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| # Overrides the BaseCodeExecutor attribute: this executor cannot | ||||||||||||||||||||||||||||||||||||||||||||||
| # optimize_data_file. | ||||||||||||||||||||||||||||||||||||||||||||||
| optimize_data_file: bool = Field(default=False, frozen=True, exclude=True) | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self, **data): | ||||||||||||||||||||||||||||||||||||||||||||||
| """Initializes the IsolatedCodeExecutor.""" | ||||||||||||||||||||||||||||||||||||||||||||||
| if 'stateful' in data and data['stateful']: | ||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError('Cannot set `stateful=True` in IsolatedCodeExecutor.') | ||||||||||||||||||||||||||||||||||||||||||||||
| if 'optimize_data_file' in data and data['optimize_data_file']: | ||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||
| 'Cannot set `optimize_data_file=True` in IsolatedCodeExecutor.' | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||
| super().__init__(**data) | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||||||||||||||
| def execute_code( | ||||||||||||||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||||||||||||||
| invocation_context: InvocationContext, | ||||||||||||||||||||||||||||||||||||||||||||||
| code_execution_input: CodeExecutionInput, | ||||||||||||||||||||||||||||||||||||||||||||||
| ) -> CodeExecutionResult: | ||||||||||||||||||||||||||||||||||||||||||||||
| # Executes code by spawning a new python interpreter process. | ||||||||||||||||||||||||||||||||||||||||||||||
| code = code_execution_input.code | ||||||||||||||||||||||||||||||||||||||||||||||
| process_result = subprocess.run( | ||||||||||||||||||||||||||||||||||||||||||||||
| [sys.executable, "-c", code], | ||||||||||||||||||||||||||||||||||||||||||||||
| capture_output=True, | ||||||||||||||||||||||||||||||||||||||||||||||
| text=True | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| # Collect the final result. | ||||||||||||||||||||||||||||||||||||||||||||||
| return CodeExecutionResult( | ||||||||||||||||||||||||||||||||||||||||||||||
| stdout=process_result.stdout, | ||||||||||||||||||||||||||||||||||||||||||||||
| stderr=process_result.stderr, | ||||||||||||||||||||||||||||||||||||||||||||||
| output_files=[], | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
| return CodeExecutionResult( | |
| stdout=process_result.stdout, | |
| stderr=process_result.stderr, | |
| output_files=[], | |
| try: | |
| process_result = subprocess.run( | |
| [sys.executable, "-c", code], | |
| capture_output=True, | |
| text=True | |
| ) | |
| except subprocess.TimeoutExpired as e: | |
| return CodeExecutionResult( | |
| stdout="", | |
| stderr=f"Code execution timed out: {e}", | |
| output_files=[], | |
| ) | |
| except Exception as e: | |
| return CodeExecutionResult( | |
| stdout="", | |
| stderr=f"Code execution failed: {e}", | |
| output_files=[], | |
| ) |
Uh oh!
There was an error while loading. Please reload this page.