Compare commits

...

2 Commits

Author SHA1 Message Date
openhands
0054ef74b4 feat: real-time output tee in bash execution 2024-11-25 21:24:04 +00:00
openhands
c6b3847ad9 feat: tee command output to stdout/stderr in /execute_action endpoint 2024-11-25 21:18:38 +00:00
2 changed files with 20 additions and 3 deletions

View File

@@ -172,6 +172,8 @@ class ActionExecutor:
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 @@ class ActionExecutor:
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(

View File

@@ -251,10 +251,24 @@ class BashSession:
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 $?')