sandbox.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import json
  2. import os
  3. from abc import ABC, abstractmethod
  4. from opendevin.core.config import config
  5. from opendevin.core.schema import CancellableStream
  6. from opendevin.runtime.docker.process import Process
  7. from opendevin.runtime.plugins.mixin import PluginMixin
  8. class Sandbox(ABC, PluginMixin):
  9. background_commands: dict[int, Process] = {}
  10. _env: dict[str, str] = {}
  11. is_initial_session: bool = True
  12. def __init__(self, **kwargs):
  13. for key in os.environ:
  14. if key.startswith('SANDBOX_ENV_'):
  15. sandbox_key = key.removeprefix('SANDBOX_ENV_')
  16. self.add_to_env(sandbox_key, os.environ[key])
  17. if config.enable_auto_lint:
  18. self.add_to_env('ENABLE_AUTO_LINT', 'true')
  19. self.initialize_plugins: bool = config.initialize_plugins
  20. def add_to_env(self, key: str, value: str):
  21. self._env[key] = value
  22. # Note: json.dumps gives us nice escaping for free
  23. self.execute(f'export {key}={json.dumps(value)}')
  24. @abstractmethod
  25. def execute(
  26. self, cmd: str, stream: bool = False, timeout: int | None = None
  27. ) -> tuple[int, str | CancellableStream]:
  28. pass
  29. @abstractmethod
  30. def execute_in_background(self, cmd: str) -> Process:
  31. pass
  32. @abstractmethod
  33. def kill_background(self, id: int) -> Process:
  34. pass
  35. @abstractmethod
  36. def read_logs(self, id: int) -> str:
  37. pass
  38. @abstractmethod
  39. def close(self):
  40. pass
  41. @abstractmethod
  42. def copy_to(self, host_src: str, sandbox_dest: str, recursive: bool = False):
  43. pass
  44. @abstractmethod
  45. def get_working_directory(self):
  46. pass