mixin.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import os
  2. from typing import List, Protocol, Tuple
  3. from opendevin.core.logger import opendevin_logger as logger
  4. from opendevin.runtime.plugins.requirement import PluginRequirement
  5. class SandboxProtocol(Protocol):
  6. # https://stackoverflow.com/questions/51930339/how-do-i-correctly-add-type-hints-to-mixin-classes
  7. def execute(self, cmd: str) -> Tuple[int, str]: ...
  8. def copy_to(self, host_src: str, sandbox_dest: str, recursive: bool = False): ...
  9. class PluginMixin:
  10. """Mixin for Sandbox to support plugins."""
  11. def init_plugins(self: SandboxProtocol, requirements: List[PluginRequirement]):
  12. """Load a plugin into the sandbox."""
  13. for requirement in requirements:
  14. # copy over the files
  15. self.copy_to(requirement.host_src, requirement.sandbox_dest, recursive=True)
  16. logger.info(
  17. f'Copied files from [{requirement.host_src}] to [{requirement.sandbox_dest}] inside sandbox.'
  18. )
  19. # Execute the bash script
  20. abs_path_to_bash_script = os.path.join(
  21. requirement.sandbox_dest, requirement.bash_script_path
  22. )
  23. logger.info(
  24. f'Initializing plugin [{requirement.name}] by executing [{abs_path_to_bash_script}] in the sandbox.'
  25. )
  26. exit_code, output = self.execute(abs_path_to_bash_script)
  27. if exit_code != 0:
  28. raise RuntimeError(
  29. f'Failed to initialize plugin {requirement.name} with exit code {exit_code} and output {output}'
  30. )
  31. logger.info(
  32. f'Plugin {requirement.name} initialized successfully\n:{output}'
  33. )
  34. if len(requirements) > 0:
  35. exit_code, output = self.execute('source ~/.bashrc')
  36. if exit_code != 0:
  37. raise RuntimeError(
  38. f'Failed to source ~/.bashrc with exit code {exit_code} and output {output}'
  39. )
  40. logger.info('Sourced ~/.bashrc successfully')