mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
* Some improvements to prompts, some better exception handling for various file IO errors, added timeout and max return token configurations for the LLM api. * More monologue prompt improvements * Dynamically set username provided in prompt. * Remove absolute paths from llm prompts, fetch working directory from sandbox when resolving paths in fileio operations, add customizable timeout for bash commands, mention said timeout in llm prompt. * Switched ssh_box to disabling tty echo and removed the logic attempting to delete it from the response afterwards, fixed get_working_directory for ssh_box. * Update prompts in integration tests to match monologue agent changes. * Minor tweaks to make merge easier. * Another minor prompt tweak, better invalid json handling. * Fix lint error * More catch-up to fix lint errors introduced by merge. * Force WORKSPACE_MOUNT_PATH_IN_SANDBOX to match WORKSPACE_MOUNT_PATH in local sandbox mode, combine exception handlers in prompts.py. --------- Co-authored-by: Jim Su <jimsu@protonmail.com> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
102 lines
3.5 KiB
Python
102 lines
3.5 KiB
Python
from typing import List
|
|
|
|
from opendevin import config
|
|
from opendevin.observation import CmdOutputObservation, AgentErrorObservation
|
|
from opendevin.sandbox import DockerExecBox, DockerSSHBox, Sandbox, LocalBox, E2BBox
|
|
from opendevin.schema import ConfigType
|
|
from opendevin.action import (
|
|
Action,
|
|
)
|
|
from opendevin.observation import (
|
|
Observation,
|
|
NullObservation,
|
|
)
|
|
from opendevin.sandbox.plugins import PluginRequirement
|
|
|
|
|
|
class ActionManager:
|
|
id: str
|
|
sandbox: Sandbox
|
|
|
|
def __init__(
|
|
self,
|
|
sid: str,
|
|
):
|
|
sandbox_type = config.get(ConfigType.SANDBOX_TYPE).lower()
|
|
if sandbox_type == 'exec':
|
|
self.sandbox = DockerExecBox(
|
|
sid=(sid or 'default'),
|
|
timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
|
|
)
|
|
elif sandbox_type == 'local':
|
|
self.sandbox = LocalBox(
|
|
timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
|
|
)
|
|
elif sandbox_type == 'ssh':
|
|
self.sandbox = DockerSSHBox(
|
|
sid=(sid or 'default'),
|
|
timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
|
|
)
|
|
elif sandbox_type == 'e2b':
|
|
self.sandbox = E2BBox(
|
|
timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
|
|
)
|
|
else:
|
|
raise ValueError(f'Invalid sandbox type: {sandbox_type}')
|
|
|
|
def init_sandbox_plugins(self, plugins: List[PluginRequirement]):
|
|
self.sandbox.init_plugins(plugins)
|
|
|
|
async def run_action(self, action: Action, agent_controller) -> Observation:
|
|
observation: Observation = NullObservation('')
|
|
if not action.executable:
|
|
return observation
|
|
observation = await action.run(agent_controller)
|
|
return observation
|
|
|
|
def run_command(self, command: str, background=False) -> Observation:
|
|
if background:
|
|
return self._run_background(command)
|
|
else:
|
|
return self._run_immediately(command)
|
|
|
|
def _run_immediately(self, command: str) -> Observation:
|
|
try:
|
|
exit_code, output = self.sandbox.execute(command)
|
|
return CmdOutputObservation(
|
|
command_id=-1, content=output, command=command, exit_code=exit_code
|
|
)
|
|
except UnicodeDecodeError:
|
|
return AgentErrorObservation('Command output could not be decoded as utf-8')
|
|
|
|
def _run_background(self, command: str) -> CmdOutputObservation:
|
|
bg_cmd = self.sandbox.execute_in_background(command)
|
|
content = f'Background command started. To stop it, send a `kill` action with id {bg_cmd.pid}'
|
|
return CmdOutputObservation(
|
|
content=content,
|
|
command_id=bg_cmd.pid,
|
|
command=command,
|
|
exit_code=0,
|
|
)
|
|
|
|
def kill_command(self, id: int) -> CmdOutputObservation:
|
|
cmd = self.sandbox.kill_background(id)
|
|
return CmdOutputObservation(
|
|
content=f'Background command with id {id} has been killed.',
|
|
command_id=id,
|
|
command=cmd.command,
|
|
exit_code=0,
|
|
)
|
|
|
|
def get_background_obs(self) -> List[CmdOutputObservation]:
|
|
obs = []
|
|
for _id, cmd in self.sandbox.background_commands.items():
|
|
output = cmd.read_logs()
|
|
if output is not None and output != '':
|
|
obs.append(
|
|
CmdOutputObservation(
|
|
content=output, command_id=_id, command=cmd.command
|
|
)
|
|
)
|
|
return obs
|