runtime.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. from opendevin.events.action import (
  2. AgentRecallAction,
  3. BrowseInteractiveAction,
  4. BrowseURLAction,
  5. CmdKillAction,
  6. CmdRunAction,
  7. FileReadAction,
  8. FileWriteAction,
  9. IPythonRunCellAction,
  10. )
  11. from opendevin.events.observation import (
  12. CmdOutputObservation,
  13. ErrorObservation,
  14. IPythonRunCellObservation,
  15. NullObservation,
  16. Observation,
  17. )
  18. from opendevin.runtime.runtime import Runtime
  19. from .browse import browse
  20. from .files import read_file, write_file
  21. class ServerRuntime(Runtime):
  22. async def run(self, action: CmdRunAction) -> Observation:
  23. return self._run_command(action.command, background=action.background)
  24. async def kill(self, action: CmdKillAction) -> Observation:
  25. cmd = self.sandbox.kill_background(action.command_id)
  26. return CmdOutputObservation(
  27. content=f'Background command with id {action.command_id} has been killed.',
  28. command_id=action.command_id,
  29. command=cmd.command,
  30. exit_code=0,
  31. )
  32. async def run_ipython(self, action: IPythonRunCellAction) -> Observation:
  33. obs = self._run_command(
  34. ('cat > /tmp/opendevin_jupyter_temp.py <<EOL\n' f'{action.code}\n' 'EOL'),
  35. background=False,
  36. )
  37. # run the code
  38. obs = self._run_command(
  39. ('cat /tmp/opendevin_jupyter_temp.py | execute_cli'), background=False
  40. )
  41. return IPythonRunCellObservation(content=obs.content, code=action.code)
  42. async def read(self, action: FileReadAction) -> Observation:
  43. working_dir = self.sandbox.get_working_directory()
  44. return await read_file(action.path, working_dir, action.start, action.end)
  45. async def write(self, action: FileWriteAction) -> Observation:
  46. working_dir = self.sandbox.get_working_directory()
  47. return await write_file(
  48. action.path, working_dir, action.content, action.start, action.end
  49. )
  50. async def browse(self, action: BrowseURLAction) -> Observation:
  51. return await browse(action, self.browser)
  52. async def browse_interactive(self, action: BrowseInteractiveAction) -> Observation:
  53. return await browse(action, self.browser)
  54. async def recall(self, action: AgentRecallAction) -> Observation:
  55. return NullObservation('')
  56. def _run_command(self, command: str, background=False) -> Observation:
  57. if background:
  58. return self._run_background(command)
  59. else:
  60. return self._run_immediately(command)
  61. def _run_immediately(self, command: str) -> Observation:
  62. try:
  63. exit_code, output = self.sandbox.execute(command)
  64. return CmdOutputObservation(
  65. command_id=-1, content=output, command=command, exit_code=exit_code
  66. )
  67. except UnicodeDecodeError:
  68. return ErrorObservation('Command output could not be decoded as utf-8')
  69. def _run_background(self, command: str) -> Observation:
  70. bg_cmd = self.sandbox.execute_in_background(command)
  71. content = f'Background command started. To stop it, send a `kill` action with command_id {bg_cmd.pid}'
  72. return CmdOutputObservation(
  73. content=content,
  74. command_id=bg_cmd.pid,
  75. command=command,
  76. exit_code=0,
  77. )