Skip to content

Conversation

@alcholiclg
Copy link
Collaborator

Change Summary

Added full support for CodeExecutionTool (based on ms-enclave), enabling secure execution of code blocks in isolated sandboxes with file operation and shell command capabilities, significantly improving reliability and safety of code execution.

  1. Support for creating sandboxes via HTTP or local environments.
  2. Support for two sandbox types — docker-notebook and docker — initialized through configuration files.
  3. Added six execution tools: notebook_executor, python_executor, shell_executor, file_operation, reset_sandbox, and get_sandbox_info.
  4. Implemented retry mechanism for sandbox creation and automatic port scanning to resolve conflicts.
  5. Added corresponding documentation (Chinese version).
  6. Updated dependencies accordingly.

Related issue number

Checklist

  • The pull request title is a good summary of the changes - it will be used in the changelog
  • Unit tests for the changes exist
  • Run pre-commit install and pre-commit run --all-files before git commit, and passed lint check.
  • Documentation reflects the changes where applicable

@gemini-code-assist
Copy link

Summary of Changes

Hello @alcholiclg, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the system's capability by integrating a comprehensive CodeExecutionTool. This tool enables secure and isolated execution of code within sandboxed environments, offering both stateful and stateless options. It provides a suite of specialized tools for various operations, from Python and shell command execution to file manipulation, and includes built-in resilience features like port conflict resolution and sandbox creation retries.

Highlights

  • Code Execution Tool: Introduced a new CodeExecutionTool for secure and isolated code execution using ms-enclave.
  • Sandbox Environments: Supports creating sandboxes via HTTP or local environments, with two types: docker-notebook (stateful) and docker (stateless).
  • New Execution Tools: Added six specific tools: notebook_executor, python_executor, shell_executor, file_operation, reset_sandbox, and get_sandbox_info.
  • Robustness Improvements: Implemented a retry mechanism for sandbox creation and automatic port scanning to resolve conflicts.
  • Documentation: Updated documentation to include details about the new code_execution tool (Chinese version).
  • Dependencies: Added ms-enclave to the project dependencies.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the CodeExecutionTool, enhancing the agent's capabilities by enabling secure code execution within isolated sandboxes. The tool supports both HTTP and local sandbox environments, accommodating docker and docker-notebook types. It includes several executor tools (notebook, python, shell, file operation, reset sandbox, get sandbox info), a retry mechanism for sandbox creation, and automatic port scanning. The changes also include documentation and dependency updates. The review focuses on correctness and maintainability, with suggestions for improved error handling and code clarity.

Comment on lines 822 to 824
elif info.status == SandboxStatus.ERROR:
error_msg = info.metadata.get('error', 'Unknown error')
raise RuntimeError(f'Sandbox failed to start: {error_msg}')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When the sandbox enters an error state, the code retrieves the error message from info.metadata.get('error', 'Unknown error'). However, it does not include the original exception or any other context about why the sandbox entered the error state. It would be helpful to log the entire info.metadata for debugging purposes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines +42 to +44
except OSError as e:
if e.errno == 98 or e.errno == 48: # Address already in use
return False # Port is occupied

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The OSError exception handling only checks for errno 98 and 48, but there might be other relevant errno values indicating address already in use or permission issues. It would be more robust to check for a broader range of potential port binding errors.

Consider including EACCES (13) which indicates permission denied.

return result != 0 # 0 means connection successful, port is occupied
except Exception as e:
logger.warning(f'Error checking port {port}: {e}')
return False # Be conservative: assume occupied if we can't check reliably

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When the port check fails, the function conservatively assumes the port is occupied. However, the log message indicates that the check might be unreliable. It would be better to raise an exception or return a specific error code to allow the calling function to handle this ambiguous state appropriately, rather than assuming the port is occupied.

Comment on lines +80 to +82
logger.error(
f'Could not find available port in range {start_port}-{start_port + max_attempts - 1}'
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The log message indicates that no available port was found, but the function simply returns None. It would be more informative to raise an exception with a descriptive message, providing more context to the caller about why a port could not be found.

Comment on lines +233 to +236
except Exception as e:
error_msg = str(e).lower()
last_error = e

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The code converts the exception e to a lowercase string (error_msg = str(e).lower()) for checking port conflict. This might lead to incorrect detection if the error message contains uppercase letters or if the relevant keywords are not consistently cased. A case-insensitive search would be more reliable.

error_msg = str(e).lower()
is_port_conflict = any(keyword in error_msg.lower()

Comment on lines 284 to 286
raise RuntimeError(
f'Port conflict and no available ports found: {e}'
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If no available ports are found, a RuntimeError is raised, but the original exception e is not included in the new exception's message. It would be helpful to include the original exception for debugging purposes.

raise RuntimeError(
                                    f'Port conflict and no available ports found: {e}'
                                ) from e

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 300 to 302
raise RuntimeError(
f'Sandbox initialization failed after {max_retries} attempts: {last_error}'
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the sandbox initialization fails after multiple retries, a RuntimeError is raised, but the original exception last_error is not chained to the new exception. This makes it harder to trace the root cause of the failure. Chain the original exception to preserve the context.

raise RuntimeError(
                f'Sandbox initialization failed after {max_retries} attempts: {last_error}'
            ) from last_error

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 305 to 306
logger.error(f'Failed to initialize sandbox: {e}', exc_info=True)
raise RuntimeError(f'Sandbox initialization failed: {e}')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When the sandbox initialization fails, the code logs the exception with exc_info=True, which is good for debugging. However, the RuntimeError that is raised does not include the original exception as the cause. It would be better to chain the original exception to the RuntimeError to preserve the exception context.

raise RuntimeError(f'Sandbox initialization failed: {e}') from e

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@alcholiclg alcholiclg merged commit 0a83d4f into modelscope:main Nov 7, 2025
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants