.*?)```'
+ matches = list(re.finditer(code_block_regex, message, re.DOTALL))
+
+ if not matches:
+ return None
+
+ # Define a low-priority list for certain languages
+ low_priority_languages = ['bash', 'shell',
+ 'sh', 'zsh', 'powershell', 'pwsh', '']
+
+ # Find the main code block by avoiding low-priority languages
+ main_code = None
+ main_code_lang = None
+ max_length = 0
+
+ for match in matches:
+ code = match.group('code').strip()
+ code_lang = (match.group('code_lang') or '').lower()
+ if code_lang not in low_priority_languages and len(code) > max_length:
+ main_code = code
+ main_code_lang = code_lang
+ max_length = len(code)
+
+ # Fallback to the longest code block if no main code was found
+ if not main_code:
+ longest_match = max(matches, key=lambda m: len(m.group('code')))
+ main_code = longest_match.group('code').strip()
+ main_code_lang = (longest_match.group('code_lang') or '').lower()
+
+ # Define language prefixes for each environment
+ python_prefixes = ['py', 'ipython', 'pygame', 'gradio', 'streamlit']
+ vue_prefixes = ['vue']
+ react_prefixes = ['react', 'next']
+ js_prefixes = ['js', 'javascript', 'jsx', 'coffee', 'ecma', 'node', 'es', 'svelte']
+ html_prefixes = ['html', 'xhtml', 'htm']
+ ts_prefixes = ['ts', 'typescript', 'tsx']
+ mermaid_prefixes = ['mermaid', 'mmd']
+ c_prefixes = ['c']
+ cpp_prefixes = ['cpp', 'c++']
+ go_prefixes = ['go', 'golang']
+ java_prefixes = ['java']
+ rust_prefixes = ['rust']
+ csharp_prefixes = ['cs', 'csharp', 'dotnet']
+
+ # Extract package dependencies from the main program
+ python_packages: list[str] = []
+ npm_packages: list[str] = []
+
+ # Helper function to check if any prefix matches
+ def matches_prefix(lang: str, prefixes: list[str]) -> bool:
+ return any(lang.lower().startswith(prefix) for prefix in prefixes)
+
+ if matches_prefix(main_code_lang, python_prefixes):
+ python_packages = extract_python_imports(main_code)
+ extra_python_packages, main_code = extract_inline_pip_install_commands(
+ main_code)
+ python_packages.extend(extra_python_packages)
+ sandbox_env_name = determine_python_environment(
+ main_code, python_packages)
+ elif matches_prefix(main_code_lang, vue_prefixes):
+ npm_packages = extract_js_imports(main_code)
+ sandbox_env_name = SandboxEnvironment.VUE
+ main_code_lang = detect_js_ts_code_lang(main_code)
+ elif matches_prefix(main_code_lang, react_prefixes):
+ npm_packages = extract_js_imports(main_code)
+ sandbox_env_name = SandboxEnvironment.REACT
+ main_code_lang = detect_js_ts_code_lang(main_code)
+ elif ('' in main_code and ('' in main_code)):
+ npm_packages = extract_js_from_html_script_tags(main_code)
+ sandbox_env_name = SandboxEnvironment.HTML
+ main_code_lang = 'html'
+ elif matches_prefix(main_code_lang, js_prefixes):
+ main_code_lang = 'javascript'
+ npm_packages = extract_js_imports(main_code)
+ sandbox_env_name = determine_jsts_environment(main_code, npm_packages)
+ elif matches_prefix(main_code_lang, ts_prefixes):
+ main_code_lang = 'typescript'
+ npm_packages = extract_js_imports(main_code)
+ sandbox_env_name = determine_jsts_environment(main_code, npm_packages)
+ elif matches_prefix(main_code_lang, html_prefixes):
+ main_code_lang = detect_js_ts_code_lang(main_code)
+ npm_packages = extract_js_imports(main_code)
+ sandbox_env_name = determine_jsts_environment(main_code, npm_packages)
+ elif matches_prefix(main_code_lang, mermaid_prefixes):
+ main_code_lang = 'markdown'
+ sandbox_env_name = SandboxEnvironment.MERMAID
+ elif matches_prefix(main_code_lang, cpp_prefixes):
+ main_code_lang = 'cpp'
+ sandbox_env_name = SandboxEnvironment.CPP_RUNNER
+ elif matches_prefix(main_code_lang, go_prefixes):
+ main_code_lang = 'go'
+ sandbox_env_name = SandboxEnvironment.GOLANG_RUNNER
+ elif matches_prefix(main_code_lang, java_prefixes):
+ main_code_lang = 'java'
+ sandbox_env_name = SandboxEnvironment.JAVA_RUNNER
+ elif matches_prefix(main_code_lang, rust_prefixes):
+ main_code_lang = 'rust'
+ sandbox_env_name = SandboxEnvironment.RUST_RUNNER
+ elif main_code_lang == 'c':
+ main_code_lang = 'c'
+ sandbox_env_name = sandbox_env_name = SandboxEnvironment.C_RUNNER
+ else:
+ sandbox_env_name = None
+
+ all_python_packages: Set[str] = set(python_packages)
+ all_npm_packages: Set[str] = set(npm_packages)
+
+ for match in matches:
+ code = match.group('code').strip()
+ if code != main_code:
+ install_python_packages, install_npm_packages = extract_installation_commands(
+ code)
+ all_python_packages.update(install_python_packages)
+ all_npm_packages.update(install_npm_packages)
+
+ if not main_code_lang:
+ main_code_lang = 'markdown'
+
+ return main_code, main_code_lang, (list(all_python_packages), list(all_npm_packages)), sandbox_env_name
+
+
+def create_placeholder_svg_data_url(width: int, height: int) -> str:
+ '''
+ Create a data URL for a placeholder image with given dimensions.
+ Uses SVG to create an elegant placeholder.
+
+ Args:
+ width: Width of the placeholder image
+ height: Height of the placeholder image
+
+ Returns:
+ str: Data URL containing the SVG image
+ '''
+ # Create SVG with gradient background and text
+ # Use simpler SVG structure for better browser compatibility
+ svg = f''''''
+
+ # Convert to base64 data URL
+ try:
+ encoded_svg = base64.b64encode(svg.encode('utf-8')).decode('utf-8')
+ return f'data:image/svg+xml;base64,{encoded_svg}'
+ except Exception as e:
+ print(f'Error encoding SVG: {e}')
+ # Fallback to a simple colored div
+ return f'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0ie3dpZHRofSIgaGVpZ2h0PSJ7aGVpZ2h0fSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjNmNGY2Ii8+PC9zdmc+'
+
+
+def replace_placeholder_urls(code: str) -> str:
+ '''
+ Replace placeholder image URLs with SVG data URLs.
+ Only replaces exact matches of "/api/placeholder/{width}/{height}".
+
+ Args:
+ code: The source code containing placeholder URLs
+
+ Returns:
+ str: Code with placeholder URLs replaced with data URLs
+ '''
+
+ def replacer(match: re.Match) -> str:
+ try:
+ # Extract width and height from the URL using capturing groups
+ width = int(match.group(1))
+ height = int(match.group(2))
+
+ # Validate dimensions
+ if width <= 0 or height <= 0:
+ print(f'Warning: Invalid dimensions {width}x{height}, using default 100x100')
+ width, height = 100, 100
+ elif width > 10000 or height > 10000:
+ print(f'Warning: Dimensions {width}x{height} are very large, capping at 1000x1000')
+ width, height = min(width, 1000), min(height, 1000)
+
+ print(f'Replacing placeholder URL with SVG: {width}x{height}')
+ data_url = create_placeholder_svg_data_url(width, height)
+ return data_url
+ except Exception as e:
+ print(f'Error replacing placeholder URL: {e}')
+ # Return a simple fallback
+ return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjNmNGY2Ii8+PC9zdmc+'
+
+ # Regular expression pattern to match placeholder URLs
+ pattern = r'/api/placeholder/(\d+)/(\d+)'
+
+ try:
+ # Replace all occurrences
+ result = re.sub(pattern, replacer, code)
+ print(f'Placeholder URL replacement completed successfully')
+ return result
+ except Exception as e:
+ print(f'Error during placeholder URL replacement: {e}')
+ return code # Return original code if replacement fails
+
+
+def extract_installation_commands(code: str) -> tuple[list[str], list[str]]:
+ '''
+ Extracts package installation commands from the code block, preserving version information.
+
+ Args:
+ code (str): The code block to analyze.
+
+ Returns:
+ tuple[list[str], list[str]]: A tuple containing two lists:
+ 1. Python packages from pip install commands (with versions if specified).
+ 2. npm packages from npm install commands (with versions if specified).
+ '''
+ python_packages = []
+ npm_packages = []
+
+ # Process the code line by line to handle both pip and npm commands
+ lines = code.split('\n')
+ for line in lines:
+ line = line.strip()
+
+ # Skip empty lines and comments
+ if not line or line.startswith('#'):
+ continue
+
+ # Handle pip install commands
+ if any(x in line for x in ['pip install', 'pip3 install', 'python -m pip install']):
+ # Remove the command part and any flags
+ parts = line.split('install', 1)[1].strip()
+ # Handle flags at the start
+ while parts.startswith(('-', '--')):
+ parts = parts.split(None, 1)[1]
+
+ # Split by whitespace, respecting quotes
+ current = ''
+ in_quotes = False
+ quote_char = None
+ packages = []
+
+ for char in parts:
+ if char in '"\'':
+ if not in_quotes:
+ in_quotes = True
+ quote_char = char
+ elif char == quote_char:
+ in_quotes = False
+ quote_char = None
+ elif char.isspace() and not in_quotes:
+ if current:
+ packages.append(current)
+ current = ''
+ else:
+ current += char
+ if current:
+ packages.append(current)
+
+ # Add packages, stripping quotes and ignoring flags
+ for pkg in packages:
+ pkg = pkg.strip('"\'')
+ if pkg and not pkg.startswith(('-', '--')) and not pkg == '-r':
+ python_packages.append(pkg)
+
+ # Handle npm/yarn install commands
+ elif any(x in line for x in ['npm install', 'npm i', 'yarn add']):
+ # Remove the command part and any flags
+ if 'yarn add' in line:
+ parts = line.split('add', 1)[1]
+ else:
+ parts = line.split('install', 1)[
+ 1] if 'install' in line else line.split('i', 1)[1]
+ parts = parts.strip()
+
+ # Handle flags at the start
+ while parts.startswith(('-', '--')):
+ parts = parts.split(None, 1)[1] if ' ' in parts else ''
+
+ # Process each package
+ for pkg in parts.split():
+ if pkg.startswith(('-', '--')) or pkg in ('install', 'i', 'add'):
+ continue
+
+ if pkg.startswith('@'):
+ # Handle scoped packages (e.g., @types/node@16.0.0)
+ if '@' in pkg[1:]: # Has version
+ pkg_parts = pkg.rsplit('@', 1)
+ base_pkg = pkg_parts[0] # @scope/name
+ version = pkg_parts[1] # version
+ npm_packages.append(f"{base_pkg}@{version}")
+ else:
+ npm_packages.append(pkg)
+ else:
+ npm_packages.append(pkg)
+
+ # Remove duplicates while preserving order
+ python_packages = list(dict.fromkeys(python_packages))
+ npm_packages = list(dict.fromkeys(npm_packages))
+
+ # Filter out npm command words
+ npm_packages = [p for p in npm_packages if p not in (
+ 'npm', 'install', 'i', 'add')]
+
+ return python_packages, npm_packages
+
+
+def validate_dependencies(dependencies: list) -> tuple[bool, str]:
+ """
+ Validate dependency list format and values.
+ Allows empty rows but validates format when package name is specified.
+ """
+ if not dependencies:
+ return True, ""
+
+ valid_types = ["python", "npm"]
+ for dep in dependencies:
+ # Skip validation for empty rows
+ if len(dep) != 3:
+ return False, "Each dependency must have type, package and version fields"
+
+ dep_type, pkg_name, version = dep
+
+ # Skip empty rows
+ if not pkg_name.strip():
+ continue
+
+ if dep_type.lower() not in valid_types:
+ return False, f"Invalid dependency type: {dep_type}"
+
+ # Validate version format if specified
+ if version.strip():
+ if dep_type.lower() == "python":
+ # Check for valid pip version specifiers
+ if not any(op in version for op in ['==', '>=', '<=', '~=', '>', '<']) and version.lower() != "latest":
+ return False, f"Invalid Python version format for {pkg_name}: {version}"
+ elif dep_type.lower() == "npm":
+ # Check for valid npm version format (starts with @ or valid semver-like)
+ if not (version.startswith('@') or version.lower() == "latest"):
+ return False, f"Invalid NPM version format for {pkg_name}: {version}"
+
+ return True, ""
+
+
+def extract_java_class_name(java_code: str) -> str:
+ '''
+ Extract the class name from Java code.
+ '''
+ match = re.search(r'public\s+class\s+(\w+)', java_code)
+ return match.group(1) if match else "Main"
\ No newline at end of file
diff --git a/sandbox/code_runner.py b/sandbox/code_runner.py
new file mode 100644
index 0000000000000000000000000000000000000000..09ebab33db767b14ad861d91936bdbd6c1d56b07
--- /dev/null
+++ b/sandbox/code_runner.py
@@ -0,0 +1,1612 @@
+'''
+Run generated code in a sandbox environment.
+
+Gradio will interact with this module.
+'''
+
+from typing import Any, Generator, Literal, TypeAlias, TypedDict, Set
+import uuid
+import gradio as gr
+
+import base64
+from e2b_code_interpreter import Sandbox as CodeSandbox
+from gradio_sandboxcomponent import SandboxComponent
+
+from sandbox.sandbox_state import ChatbotSandboxState
+from sandbox.code_analyzer import SandboxEnvironment, extract_code_from_markdown, extract_installation_commands, extract_java_class_name, extract_js_imports, extract_python_imports, replace_placeholder_urls, validate_dependencies
+from sandbox.prompts import (
+ DEFAULT_C_CODE_RUN_SANDBOX_INSTRUCTION, DEFAULT_CPP_CODE_RUN_SANDBOX_INSTRUCTION, DEFAULT_GOLANG_CODE_RUN_SANDBOX_INSTRUCTION, DEFAULT_GRADIO_SANDBOX_INSTRUCTION, DEFAULT_HTML_SANDBOX_INSTRUCTION, DEFAULT_JAVA_CODE_RUN_SANDBOX_INSTRUCTION, DEFAULT_JAVASCRIPT_RUNNER_INSTRUCTION, DEFAULT_MERMAID_SANDBOX_INSTRUCTION, DEFAULT_PYGAME_SANDBOX_INSTRUCTION, DEFAULT_PYTHON_RUNNER_INSTRUCTION, DEFAULT_REACT_SANDBOX_INSTRUCTION, DEFAULT_RUST_CODE_RUN_SANDBOX_INSTRUCTION, DEFAULT_STREAMLIT_SANDBOX_INSTRUCTION, DEFAULT_VUE_SANDBOX_INSTRUCTION, GENERAL_SANDBOX_INSTRUCTION
+)
+from sandbox.sandbox_telemetry import log_sandbox_telemetry_gradio_fn
+
+
+from .constants import CODE_RUN_TIMEOUT_SECONDS, E2B_API_KEY, SANDBOX_TEMPLATE_ID, SANDBOX_NGINX_PORT
+from .sandbox_manager import get_sandbox_app_url, create_sandbox, install_npm_dependencies, install_pip_dependencies, reuse_or_create_sandbox, run_background_command_with_timeout, run_command_in_sandbox
+
+SUPPORTED_SANDBOX_ENVIRONMENTS: list[str] = [
+ env.value for env in SandboxEnvironment
+
+]
+
+WEB_UI_SANDBOX_ENVIRONMENTS = [
+ SandboxEnvironment.HTML,
+ SandboxEnvironment.REACT,
+ SandboxEnvironment.VUE,
+ SandboxEnvironment.GRADIO,
+ SandboxEnvironment.STREAMLIT,
+ # SandboxEnvironment.NICEGUI,
+ SandboxEnvironment.PYGAME,
+ SandboxEnvironment.MERMAID
+]
+'''
+Sandbox environments that can be rendered in the web UI.
+'''
+
+VALID_GRADIO_CODE_LANGUAGES = [
+ 'python', 'c', 'cpp', 'markdown', 'json', 'html', 'css', 'javascript', 'jinja2', 'typescript', 'yaml', 'dockerfile', 'shell', 'r', 'sql',
+ 'sql-msSQL', 'sql-mySQL', 'sql-mariaDB', 'sql-sqlite', 'sql-cassandra', 'sql-plSQL', 'sql-hive', 'sql-pgSQL', 'sql-gql', 'sql-gpSQL', 'sql-sparkSQL',
+ 'sql-esper'
+]
+'''
+Languages that gradio code component can render.
+'''
+
+RUN_CODE_BUTTON_HTML = ""
+'''
+Button in the chat to run the code in the sandbox.
+'''
+
+
+DEFAULT_SANDBOX_INSTRUCTIONS: dict[SandboxEnvironment, str] = {
+ SandboxEnvironment.AUTO: GENERAL_SANDBOX_INSTRUCTION.strip(),
+ SandboxEnvironment.PYTHON_RUNNER: DEFAULT_PYTHON_RUNNER_INSTRUCTION.strip(),
+ SandboxEnvironment.JAVASCRIPT_RUNNER: DEFAULT_JAVASCRIPT_RUNNER_INSTRUCTION.strip(),
+ SandboxEnvironment.HTML: DEFAULT_HTML_SANDBOX_INSTRUCTION.strip(),
+ SandboxEnvironment.REACT: DEFAULT_REACT_SANDBOX_INSTRUCTION.strip(),
+ SandboxEnvironment.VUE: DEFAULT_VUE_SANDBOX_INSTRUCTION.strip(),
+ SandboxEnvironment.GRADIO: DEFAULT_GRADIO_SANDBOX_INSTRUCTION.strip(),
+ SandboxEnvironment.STREAMLIT: DEFAULT_STREAMLIT_SANDBOX_INSTRUCTION.strip(),
+ SandboxEnvironment.PYGAME: DEFAULT_PYGAME_SANDBOX_INSTRUCTION.strip(),
+ SandboxEnvironment.MERMAID: DEFAULT_MERMAID_SANDBOX_INSTRUCTION.strip(),
+ # Runners
+ SandboxEnvironment.C_RUNNER: DEFAULT_C_CODE_RUN_SANDBOX_INSTRUCTION,
+ SandboxEnvironment.CPP_RUNNER: DEFAULT_CPP_CODE_RUN_SANDBOX_INSTRUCTION,
+ SandboxEnvironment.JAVA_RUNNER: DEFAULT_JAVA_CODE_RUN_SANDBOX_INSTRUCTION,
+ SandboxEnvironment.GOLANG_RUNNER: DEFAULT_GOLANG_CODE_RUN_SANDBOX_INSTRUCTION,
+ SandboxEnvironment.RUST_RUNNER: DEFAULT_RUST_CODE_RUN_SANDBOX_INSTRUCTION,
+
+}
+
+
+SandboxGradioSandboxComponents: TypeAlias = tuple[
+ gr.Markdown | Any, # sandbox_output_md
+ SandboxComponent | Any, # sandbox_ui
+ gr.Code | Any, # sandbox_code
+ Any
+]
+'''
+Gradio components for the sandbox.
+'''
+
+class CodeRunResult(TypedDict):
+ '''
+ The result of running the code in the sandbox.
+ '''
+ sandbox_id: str
+ '''
+ The sandbox id to run the code.
+ '''
+ sandbox_url: str
+ '''
+ The sandbox url to access the rendered results.
+ '''
+ is_run_success: bool
+ '''
+ Whether the code run is successful.
+ '''
+ stderr: str
+ '''
+ The stderr output from the sandbox.
+ '''
+
+
+def create_chatbot_sandbox_state(btn_list_length: int = 5) -> ChatbotSandboxState:
+ '''
+ Create a new sandbox state for a chatbot.
+ '''
+ return {
+ 'enable_sandbox': True, # Always enabled
+ 'enabled_round': 0,
+ 'sandbox_run_round': 0,
+ 'edit_round': 0,
+ 'sandbox_environment': SandboxEnvironment.AUTO,
+ 'auto_selected_sandbox_environment': None,
+ 'sandbox_instruction': DEFAULT_SANDBOX_INSTRUCTIONS[SandboxEnvironment.AUTO],
+ 'code_to_execute': "",
+ 'code_language': None,
+ 'code_dependencies': ([], []),
+ 'btn_list_length': btn_list_length,
+ 'sandbox_id': None,
+ 'chat_session_id': None,
+ 'conv_id': None,
+ "sandbox_output": None,
+ "sandbox_error": None,
+ }
+
+
+def set_sandbox_state_ids(
+ sandbox_state: ChatbotSandboxState,
+ conv_id: str,
+ chat_session_id: str,
+) -> ChatbotSandboxState:
+ '''
+ Set the conv_id and chat_session_id in the sandbox state.
+ '''
+ sandbox_state['conv_id'] = conv_id
+ sandbox_state['chat_session_id'] = chat_session_id
+ return sandbox_state
+
+
+def reset_sandbox_state(state: ChatbotSandboxState) -> ChatbotSandboxState:
+ '''
+ Reset the sandbox state.
+ Used when the chatbot session is reset.
+ '''
+ # reset rounds
+ state['enabled_round'] = 0
+ state['sandbox_run_round'] = 0
+ state['edit_round'] = 0
+
+ # state['sandbox_environment'] = SandboxEnvironment.AUTO
+ state['auto_selected_sandbox_environment'] = None
+ state['sandbox_instruction'] = DEFAULT_SANDBOX_INSTRUCTIONS[SandboxEnvironment.AUTO]
+ state['code_to_execute'] = ""
+ state['code_language'] = None
+ state['code_dependencies'] = ([], [])
+ state['sandbox_error'] = None
+ state['sandbox_output'] = None
+
+ # reset ids
+ state['sandbox_id'] = None
+ state['conv_id'] = None
+ state['chat_session_id'] = None
+
+ return state
+
+
+def update_sandbox_config_multi(
+ enable_sandbox: bool,
+ sandbox_environment: SandboxEnvironment,
+ *states: ChatbotSandboxState
+) -> list[ChatbotSandboxState]:
+ '''
+ Fn to update sandbox config.
+ '''
+ return [
+ update_sandbox_config(enable_sandbox, sandbox_environment, state)
+ for state
+ in states
+ ]
+
+
+def update_sandbox_state_system_prompt(sandbox_state: ChatbotSandboxState, system_prompt: str):
+ if sandbox_state['enabled_round'] == 0:
+ sandbox_state['sandbox_instruction'] = system_prompt
+ return sandbox_state
+
+
+def update_sandbox_config(
+ enable_sandbox: bool,
+ sandbox_environment: SandboxEnvironment,
+ state: ChatbotSandboxState
+) -> ChatbotSandboxState:
+ '''
+ Fn to update sandbox config for single model.
+ '''
+ state["enable_sandbox"] = enable_sandbox
+ state["sandbox_environment"] = sandbox_environment
+ state['sandbox_instruction'] = DEFAULT_SANDBOX_INSTRUCTIONS.get(sandbox_environment, None)
+ return state
+
+
+def update_visibility(visible):
+ return [gr.update(visible=visible)] *14
+
+
+def update_visibility_for_single_model(visible: bool, component_cnt: int):
+ return [gr.update(visible=visible)] * component_cnt
+
+
+def mermaid_to_html(mermaid_code: str, theme: str = 'default') -> str:
+ """
+ Convert Mermaid diagram code to a minimal HTML document.
+
+ Args:
+ mermaid_code: The Mermaid diagram syntax
+ theme: Theme name ('default', 'dark', 'forest', 'neutral', etc.)
+
+ Returns:
+ str: Complete HTML document with embedded Mermaid diagram
+ """
+ html_template = f'''
+
+
+
+
+
+
+
+
+{mermaid_code}
+
+
+'''
+ return html_template
+
+
+def javascript_to_html(javascript_code: str) -> str:
+ """
+ Convert JavaScript code to a minimal HTML document that executes the code.
+
+ Args:
+ javascript_code: The JavaScript code to embed
+
+ Returns:
+ str: Complete HTML document with embedded JavaScript code
+ """
+ html_template = f'''
+
+
+
+ JavaScript Code Execution
+
+
+
+ JavaScript Code Execution
+
+
+
+
+'''
+ return html_template
+
+
+def render_result(result):
+ if result.png:
+ if isinstance(result.png, str):
+ img_str = result.png
+ else:
+ img_str = base64.b64encode(result.png).decode()
+ return f""
+ elif result.jpeg:
+ if isinstance(result.jpeg, str):
+ img_str = result.jpeg
+ else:
+ img_str = base64.b64encode(result.jpeg).decode()
+ return f""
+ elif result.svg:
+ if isinstance(result.svg, str):
+ svg_data = result.svg
+ else:
+ svg_data = result.svg.decode()
+ svg_base64 = base64.b64encode(svg_data.encode()).decode()
+ return f""
+ elif result.html:
+ return result.html
+ elif result.markdown:
+ return f"```markdown\n{result.markdown}\n```"
+ elif result.latex:
+ return f"```latex\n{result.latex}\n```"
+ elif result.json:
+ return f"```json\n{result.json}\n```"
+ elif result.javascript:
+ return result.javascript # Return raw JavaScript
+ else:
+ return str(result)
+
+
+def run_code_interpreter(code: str, code_language: str | None, code_dependencies: tuple[list[str], list[str]]) -> tuple[str, str]:
+ """
+ Executes the provided code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The code to be executed.
+ """
+ sandbox = CodeSandbox(
+ api_key=E2B_API_KEY,
+ )
+
+ sandbox.commands.run("pip install uv",
+ timeout=60 * 3,
+ on_stderr=lambda message: print(message),)
+
+ stderrs = []
+
+ python_dependencies, npm_dependencies = code_dependencies
+ pip_install_errs = install_pip_dependencies(sandbox, python_dependencies)
+ npm_install_errs = install_npm_dependencies(sandbox, npm_dependencies)
+
+ stderrs.extend(pip_install_errs)
+ stderrs.extend(npm_install_errs)
+
+ execution = sandbox.run_code(
+ code=code,
+ language=code_language
+ )
+
+ # collect stdout, stderr from sandbox
+ stdout = "\n".join(execution.logs.stdout)
+ stderr = "\n".join(execution.logs.stderr)
+ if execution.error:
+ stderr += f"\n{execution.error.name}: {execution.error.value}"
+ output = ""
+ if stdout:
+ output += f"### Stdout:\n```markdown\n{stdout}\n```\n\n"
+
+ stderrs.append(stderr)
+
+ results = []
+ for result in execution.results:
+ if result.html or result.javascript:
+ # TODO: fix this
+ continue
+ # with open('html_code.html', 'w') as f:
+ # f.write(result.html)
+ # url, _ = run_html_sandbox(result.html, ([], extract_js_imports(result.html)))
+ else:
+ rendered_result = render_result(result)
+ results.append(rendered_result)
+ if results:
+ output += "\n### Results:\n" + "\n".join(results)
+
+ stderrs = '\n'.join(stderrs)
+ return output, "" if output else stderrs
+
+
+def run_html_sandbox(code: str, code_dependencies: tuple[list[str], list[str]], existing_sandbox_id: str | None = None) -> tuple[str, str, str]:
+ """
+ Executes the provided code within a sandboxed environment and returns the output.
+ Supports both React and Vue.js rendering in HTML files.
+
+ Args:
+ code (str): The code to be executed.
+ code_dependencies: Tuple of (python_deps, npm_deps)
+
+ Returns:
+ tuple: (sandbox_url, sandbox_id, stderr)
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+ project_root = "~/html_app"
+ sandbox.files.make_dir(project_root)
+
+ # HTML does not support dependencies for now
+ # _, npm_dependencies = code_dependencies
+ # install_npm_dependencies(sandbox, npm_dependencies, project_root=project_root)
+
+ # replace placeholder URLs with SVG data URLs
+ code = replace_placeholder_urls(code)
+
+ file_path = f"{project_root}/index.html"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ sandbox_url = get_sandbox_app_url(sandbox, 'html')
+ return (sandbox_url, sandbox.sandbox_id, '')
+
+
+def run_react_sandbox(code: str, code_dependencies: tuple[list[str], list[str]], existing_sandbox_id: str | None = None) -> CodeRunResult:
+ """
+ Executes the provided code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The code to be executed.
+
+ Returns:
+ url for remote sandbox
+ """
+ project_root = "~/react_app"
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+ stderrs: list[str] = [] # to collect errors
+
+ _, npm_dependencies = code_dependencies
+ if npm_dependencies:
+ print(f"Installing NPM dependencies...: {npm_dependencies}")
+ install_errs = install_npm_dependencies(sandbox, npm_dependencies, project_root=project_root)
+ stderrs.extend(install_errs)
+ print("NPM dependencies installed. " + "Errors: " + str(install_errs))
+
+ # replace placeholder URLs with SVG data URLs
+ code = replace_placeholder_urls(code)
+
+ # set up the sandbox
+ print("Setting up sandbox directory structure...")
+ file_path = "~/react_app/src/App.tsx"
+ sandbox.files.write(file_path, code, "user", 60)
+ print("Code files written successfully.")
+
+ is_run_success, _, build_stderrs = run_command_in_sandbox(
+ sandbox=sandbox,
+ command="npm run build --loglevel=error -- --mode development --logLevel error",
+ working_directory=project_root,
+ )
+ stderrs.extend(build_stderrs)
+
+ sandbox_url = get_sandbox_app_url(sandbox, 'react')
+ return {
+ 'sandbox_id': sandbox.sandbox_id,
+ 'sandbox_url': sandbox_url,
+ 'is_run_success': is_run_success,
+ 'stderr': '\n'.join(stderrs),
+ }
+
+
+def run_vue_sandbox(code: str, code_dependencies: tuple[list[str], list[str]], existing_sandbox_id: str | None = None) -> CodeRunResult:
+ """
+ Executes the provided Vue code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The Vue code to be executed.
+
+ Returns:
+ url for remote sandbox
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+ project_root = "~/vue_app"
+
+ stderrs: list[str] = [] # to collect errors
+
+ # replace placeholder URLs with SVG data URLs
+ code = replace_placeholder_urls(code)
+
+ # Set up the sandbox
+ file_path = "~/vue_app/src/App.vue"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ _, npm_dependencies = code_dependencies
+ if npm_dependencies:
+ print(f"Installing NPM dependencies...: {npm_dependencies}")
+ install_errs = install_npm_dependencies(sandbox, npm_dependencies, project_root=project_root)
+ stderrs.extend(install_errs)
+ print("NPM dependencies installed. " + "Errors: " + str(install_errs))
+
+ is_run_success, _, build_stderrs = run_command_in_sandbox(
+ sandbox=sandbox,
+ command="npm run build --loglevel=error -- --mode development --logLevel error",
+ working_directory=project_root,
+ )
+ stderrs.extend(build_stderrs)
+
+ sandbox_url = get_sandbox_app_url(sandbox, 'vue')
+ return {
+ 'sandbox_id': sandbox.sandbox_id,
+ 'sandbox_url': sandbox_url,
+ 'is_run_success': is_run_success,
+ 'stderr': '\n'.join(stderrs),
+ }
+
+
+def run_pygame_sandbox(code: str, code_dependencies: tuple[list[str], list[str]], existing_sandbox_id: str | None = None) -> CodeRunResult:
+ """
+ Executes the provided code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The code to be executed.
+
+ Returns:
+ url for remote sandbox
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+ project_root = "~/pygame_app"
+ file_path = f"{project_root}/main.py"
+
+ stderrs = []
+
+ sandbox.files.write(file_path, code, "user", 60)
+
+ python_dependencies, _ = code_dependencies
+ install_errs = install_pip_dependencies(sandbox, python_dependencies)
+ stderrs.extend(install_errs)
+
+ # build the pygame code
+ is_run_success, _, build_stderrs = run_command_in_sandbox(
+ sandbox=sandbox,
+ command="pygbag --build ~/pygame_app",
+ )
+ stderrs.extend(build_stderrs)
+
+ sandbox_url = get_sandbox_app_url(sandbox, 'pygame')
+ return {
+ 'sandbox_id': sandbox.sandbox_id,
+ 'sandbox_url': sandbox_url,
+ 'is_run_success': is_run_success,
+ 'stderr': '\n'.join(stderrs),
+ }
+
+
+def run_gradio_sandbox(code: str, code_dependencies: tuple[list[str], list[str]], existing_sandbox_id: str | None = None) -> tuple[str, str, str]:
+ """
+ Executes the provided code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The code to be executed.
+
+ Returns:
+ url for remote sandbox and sandbox id
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+ file_path = "~/gradio_app/main.py"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ stderrs = []
+
+ python_dependencies, _ = code_dependencies
+ install_stderr = install_pip_dependencies(sandbox, python_dependencies)
+ stderrs.extend(install_stderr)
+
+ stderr = run_background_command_with_timeout(
+ sandbox,
+ f"python {file_path}",
+ timeout=10,
+ )
+ stderrs.append(stderr)
+
+ sandbox_url = 'https://' + sandbox.get_host(7860)
+
+ return (sandbox_url, sandbox.sandbox_id, '\n'.join(stderrs))
+
+
+def run_streamlit_sandbox(code: str, code_dependencies: tuple[list[str], list[str]], existing_sandbox_id: str | None = None) -> tuple[str, str, str]:
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+ stderrs = []
+
+ sandbox.files.make_dir('mystreamlit')
+ file_path = "~/mystreamlit/app.py"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ python_dependencies, _ = code_dependencies
+ install_stderr = install_pip_dependencies(sandbox, python_dependencies)
+ stderrs.extend(install_stderr)
+
+ stderr = run_background_command_with_timeout(
+ sandbox,
+ r"sudo kill -9 $(ss -lptn 'sport = :8501' | grep -oP '(?<=pid=)\d+'); streamlit run ~/mystreamlit/app.py --server.port 8501 --server.headless true",
+ timeout=8,
+ )
+ stderrs.append(stderr)
+
+ host = sandbox.get_host(port=8501)
+ url = f"https://{host}"
+ return (url, sandbox.sandbox_id, '\n'.join(stderrs))
+
+
+def run_c_code(code: str, existing_sandbox_id: str | None = None) -> tuple[str, str]:
+ """
+ Executes the provided C code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The C code to be executed.
+
+ Returns:
+ tuple: (stdout, stderr)
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+ file_path = "~/main.c"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ is_success, stdouts, stderrs = run_command_in_sandbox(
+ sandbox=sandbox,
+ command=f"gcc {file_path} -o ~/main && ./main",
+ timeout=CODE_RUN_TIMEOUT_SECONDS,
+ )
+
+ # collect stdout, stderr from sandbox
+ stdout = "\n".join(stdouts)
+ stderr = "\n".join(stderrs)
+ return stdout, stderr
+
+
+def run_cpp_code(code: str, existing_sandbox_id: str | None = None) -> tuple[str, str]:
+ """
+ Executes the provided C++ code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The C++ code to be executed.
+
+ Returns:
+ tuple: (stdout, stderr)
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+ file_path = "~/main.cpp"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ is_success, stdouts, stderrs = run_command_in_sandbox(
+ sandbox=sandbox,
+ command=f"g++ {file_path} -o ~/main && ./main",
+ timeout=CODE_RUN_TIMEOUT_SECONDS,
+ )
+
+ # collect stdout, stderr from sandbox
+ stdout = "\n".join(stdouts)
+ stderr = "\n".join(stderrs)
+ return stdout, stderr
+
+
+def run_java_code(code: str, existing_sandbox_id: str | None = None) -> tuple[str, str]:
+ """
+ Executes the provided Java code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The Java code to be executed.
+
+ Returns:
+ tuple: (stdout, stderr)
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+ class_name = extract_java_class_name(code)
+ file_path = f"~/{class_name}.java"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ is_success, stdouts, stderrs = run_command_in_sandbox(
+ sandbox=sandbox,
+ command=f"javac {file_path} && java {class_name}",
+ timeout=CODE_RUN_TIMEOUT_SECONDS,
+ )
+
+ # collect stdout, stderr from sandbox
+ stdout = "\n".join(stdouts)
+ stderr = "\n".join(stderrs)
+ return stdout, stderr
+
+
+def run_golang_code(code: str, existing_sandbox_id: str | None = None) -> tuple[str, str]:
+ """
+ Executes the provided Go code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The Go code to be executed
+
+ Returns:
+ tuple: (stdout, stderr)
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+ file_path = "~/main.go"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ is_success, stdouts, stderrs = run_command_in_sandbox(
+ sandbox=sandbox,
+ command=f"go run {file_path}",
+ timeout=CODE_RUN_TIMEOUT_SECONDS,
+ )
+
+ # collect stdout, stderr from sandbox
+ stdout = "\n".join(stdouts)
+ stderr = "\n".join(stderrs)
+ return stdout, stderr
+
+
+# def run_csharp_code(code: str, existing_sandbox_id: str | None = None) -> tuple[str, str]:
+# """
+# Executes the provided C# code within a sandboxed environment and returns the output.
+
+# Args:
+# code (str): The C# code to be executed
+
+# Returns:
+# tuple: (stdout, stderr)
+# """
+# sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+# file_path = "~/main.cs"
+# sandbox.files.write(file_path, code, "user", 60)
+
+# is_success, stdouts, stderrs = run_command_in_sandbox(
+# sandbox=sandbox,
+# command=f"mcs {file_path} && mono main.exe",
+# timeout=CODE_RUN_TIMEOUT_SECONDS,
+# )
+
+# # collect stdout, stderr from sandbox
+# stdout = "\n".join(stdouts)
+# stderr = "\n".join(stderrs)
+# return stdout, stderr
+
+
+def run_rust_code(code: str, existing_sandbox_id: str | None = None) -> tuple[str, str]:
+ """
+ Executes the provided Rust code within a sandboxed environment and returns the output.
+
+ Args:
+ code (str): The Rust code to be executed
+
+ Returns:
+ tuple: (stdout, stderr)
+ """
+ sandbox = reuse_or_create_sandbox(sandbox_id=existing_sandbox_id)
+
+ file_path = "~/main.rs"
+ sandbox.files.write(file_path, code, "user", 60)
+
+ is_success, stdouts, stderrs = run_command_in_sandbox(
+ sandbox=sandbox,
+ command=f"rustc {file_path} && ./main",
+ timeout=CODE_RUN_TIMEOUT_SECONDS,
+ )
+
+ # collect stdout, stderr from sandbox
+ stdout = "\n".join(stdouts)
+ stderr = "\n".join(stderrs)
+ return stdout, stderr
+
+
+def on_edit_code(
+ state,
+ sandbox_state: ChatbotSandboxState,
+ sandbox_output_md: gr.Markdown,
+ sandbox_ui: SandboxComponent,
+ sandbox_code: str,
+ sandbox_dependency: gr.Dataframe,
+) -> Generator[tuple[Any, Any, Any, Any], None, None]:
+ '''
+ Gradio Handler when code is edited manually by users.
+ '''
+ if sandbox_state['enable_sandbox'] is False:
+ yield None, None, None, None
+ return
+ if len(sandbox_code.strip()) == 0 or sandbox_code == sandbox_state['code_to_execute']:
+ yield gr.skip(), gr.skip(), gr.skip(), gr.skip()
+ return
+ sandbox_state['code_to_execute'] = sandbox_code
+
+ # Extract packages from imports (without versions)
+ python_deps_from_imports = set(extract_python_imports(sandbox_code))
+ npm_deps_from_imports = set(extract_js_imports(sandbox_code))
+
+ # Get existing dependencies with versions from state
+ existing_python_deps, existing_npm_deps = sandbox_state["code_dependencies"]
+
+ # Create dictionaries to track package versions
+ python_deps_dict = {} # pkg_name -> version
+ npm_deps_dict = {} # pkg_name -> version
+
+ # First add existing dependencies with their specific versions
+ for dep in existing_python_deps:
+ pkg_name = dep.split('==')[0].split('>=')[0].split('<=')[0].split('~=')[0]
+ version = dep[len(pkg_name):]
+ if version: # If it has a specific version
+ python_deps_dict[pkg_name] = version
+ elif pkg_name in python_deps_from_imports: # Only keep packages that are still imported
+ python_deps_dict[pkg_name] = "latest"
+
+ for dep in existing_npm_deps:
+ if '@' in dep and not dep.startswith('@'):
+ pkg_name = dep.split('@')[0]
+ version = '@' + dep.split('@')[1]
+ elif '@' in dep[1:]: # Handle scoped packages
+ pkg_name, version = dep.rsplit('@', 1)
+ version = '@' + version
+ else:
+ pkg_name = dep
+ version = "latest"
+ if version != "latest": # If it has a specific version
+ npm_deps_dict[pkg_name] = version
+ elif pkg_name in npm_deps_from_imports: # Only keep packages that are still imported
+ npm_deps_dict[pkg_name] = "latest"
+
+ # Add new dependencies from imports with "latest" if not already present
+ for dep in python_deps_from_imports:
+ if dep not in python_deps_dict:
+ python_deps_dict[dep] = "latest"
+
+ for dep in npm_deps_from_imports:
+ if dep not in npm_deps_dict:
+ npm_deps_dict[dep] = "latest"
+
+ # Convert to dataframe format
+ dependencies = []
+
+ # Add Python packages
+ for pkg_name, version in python_deps_dict.items():
+ dependencies.append(["python", pkg_name, version])
+
+ # Add NPM packages
+ for pkg_name, version in npm_deps_dict.items():
+ dependencies.append(["npm", pkg_name, version])
+
+ # If no dependencies found, provide default empty rows
+ if not dependencies:
+ dependencies = [["python", "", ""], ["npm", "", ""]]
+
+ # Update dependencies in sandbox state
+ sandbox_state["code_dependencies"] = (
+ [f"{pkg}{ver}" if ver != "latest" else pkg for pkg, ver in python_deps_dict.items()],
+ [f"{pkg}{ver}" if ver != "latest" else pkg for pkg, ver in npm_deps_dict.items()]
+ )
+
+ yield (
+ gr.skip(), # sandbox_output_md
+ gr.skip(), # sandbox_ui
+ gr.skip(), # sandbox_code
+ gr.update(value=dependencies), # sandbox_dependency
+ )
+ yield from on_run_code(
+ state,
+ sandbox_state,
+ sandbox_output_md,
+ sandbox_ui,
+ sandbox_code,
+ sandbox_dependency,
+ )
+
+
+def on_edit_dependency(
+ state,
+ sandbox_state: ChatbotSandboxState,
+ sandbox_dependency: gr.Dataframe,
+ sandbox_output_md: gr.Markdown,
+ sandbox_ui: SandboxComponent,
+ sandbox_code: str,
+) -> Generator[tuple[Any, Any, Any, Any], None, None]:
+ """
+ Gradio Handler when dependencies are edited manually by users.
+ Handles version specifications and dependency removal.
+ """
+ if sandbox_state["enable_sandbox"] is False:
+ yield None, None, None, None
+ return
+
+ # Validate dependencies format
+ is_valid, error_msg = validate_dependencies(sandbox_dependency)
+ if not is_valid:
+ yield (
+ gr.Markdown(f"Invalid dependencies: {error_msg}"),
+ gr.skip(),
+ gr.skip(),
+ sandbox_dependency, # Return original dataframe
+ )
+ return
+
+ # Convert dataframe format to separate python and npm lists
+ python_deps = []
+ npm_deps = []
+ for dep in sandbox_dependency:
+ dep_type, pkg_name, version = dep
+ pkg_name = pkg_name.strip()
+ version = version.strip()
+
+ # Skip empty rows
+ if not pkg_name:
+ continue
+
+ if dep_type.lower() == "python":
+ # Handle Python package with version
+ if version and version.lower() != "latest":
+ if not any(op in version for op in ["==", ">=", "<=", "~=", ">", "<"]):
+ python_deps.append(f"{pkg_name}=={version}")
+ else:
+ python_deps.append(f"{pkg_name}{version}")
+ else:
+ python_deps.append(pkg_name)
+
+ elif dep_type.lower() == "npm":
+ # Handle NPM package with version
+ if version and version.lower() != "latest":
+ if not version.startswith("@"):
+ version = "@" + version
+ npm_deps.append(f"{pkg_name}{version}")
+ else:
+ npm_deps.append(pkg_name)
+
+ # Update sandbox state with new dependencies
+ sandbox_state["code_dependencies"] = (python_deps, npm_deps)
+
+ # increase edit round
+ sandbox_state['edit_round'] += 1
+
+ # First yield: Update UI with success message
+ yield (
+ gr.Markdown("Dependencies updated successfully"),
+ gr.skip(), # sandbox_ui
+ gr.skip(), # sandbox_code
+ sandbox_dependency, # Return the same dataframe
+ )
+
+ # Second yield: Run code with new dependencies
+ yield from on_run_code(
+ state,
+ sandbox_state,
+ sandbox_output_md,
+ sandbox_ui,
+ sandbox_code,
+ sandbox_dependency,
+ )
+
+
+def on_click_code_message_run(
+ state,
+ sandbox_state: ChatbotSandboxState,
+ sandbox_output_md: gr.Markdown,
+ sandbox_ui: SandboxComponent,
+ sandbox_code: str,
+ sandbox_dependency: gr.Dataframe,
+ evt: gr.SelectData
+) -> Generator[SandboxGradioSandboxComponents, None, None]:
+ '''
+ Gradio Handler when run code button in message is clicked. Update Sandbox components.
+ '''
+ print("on_click_code_message_run")
+
+ if sandbox_state['enable_sandbox'] is False:
+ yield None, None, None, None
+ return
+ if not evt.value.endswith(RUN_CODE_BUTTON_HTML):
+ yield gr.skip(), gr.skip(), gr.skip(), gr.skip()
+ return
+
+ message = evt.value.replace(RUN_CODE_BUTTON_HTML, "").strip()
+ extract_result = extract_code_from_markdown(
+ message=message,
+ enable_auto_env=sandbox_state['sandbox_environment'] == SandboxEnvironment.AUTO
+ )
+ if extract_result is None:
+ yield gr.skip(), gr.skip(), gr.skip(), gr.skip()
+ return
+
+ code, code_language, code_dependencies, env_selection = extract_result
+
+ # As sandbox is reused, no need to skip
+ # if sandbox_state['code_to_execute'] == code and sandbox_state['code_language'] == code_language:
+ # # skip if no changes
+ # yield gr.skip(), gr.skip(), gr.skip(), gr.skip()
+ # return
+
+ if code_language == 'tsx':
+ code_language = 'typescript'
+ code_language = code_language.lower()
+ gradio_code_language = code_language.lower() if code_language and code_language.lower(
+ # ensure gradio supports the code language
+ ) in VALID_GRADIO_CODE_LANGUAGES else None
+
+ python_deps, npm_deps = code_dependencies
+
+ # Convert to dataframe format
+ dependencies = []
+
+ # Add Python packages with versions
+ for dep in python_deps:
+ # Check if package has version specifier
+ if any(op in dep for op in ['==', '>=', '<=', '~=']):
+ # Split on first occurrence of version operator
+ pkg_name = dep.split('==')[0].split('>=')[0].split('<=')[0].split('~=')[0]
+ version = dep[len(pkg_name):] # Get everything after package name
+ dependencies.append(["python", pkg_name, version])
+ else:
+ dependencies.append(["python", dep, "latest"])
+
+ # Add NPM packages with versions
+ for dep in npm_deps:
+ # Check if package has version specifier
+ if '@' in dep and not dep.startswith('@'):
+ # Handle non-scoped packages with version
+ pkg_name, version = dep.split('@', 1)
+ dependencies.append(["npm", pkg_name, '@' + version])
+ elif '@' in dep[1:]: # Handle scoped packages with version
+ # Split on last @ for scoped packages
+ pkg_parts = dep.rsplit('@', 1)
+ dependencies.append(["npm", pkg_parts[0], '@' + pkg_parts[1]])
+ else:
+ dependencies.append(["npm", dep, "latest"])
+
+ # If no dependencies found, provide default empty rows
+ if not dependencies:
+ dependencies = [["python", "", ""], ["npm", "", ""]]
+
+ sandbox_state['code_to_execute'] = code
+ sandbox_state['code_language'] = code_language
+ sandbox_state["code_dependencies"] = code_dependencies
+ if sandbox_state['sandbox_environment'] == SandboxEnvironment.AUTO:
+ sandbox_state['auto_selected_sandbox_environment'] = env_selection
+
+ # reset edit round
+ sandbox_state['edit_round'] = 0
+
+ yield (
+ gr.skip(), # sandbox_output_md
+ gr.skip(), # sandbox_ui
+ gr.update(value=code, language=gradio_code_language), # sandbox_code
+ gr.update(value=dependencies) # sandbox_dependency
+ )
+
+ yield from on_run_code(
+ state,
+ sandbox_state,
+ sandbox_output_md,
+ sandbox_ui,
+ sandbox_code,
+ sandbox_dependency,
+ )
+
+
+def on_run_code(
+ state,
+ sandbox_state: ChatbotSandboxState,
+ sandbox_output_md: gr.Markdown,
+ sandbox_ui: SandboxComponent,
+ sandbox_code: str,
+ sandbox_dependency: gr.Dataframe,
+) -> Generator[tuple[Any, Any, Any, Any], None, None]:
+ '''
+ gradio fn when run code button is clicked. Update Sandbox components.
+ '''
+ print("on_run_code")
+
+ if sandbox_state['enable_sandbox'] is False:
+ yield None, None, None, None
+ return
+
+ # validate e2b api key
+ if not E2B_API_KEY:
+ raise ValueError("E2B_API_KEY is not set in env vars.")
+
+ # hide and change value of the current sandbox UI to force refresh the sandbox
+ # otherwise the sandbox might not change if the url is same
+ yield (
+ gr.skip(),
+ SandboxComponent(
+ value=('', False, []),
+ label="Example",
+ visible=False,
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+
+ code, code_language = sandbox_state['code_to_execute'], sandbox_state['code_language']
+ if code is None or code_language is None:
+ yield None, None, None, None
+ return
+
+ gradio_code_language = code_language.lower() if code_language and code_language.lower(
+ # ensure gradio supports the code language
+ ) in VALID_GRADIO_CODE_LANGUAGES else None
+
+ # Use dependencies from sandbox_state instead of re-extracting
+ code_dependencies = sandbox_state['code_dependencies']
+ python_deps, npm_deps = code_dependencies
+
+ # Helper function to extract package name without version
+ def get_base_package_name(pkg: str) -> str:
+ # For Python packages
+ if any(op in pkg for op in ['==', '>=', '<=', '~=', '>', '<']):
+ return pkg.split('==')[0].split('>=')[0].split('<=')[0].split('~=')[0].split('>')[0].split('<')[0]
+ # For NPM packages
+ if '@' in pkg and not pkg.startswith('@'):
+ return pkg.split('@')[0]
+ elif '@' in pkg[1:]: # Handle scoped packages
+ return pkg.rsplit('@', 1)[0]
+ return pkg
+
+ # Helper function to extract version from package string
+ def get_package_version(pkg: str) -> str:
+ # For Python packages
+ if any(op in pkg for op in ['==', '>=', '<=', '~=', '>', '<']):
+ base_name = get_base_package_name(pkg)
+ return pkg[len(base_name):]
+ # For NPM packages
+ if '@' in pkg and not pkg.startswith('@'):
+ return '@' + pkg.split('@', 1)[1]
+ elif '@' in pkg[1:]: # Handle scoped packages
+ _, version = pkg.rsplit('@', 1)
+ return '@' + version
+ return "latest"
+
+ # Create unified dependency dictionaries to avoid duplicates
+ python_deps_dict = {} # pkg_name -> version
+ npm_deps_dict = {} # pkg_name -> version
+
+ # Process Python dependencies
+ for dep in python_deps:
+ base_name = get_base_package_name(dep)
+ version = get_package_version(dep)
+ # Only update if we don't have a version yet or if we're replacing 'latest'
+ if base_name not in python_deps_dict or python_deps_dict[base_name] == "latest":
+ python_deps_dict[base_name] = version
+
+ # Process NPM dependencies
+ for dep in npm_deps:
+ base_name = get_base_package_name(dep)
+ version = get_package_version(dep)
+ # Only update if we don't have a version yet or if we're replacing 'latest'
+ if base_name not in npm_deps_dict or npm_deps_dict[base_name] == "latest":
+ npm_deps_dict[base_name] = version
+
+ # Convert unified dictionaries to dataframe format
+ dependencies = []
+ for pkg_name, version in python_deps_dict.items():
+ dependencies.append(["python", pkg_name, version])
+ for pkg_name, version in npm_deps_dict.items():
+ dependencies.append(["npm", pkg_name, version])
+
+ # If no dependencies found, provide default empty rows
+ if not dependencies:
+ dependencies = [["python", "", ""], ["npm", "", ""]]
+
+ # Initialize output with loading message
+ markdown_output_text = "### Sandbox Execution Log\n\n"
+ yield (
+ gr.Markdown(
+ value=markdown_output_text + "๐ Initializing sandbox environment...", visible=True
+ ),
+ SandboxComponent(visible=False),
+ gr.Code(value=code, language=gradio_code_language, visible=True),
+ gr.update(value=dependencies, visible=True), # Update with unified dependencies
+ )
+
+ # Use auto_selected_sandbox_environment only when in AUTO mode, otherwise use sandbox_environment
+ sandbox_env = (
+ sandbox_state['auto_selected_sandbox_environment']
+ if sandbox_state['sandbox_environment'] == SandboxEnvironment.AUTO
+ else sandbox_state['sandbox_environment']
+ )
+
+ def update_markdown_output(message: str, clear_output: bool = False):
+ nonlocal markdown_output_text
+ if clear_output:
+ markdown_output_text = ""
+ markdown_output_text += f"\n{message}"
+ return (
+ gr.Markdown(value=markdown_output_text, visible=True, sanitize_html=False),
+ gr.skip(),
+ gr.skip(),
+ gr.skip() # Always include dependencies update
+ )
+
+ sandbox_id: str | None = sandbox_state["sandbox_id"] # the sandbox id
+ sandbox_output: str = "" # stdout from sandbox
+ sandbox_error: str = "" # stderr from sandbox
+ print(f"sandbox_env: {sandbox_env}")
+ match sandbox_env:
+ case SandboxEnvironment.HTML:
+ yield update_markdown_output("๐ Setting up HTML sandbox...")
+ sandbox_url, sandbox_id, sandbox_error = run_html_sandbox(
+ code=code,
+ code_dependencies=code_dependencies,
+ existing_sandbox_id=sandbox_state['sandbox_id'],
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ HTML sandbox failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
HTML sandbox is ready!", clear_output=True)
+ yield (
+ gr.Markdown(value=markdown_output_text, visible=True),
+ SandboxComponent(
+ value=(sandbox_url, True, []),
+ label="Example",
+ visible=True,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.REACT:
+ yield update_markdown_output("๐ Setting up React sandbox...")
+ code_run_result = run_react_sandbox(
+ code=code,
+ code_dependencies=code_dependencies,
+ existing_sandbox_id=sandbox_state['sandbox_id'],
+ )
+ sandbox_id, sandbox_error = code_run_result['sandbox_id'], code_run_result['stderr']
+ if code_run_result['is_run_success'] is False and sandbox_error:
+ yield update_markdown_output("โ React sandbox failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
React sandbox is ready!", clear_output=True)
+ yield (
+ gr.Markdown(value=markdown_output_text, visible=True),
+ SandboxComponent(
+ value=(code_run_result['sandbox_url'], True, []),
+ label="Example",
+ visible=True,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.VUE:
+ yield update_markdown_output("๐ Setting up Vue sandbox...")
+ code_run_result = run_vue_sandbox(
+ code=code,
+ code_dependencies=code_dependencies,
+ existing_sandbox_id=sandbox_state['sandbox_id'],
+ )
+ sandbox_id, sandbox_error = code_run_result['sandbox_id'], code_run_result['stderr']
+ if code_run_result['is_run_success'] is False and code_run_result['stderr']:
+ yield update_markdown_output("โ Vue sandbox failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{code_run_result['stderr']}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Vue sandbox is ready!", clear_output=True)
+ yield (
+ gr.Markdown(value=markdown_output_text, visible=True),
+ SandboxComponent(
+ value=(code_run_result['sandbox_url'], True, []),
+ label="Example",
+ visible=True,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.PYGAME:
+ yield update_markdown_output("๐ Setting up PyGame sandbox...")
+ code_run_result = run_pygame_sandbox(
+ code=code,
+ code_dependencies=code_dependencies,
+ existing_sandbox_id=sandbox_state['sandbox_id'],
+ )
+ sandbox_id, sandbox_error = code_run_result['sandbox_id'], code_run_result['stderr']
+ if code_run_result['is_run_success'] is False and code_run_result['stderr']:
+ yield update_markdown_output("โ PyGame sandbox failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{code_run_result['stderr']}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
PyGame sandbox is ready!", clear_output=True)
+ yield (
+ gr.Markdown(value=markdown_output_text, visible=True),
+ SandboxComponent(
+ value=(code_run_result['sandbox_url'], True, []),
+ label="Example",
+ visible=True,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.GRADIO:
+ yield update_markdown_output("๐ Setting up Gradio sandbox...")
+ sandbox_url, sandbox_id, sandbox_error = run_gradio_sandbox(
+ code=code,
+ code_dependencies=code_dependencies,
+ existing_sandbox_id=sandbox_state['sandbox_id'],
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ Gradio sandbox failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Gradio sandbox is ready!", clear_output=True)
+ yield (
+ gr.Markdown(value=markdown_output_text, visible=True),
+ SandboxComponent(
+ value=(sandbox_url, True, []),
+ label="Example",
+ visible=True,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.STREAMLIT:
+ yield update_markdown_output("๐ Setting up Streamlit sandbox...")
+ sandbox_url, sandbox_id, sandbox_error = run_streamlit_sandbox(
+ code=code,
+ code_dependencies=code_dependencies,
+ existing_sandbox_id=sandbox_state['sandbox_id'],
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ Streamlit sandbox failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Streamlit sandbox is ready!", clear_output=True)
+ yield (
+ gr.Markdown(value=markdown_output_text, visible=True),
+ SandboxComponent(
+ value=(sandbox_url, True, []),
+ label="Example",
+ visible=True,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.MERMAID:
+ yield update_markdown_output("๐ Setting up Mermaid visualization...")
+ # Convert Mermaid to HTML at execution time
+ html_code = mermaid_to_html(code, theme='light')
+ sandbox_url, sandbox_id, sandbox_error = run_html_sandbox(
+ code=html_code,
+ code_dependencies=code_dependencies,
+ existing_sandbox_id=sandbox_state['sandbox_id'],
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ Mermaid visualization failed to render!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Mermaid visualization is ready!", clear_output=True)
+ yield (
+ gr.Markdown(value=markdown_output_text, visible=True),
+ SandboxComponent(
+ value=(sandbox_url, True, []),
+ label="Mermaid Diagram",
+ visible=True,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.PYTHON_RUNNER:
+ yield update_markdown_output("๐ Running Python Runner...", clear_output=True)
+ sandbox_output, sandbox_error = run_code_interpreter(
+ code=code, code_language='python', code_dependencies=code_dependencies
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ Python Runner failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Code execution is ready!", clear_output=True)
+ yield (
+ gr.Markdown(
+ value=markdown_output_text + "\n\n" + sandbox_output,
+ sanitize_html=False,
+ visible=True,
+ ),
+ SandboxComponent(
+ value=("", False, []),
+ label="Example",
+ visible=False,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.JAVASCRIPT_RUNNER:
+ yield update_markdown_output("๐ Running JavaScript Runner...", clear_output=True)
+ sandbox_output, sandbox_error = run_code_interpreter(
+ code=code, code_language='javascript', code_dependencies=code_dependencies
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ JavaScript Runner failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Code execution is ready!", clear_output=True)
+ yield (
+ gr.Markdown(
+ value=markdown_output_text + "\n\n" + sandbox_output,
+ sanitize_html=False,
+ visible=True,
+ ),
+ SandboxComponent(
+ value=("", False, []),
+ label="Example",
+ visible=False,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.C_RUNNER:
+ yield update_markdown_output("๐ Running C Runner...", clear_output=True)
+ sandbox_output, sandbox_error = run_c_code(
+ code=code, existing_sandbox_id=sandbox_state['sandbox_id']
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ C Runner failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Code execution is ready!", clear_output=True)
+ yield (
+ gr.Markdown(
+ value=markdown_output_text + "\n\n" + f"```markdown\n{sandbox_output}\n```",
+ sanitize_html=False,
+ visible=True,
+ ),
+ SandboxComponent(
+ value=("", False, []),
+ label="Example",
+ visible=False,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.CPP_RUNNER:
+ yield update_markdown_output("๐ Running C++ Runner...", clear_output=True)
+ sandbox_output, sandbox_error = run_cpp_code(
+ code=code, existing_sandbox_id=sandbox_state['sandbox_id']
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ C++ Runner failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Code execution is ready!", clear_output=True)
+ yield (
+ gr.Markdown(
+ value=markdown_output_text + "\n\n" + f"```markdown\n{sandbox_output}\n```",
+ sanitize_html=False,
+ visible=True,
+ ),
+ SandboxComponent(
+ value=("", False, []),
+ label="Example",
+ visible=False,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.JAVA_RUNNER:
+ yield update_markdown_output("๐ Running Java Runner...", clear_output=True)
+ sandbox_output, sandbox_error = run_java_code(
+ code=code, existing_sandbox_id=sandbox_state['sandbox_id']
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ Java Runner failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Code execution is ready!", clear_output=True)
+ yield (
+ gr.Markdown(
+ value=markdown_output_text + "\n\n" + f"```markdown\n{sandbox_output}\n```",
+ sanitize_html=False,
+ visible=True,
+ ),
+ SandboxComponent(
+ value=("", False, []),
+ label="Example",
+ visible=False,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case SandboxEnvironment.GOLANG_RUNNER:
+ yield update_markdown_output("๐ Running Go Runner...", clear_output=True)
+ sandbox_output, sandbox_error = run_golang_code(
+ code=code, existing_sandbox_id=sandbox_state['sandbox_id']
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ Go Runner failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Code execution is ready!", clear_output=True)
+ yield (
+ gr.Markdown(
+ value=markdown_output_text + "\n\n" + f"```markdown\n{sandbox_output}\n```",
+ sanitize_html=False,
+ visible=True,
+ ),
+ SandboxComponent(
+ value=("", False, []),
+ label="Example",
+ visible=False,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ # case SandboxEnvironment.CSHARP_RUNNER:
+ # yield update_markdown_output("๐ Running C# Runner...", clear_output=True)
+ # output, stderr = run_csharp_code(
+ # code=code, existing_sandbox_id=sandbox_state['sandbox_id']
+ # )
+ # yield update_markdown_output("โ
Code execution is ready!", clear_output=True)
+ # if output:
+ # yield update_markdown_output(f"### Stdout:\n```markdown\n{output}\n```\n\n")
+ # if stderr:
+ # yield update_markdown_output(f"### Stderr:\n```markdown\n{stderr}\n```\n\n")
+ case SandboxEnvironment.RUST_RUNNER:
+ yield update_markdown_output("๐ Running Rust Runner...", clear_output=True)
+ sandbox_output, sandbox_error = run_rust_code(
+ code=code, existing_sandbox_id=sandbox_state['sandbox_id']
+ )
+ if sandbox_error:
+ yield update_markdown_output("โ Rust Runner failed to run!", clear_output=True)
+ yield update_markdown_output(f"### Stderr:\n```markdown\n{sandbox_error}\n```\n\n")
+ else:
+ yield update_markdown_output("โ
Code execution is ready!", clear_output=True)
+ yield (
+ gr.Markdown(
+ value=markdown_output_text + "\n\n" + f"```markdown\n{sandbox_output}\n```",
+ sanitize_html=False,
+ visible=True,
+ ),
+ SandboxComponent(
+ value=("", False, []),
+ label="Example",
+ visible=False,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+ case _:
+ yield (
+ gr.Markdown(value=code, visible=True),
+ SandboxComponent(
+ value=("", False, []),
+ label="Example",
+ visible=False,
+ key="newsandbox",
+ ),
+ gr.skip(),
+ gr.skip(),
+ )
+
+ sandbox_state['sandbox_run_round'] += 1
+ sandbox_state["sandbox_output"] = sandbox_output # record sandbox output if exists
+ sandbox_state["sandbox_error"] = sandbox_error # record sandbox error if exists
+ # generate a random sandbox id if not exists as some code runners might not return sandbox id
+ sandbox_state['sandbox_id'] = sandbox_id if sandbox_id else str(uuid.uuid4())
+ log_sandbox_telemetry_gradio_fn(
+ sandbox_state=sandbox_state,
+ sandbox_ui_value=None,
+ )
+
+ print("on_run_code done")
\ No newline at end of file
diff --git a/sandbox/constants.py b/sandbox/constants.py
new file mode 100644
index 0000000000000000000000000000000000000000..540a6c5763c8fd21131557efb63c27e01c35146a
--- /dev/null
+++ b/sandbox/constants.py
@@ -0,0 +1,148 @@
+'''
+Constants for sandbox.
+'''
+
+import os
+
+E2B_API_KEY = os.environ.get("E2B_API_KEY")
+'''
+API key for the e2b API.
+'''
+
+AZURE_BLOB_STORAGE_CONNECTION_STRING = os.environ.get("AZURE_STORAGE_CONNECTION_STRING")
+'''
+API key for the Azure Blob Storage.
+'''
+
+AZURE_BLOB_STORAGE_CONTAINER_NAME = "softwarearenalogs"
+'''
+Contianer name for the Azure Blob Storage.
+'''
+
+SANDBOX_TEMPLATE_ID: str = "bxq9sha9l55ytsyfturr"
+'''
+Template ID for the sandbox.
+'''
+
+SANDBOX_NGINX_PORT: int = 8000
+'''
+Nginx port for the sandbox.
+'''
+
+SANDBOX_TIMEOUT_SECONDS: int = 1 * 60
+'''
+Timeout in seconds for created sandboxes to expire.
+'''
+
+CODE_RUN_TIMEOUT_SECONDS: int = 60
+'''
+Timeout in seconds for code execution.
+'''
+
+SANDBOX_RETRY_COUNT: int = 3
+'''
+Number of times to retry the sandbox creation.
+'''
+
+INSTALLED_PYPI_PACKAGES = [
+ "boto3",
+ "botocore",
+ "urllib3",
+ "setuptools",
+ "requests",
+ "certifi",
+ "idna",
+ "charset-normalizer",
+ "packaging",
+ "typing-extensions",
+ "python-dateutil",
+ "aiobotocore",
+ "s3transfer",
+ "grpcio-status",
+ "pyyaml",
+ "six",
+ "fsspec",
+ "s3fs",
+ "numpy",
+ "wheel",
+ "pip",
+ "cryptography",
+ "awscli",
+ "pydantic",
+ "cffi",
+ "attrs",
+ "google-api-core",
+ "pycparser",
+ "pandas",
+ "importlib-metadata",
+ "jmespath",
+ "click",
+ "zipp",
+ "rsa",
+ "pyasn1",
+ "markupsafe",
+ "pytz",
+ "colorama",
+ "protobuf",
+ "platformdirs",
+ "jinja2",
+ "rich",
+ "tomli",
+ "pytest",
+ "pydantic-core",
+ "pyjwt",
+ "pluggy",
+ "aiohttp",
+ "virtualenv",
+ "jsonschema",
+ "googleapis-common-protos",
+ "cachetools",
+ "google-auth",
+ "filelock",
+ "wrapt",
+ "sqlalchemy",
+ "docutils",
+ "pyasn1-modules",
+ "pyarrow",
+ "greenlet",
+ "iniconfig",
+ "pygments",
+ "annotated-types",
+ "yarl",
+ "requests-oauthlib",
+ "tzdata",
+ "psutil",
+ "multidict",
+ "pyparsing",
+ "requests-toolbelt",
+ "exceptiongroup",
+ "werkzeug",
+ "soupsieve",
+ "oauthlib",
+ "beautifulsoup4",
+ "frozenlist",
+ "more-itertools",
+ "distlib",
+ "tomlkit",
+ "pathspec",
+ "aiosignal",
+ "grpcio",
+ "tqdm",
+ "scipy",
+ "async-timeout",
+ "pillow",
+ "isodate",
+ "anyio",
+ "sortedcontainers",
+ "decorator",
+ "markdown-it-py",
+ "deprecated",
+ "mypy-extensions",
+ "sniffio",
+ "httpx",
+ "coverage",
+ "openpyxl",
+ "flask",
+ "rpds-py",
+ "et-xmlfile"
+]
\ No newline at end of file
diff --git a/sandbox/prompts.py b/sandbox/prompts.py
new file mode 100644
index 0000000000000000000000000000000000000000..49771bcca0b2bc8a84b7e3c09fe50df7d57ac7af
--- /dev/null
+++ b/sandbox/prompts.py
@@ -0,0 +1,393 @@
+'''
+Prompts for the sandbox.
+'''
+
+GENERAL_SANDBOX_INSTRUCTION = """\
+You are an expert Software Engineer, UI/UX designer, and product manager. Your task is to generate self-contained, executable code for a single file or block that can run directly in a sandbox environment. Feel free to ask questions or explain your reasoning.
+If you do a great job based on the instructions, you will be rewarded with a high salary and a promotion.
+
+Your code must be written using one of these supported development frameworks and environments:
+- React (JavaScript/TypeScript)
+- Vue (JavaScript/TypeScript)
+- HTML (Vanilla HTML)
+- Gradio (Python)
+- Streamlit (Python)
+- PyGame (Python)
+- Mermaid (Markdown)
+- Python Runner
+- JavaScript Runner
+- Command Line Code Runner (C/C++/Go/Java/Rust)
+
+All web framework code (React, Vue, HTML) must be directly rendered in a browser and immediately executable without additional setup. DO NOT create separate CSS files
+Python-based frameworks should be directly executable in a browser environment.
+The code to be executed in Runners must be plain Python or JavaScript programs that do not require web UI frameworks or standard user input.
+
+The code must be in the markdown format:
+```
+
+```
+
+Before you begin writing any code, you must follow these fundamental rules:
+- You are NOT allowed to start directly with a code block. Before writing code, ALWAYS think carefully step-by-step
+- Your response must contain a clear explanation of the solution you are providing
+- ALWAYS generate complete, self-contained code in a single file
+- You CAN NOT split your program into multiple files or multiple code blocks
+- If you use any external libraries, make sure to specify them for the installation command in either `pip install` or `npm install`
+- You prefer JavaScript over HTML
+- Each code block must be completely independent. If modifications are needed, the entire code block must be rewritten
+- When fetching data, you MUST use external libraries and packages, and avoid using placeholder URLs or URLs that require API keys
+- Make sure the program is functional by creating a state when needed and having no required props
+- Make sure to include all necessary code in one file
+- There are no additional files in the local file system, unless you create them inside the same program
+- Do not touch project dependencies files like package.json, package-lock.json, requirements.txt, etc
+
+When developing with React or Vue components, follow these specific requirements:
+- Use TypeScript or JavaScript as the language
+- DO NOT use gray text color on a white background
+- Make sure it can run by itself by using a default export at the end of the file
+- DO NOT CALL `ReactDOM.render()` AT THE END OF THE FILE
+- Use Tailwind classes for styling. DO NOT USE ARBITRARY VALUES (e.g. 'h-[600px]'). Make sure to use a consistent color palette
+- If you use any imports from React like `useState` or `useEffect`, make sure to import them directly
+- Use Tailwind margin and padding classes to style the components and ensure proper spacing
+- Various npm packages are available to be imported, e.g. `import { LineChart, XAxis, ... } from "recharts"` & ` ...`
+- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so `
`
+
+For Python development, you must follow these constraints:
+- For any programs that require user inputs, you MUST USE `gradio` or `streamlit`
+- Choose suitable PyPI packages to be imported, e.g., `import pandas`
+- Avoid using libraries that require desktop GUI interfaces, with the exceptions of `pygame`, `gradio`, and `streamlit` which are explicitly supported
+- For PyGame applications, you have to write the main function as an async function like:
+```python
+import asyncio
+import pygame
+
+async def main():
+ global game_state
+ while game_state:
+ game_state(pygame.event.get())
+ pygame.display.update()
+ await asyncio.sleep(0) # it must be called on every frame
+
+if __name__ == "__main__":
+ asyncio.run(main())
+```
+
+For HTML development, ensure that:
+- All HTML code must be self-contained in a single file
+- Include any necessary CSS and JavaScript within the HTML file
+- Ensure the code is directly executable in a browser environment
+- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so `
`
+
+For Mermaid development:
+- Write Mermaid diagrams directly using ```mermaid code blocks, e.g.:
+```mermaid
+graph TD;
+ A-->B;
+```
+
+For Command Line Code Runner (C/C++/Go/Java/Rust), ensure that:
+- ALWAYS generate complete, self-contained code in a single file. Avoid non-standard libraries.
+- Your code should be able to be compiled and run directly.
+- Your code must complete the task without any user inputs. It should not be long running.
+- You should provide example test cases in the code and output the result to stdout or stderr.
+
+The code must be in the markdown format:
+```
+
+```
+"""
+
+DEFAULT_PYTHON_RUNNER_INSTRUCTION = """
+You are an expert Software Engineer. Your task is to generate self-contained, executable Python code that can run directly in a code interpreter environment.
+
+Before you begin writing any code, you must follow these fundamental rules:
+- You are NOT allowed to start directly with a code block. Before writing code, ALWAYS think carefully step-by-step
+- Your response must contain a clear explanation of the solution you are providing
+- ALWAYS generate complete, self-contained code in a single file
+- If you use any external libraries, make sure to specify them for installation with `pip install`
+- Make sure to include all necessary code in one file
+- Make sure it does not require any user inputs
+- Choose suitable PyPI packages to be imported, e.g., `import pandas`
+
+The code must be in the markdown format:
+```python
+
+```
+
+You can output in stdout, stderr, or render images, plots, and tables.
+"""
+
+DEFAULT_JAVASCRIPT_RUNNER_INSTRUCTION = """
+You are an expert Software Engineer. Your task is to generate self-contained JavaScript code that can run directly in a code interpreter environment.
+
+Before you begin writing any code, you must follow these fundamental rules:
+- You are NOT allowed to start directly with a code block. Before writing code, ALWAYS think carefully step-by-step
+- Your response must contain a clear explanation of the solution you are providing
+- ALWAYS generate complete, self-contained code in a single file
+- If you use any external libraries, make sure to specify them for installation with `npm install`
+- Make sure to include all necessary code in one file
+- Ensure the code is self-contained and does not rely on browser-specific APIs
+
+The code must be in the markdown format:
+```javascript
+
+```
+
+You can output in stdout, stderr, or render images, plots, and tables.
+"""
+
+DEFAULT_HTML_SANDBOX_INSTRUCTION = """
+You are an expert Software Engineer and UI/UX designer. Your task is to generate self-contained HTML code that can run directly in a browser environment.
+
+Before you begin writing any code, you must follow these fundamental rules:
+- You are NOT allowed to start directly with a code block. Before writing code, ALWAYS think carefully step-by-step
+- Your response must contain a clear explanation of the solution you are providing
+- ALWAYS generate complete, self-contained code in a single file
+- Include any necessary CSS and JavaScript within the HTML file
+- If you use any external libraries, make sure to specify them
+- Make sure the program is functional by creating a state when needed
+- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so `
`
+
+The code must be in the markdown format:
+```html
+
+```
+
+For HTML development, ensure that:
+- All HTML code must be self-contained in a single file
+- Include any necessary CSS and JavaScript within the HTML file
+- Ensure the code is directly executable in a browser environment
+- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so `
`
+"""
+
+DEFAULT_REACT_SANDBOX_INSTRUCTION = """
+You are an expert Software Engineer and UI/UX designer. Your task is to generate a self-contained React component using TypeScript that can run directly in a browser environment.
+
+Before you begin writing any code, you must follow these fundamental rules:
+- You are NOT allowed to start directly with a code block. Before writing code, ALWAYS think carefully step-by-step
+- Your response must contain a clear explanation of the solution you are providing
+- ALWAYS generate complete, self-contained code in a single file
+- If you use any external libraries, make sure to specify them for installation with `npm install`
+- Make sure the program is functional by creating a state when needed and having no required props
+- Make sure it can run by itself by using a default export at the end of the file
+- DO NOT CALL `ReactDOM.render()` AT THE END OF THE FILE
+- Use Tailwind classes for styling. DO NOT USE ARBITRARY VALUES (e.g. 'h-[600px]'). Make sure to use a consistent color palette
+- If you use any imports from React like `useState` or `useEffect`, make sure to import them directly
+- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so `
`
+
+The code must be in the markdown format:
+```typescript
+
+```
+
+When developing with React components, follow these specific requirements:
+- Use TypeScript or JavaScript as the language
+- DO NOT use gray text color on a white background
+- Make sure it can run by itself by using a default export at the end of the file
+- DO NOT CALL `ReactDOM.render()` AT THE END OF THE FILE
+- Use Tailwind classes for styling. DO NOT USE ARBITRARY VALUES (e.g. 'h-[600px]'). Make sure to use a consistent color palette
+- If you use any imports from React like `useState` or `useEffect`, make sure to import them directly
+- Use Tailwind margin and padding classes to style the components and ensure proper spacing
+- Various npm packages are available to be imported, e.g. `import { LineChart, XAxis, ... } from "recharts"` & ` ...`
+- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so `
`
+"""
+
+DEFAULT_VUE_SANDBOX_INSTRUCTION = """
+You are an expert Software Engineer and UI/UX designer. Your task is to generate a self-contained Vue.js component using TypeScript that can run directly in a browser environment.
+
+Before you begin writing any code, you must follow these fundamental rules:
+- You are NOT allowed to start directly with a code block. Before writing code, ALWAYS think carefully step-by-step
+- Your response must contain a clear explanation of the solution you are providing
+- ALWAYS generate complete, self-contained code in a single file
+- If you use any external libraries, make sure to specify them for installation with `npm install`
+- Make sure the program is functional by creating a state when needed and having no required props
+- The component should be a simple custom page in a styled `` element
+- Do not include or reference any external components
+- Use Tailwind classes for styling. DO NOT USE ARBITRARY VALUES (e.g. 'h-[600px]'). Make sure to use a consistent color palette
+- Images from the web are not allowed, but you can use placeholder images by specifying the width and height like so `
`
+
+The code must be in the markdown format:
+```vue
+
+```
+
+When developing with Vue components, follow these specific requirements:
+- Use Vue 3's Composition API with