Skip to content
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

Bugfix: Add config to disable plugin initialization for Persistent sandbox #2179

Merged
merged 7 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions opendevin/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class AppConfig(metaclass=Singleton):
disable_color: bool = False
sandbox_user_id: int = os.getuid() if hasattr(os, 'getuid') else 1000
sandbox_timeout: int = 120
initialize_plugins: bool = True
persist_sandbox: bool = False
ssh_port: int = 63710
ssh_password: str | None = None
Expand Down
7 changes: 1 addition & 6 deletions opendevin/core/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,7 @@ async def main(
event_stream=event_stream,
)
runtime = ServerRuntime(event_stream=event_stream, sandbox=sandbox)

if runtime.sandbox.is_initial_session:
logger.info('Initializing plugins in the sandbox')
runtime.init_sandbox_plugins(controller.agent.sandbox_plugins)
else:
logger.info('Plugins are already initialized in the sandbox')
runtime.init_sandbox_plugins(controller.agent.sandbox_plugins)
runtime.init_runtime_tools(controller.agent.runtime_tools, is_async=False)

await event_stream.add_event(MessageAction(content=task), EventSource.USER)
Expand Down
80 changes: 45 additions & 35 deletions opendevin/runtime/plugins/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
class SandboxProtocol(Protocol):
# https://stackoverflow.com/questions/51930339/how-do-i-correctly-add-type-hints-to-mixin-classes

@property
def initialize_plugins(self) -> bool: ...

def execute(
self, cmd: str, stream: bool = False
) -> tuple[int, str | CancellableStream]: ...
Expand All @@ -25,41 +28,48 @@ def init_plugins(self: SandboxProtocol, requirements: list[PluginRequirement]):
if hasattr(self, 'plugin_initialized') and self.plugin_initialized:
return

# clean-up ~/.bashrc and touch ~/.bashrc
exit_code, output = self.execute('rm -f ~/.bashrc && touch ~/.bashrc')

for requirement in requirements:
# copy over the files
self.copy_to(requirement.host_src, requirement.sandbox_dest, recursive=True)
logger.info(
f'Copied files from [{requirement.host_src}] to [{requirement.sandbox_dest}] inside sandbox.'
)

# Execute the bash script
abs_path_to_bash_script = os.path.join(
requirement.sandbox_dest, requirement.bash_script_path
)
logger.info(
f'Initializing plugin [{requirement.name}] by executing [{abs_path_to_bash_script}] in the sandbox.'
)
exit_code, output = self.execute(abs_path_to_bash_script, stream=True)
if isinstance(output, CancellableStream):
for line in output:
if line.endswith('\n'):
line = line[:-1]
_exit_code = output.exit_code()
output.close()
if _exit_code != 0:
raise RuntimeError(
f'Failed to initialize plugin {requirement.name} with exit code {_exit_code} and output {output}'
)
logger.info(f'Plugin {requirement.name} initialized successfully')
else:
if exit_code != 0:
raise RuntimeError(
f'Failed to initialize plugin {requirement.name} with exit code {exit_code} and output: {output}'
)
logger.info(f'Plugin {requirement.name} initialized successfully.')
if self.initialize_plugins:
logger.info('Initializing plugins in the sandbox')

# clean-up ~/.bashrc and touch ~/.bashrc
exit_code, output = self.execute('rm -f ~/.bashrc && touch ~/.bashrc')

for requirement in requirements:
# copy over the files
self.copy_to(
requirement.host_src, requirement.sandbox_dest, recursive=True
)
logger.info(
f'Copied files from [{requirement.host_src}] to [{requirement.sandbox_dest}] inside sandbox.'
)

# Execute the bash script
abs_path_to_bash_script = os.path.join(
requirement.sandbox_dest, requirement.bash_script_path
)
logger.info(
f'Initializing plugin [{requirement.name}] by executing [{abs_path_to_bash_script}] in the sandbox.'
)
exit_code, output = self.execute(abs_path_to_bash_script, stream=True)
if isinstance(output, CancellableStream):
for line in output:
if line.endswith('\n'):
line = line[:-1]
_exit_code = output.exit_code()
output.close()
if _exit_code != 0:
raise RuntimeError(
f'Failed to initialize plugin {requirement.name} with exit code {_exit_code} and output {output}'
)
logger.info(f'Plugin {requirement.name} initialized successfully')
else:
if exit_code != 0:
raise RuntimeError(
f'Failed to initialize plugin {requirement.name} with exit code {exit_code} and output: {output}'
)
logger.info(f'Plugin {requirement.name} initialized successfully.')
else:
logger.info('Skipping plugin initialization in the sandbox')

if len(requirements) > 0:
exit_code, output = self.execute('source ~/.bashrc')
Expand Down
1 change: 1 addition & 0 deletions opendevin/runtime/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def __init__(self, **kwargs):
self.add_to_env(sandbox_key, os.environ[key])
if config.enable_auto_lint:
self.add_to_env('ENABLE_AUTO_LINT', 'true')
self.initialize_plugins: bool = config.initialize_plugins

def add_to_env(self, key: str, value: str):
self._env[key] = value
Expand Down
7 changes: 1 addition & 6 deletions opendevin/server/session/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,7 @@ async def _create_controller(self, start_event: dict):
logger.warning(
'CodeActAgent requires DockerSSHBox as sandbox! Using other sandbox that are not stateful (LocalBox, DockerExecBox) will not work properly.'
)

if self.runtime.sandbox.is_initial_session:
logger.info('Initializing plugins in the sandbox')
self.runtime.init_sandbox_plugins(agent.sandbox_plugins)
else:
logger.info('Plugins are already initialized in the sandbox')
self.runtime.init_sandbox_plugins(agent.sandbox_plugins)
self.runtime.init_runtime_tools(agent.runtime_tools)

self.controller = AgentController(
Expand Down