From c6b3847ad9f3a28951f47f2090d16418ff71c69b Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 25 Nov 2024 21:18:38 +0000 Subject: [PATCH 1/2] feat: tee command output to stdout/stderr in /execute_action endpoint --- openhands/runtime/action_execution_server.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openhands/runtime/action_execution_server.py b/openhands/runtime/action_execution_server.py index ba03613dde53..2dde9ccb3f3c 100644 --- a/openhands/runtime/action_execution_server.py +++ b/openhands/runtime/action_execution_server.py @@ -172,6 +172,8 @@ async def run( self, action: CmdRunAction ) -> CmdOutputObservation | ErrorObservation: obs = await call_sync_from_async(self.bash_session.run, action) + if isinstance(obs, CmdOutputObservation): + print(obs.content, flush=True) return obs async def run_ipython(self, action: IPythonRunCellAction) -> Observation: @@ -203,6 +205,7 @@ async def run_ipython(self, action: IPythonRunCellAction) -> Observation: f'\n[Jupyter current working directory: {self.bash_session.pwd}]' ) obs.content += f'\n[Jupyter Python interpreter: {_jupyter_plugin.python_interpreter_path}]' + print(obs.content, flush=True) return obs else: raise RuntimeError( From 0054ef74b46529c0be7d288b5ca99db7fc1661b8 Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 25 Nov 2024 21:24:04 +0000 Subject: [PATCH 2/2] feat: real-time output tee in bash execution --- openhands/runtime/utils/bash.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/openhands/runtime/utils/bash.py b/openhands/runtime/utils/bash.py index a5019315a038..dc2778c06732 100644 --- a/openhands/runtime/utils/bash.py +++ b/openhands/runtime/utils/bash.py @@ -251,10 +251,24 @@ def _continue_bash( kill_on_timeout: bool = True, ) -> tuple[str, int]: logger.debug(f'Continuing bash with timeout={timeout}') + output = '' try: - self.shell.expect(self.__bash_expect_regex, timeout=timeout) - - output = self.shell.before + # Instead of waiting for the full output, read character by character + while True: + try: + # Try to match the prompt pattern + index = self.shell.expect([self.__bash_expect_regex, '.'], timeout=0.1) + if index == 0: # Found the prompt pattern + break + elif index == 1: # Found a character + char = self.shell.after + output += char + print(char, end='', flush=True) # Print in real-time + except pexpect.TIMEOUT: + # No output available, continue waiting + continue + except pexpect.EOF: + break # Get exit code self.shell.sendline('echo $?')