mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
feat: show exact python interpreter to the agent in IPython and Bash (#3448)
* try to fix pip unavailable * update test case for pip * force rebuild in CI * remove extra symlink * fix newline * added semi-colon to line 31 * Dockerfile.j2: activate env at the end * Revert "Dockerfile.j2: activate env at the end" This reverts commit cf2f5651021fe80d4ab69a35a85f0a35b29dc3d7. * cleanup Dockerfile * switch default python image * remove image agnostic (no longer used) * fix tests * simplify integration tests default image * add nodejs specific runtime tests * update tests and workflows * switch to nikolaik/python-nodejs:python3.11-nodejs22 * update build sh to output image name correctly * increase custom images to test * fix test * fix test * fix double quote * try fixing ci * update ghcr workflow * fix artifact name * try to fix ghcr again * fix workflow * save built image to correct dir * remove extra -docker-image * make last tag to be human readable image tag * fix hyphen to underscore * run test runtime on all tags * revert app build * separate ghcr workflow * update dockerfile for eval * fix tag for test run * try fix tag * try fix tag via matrix output * try workflow again * update comments * try fixing test matrix * fix artifact name * try fix tag again * Revert "try fix tag again" This reverts commit b369badd8cccf4a526e36d27eafb77ea2d32f6be. * tweak filename * try different path * fix filepath * try fix tag artifact path again * save json instead of line * update matrix * print all tags in workflow * support only streaming diff logs from the runtime client * remove strip from log line to fix indentation * get py interpreter for jupyter * rstrip to remove newline on the rightside for logging * fix blocking issue for stream logs * set python interpreter path in bash ps1 * update testcase for jupyter py interpreter path * remove accidentally added changes * remove accidentally added changes * only print dockerfile when debug * add docs * remove extra tests that weren't supposed to be in this pr * add back missing test * revert * make LogBuffer synchronous to fix hang in integration tests * fix integration tests * Update opendevin/runtime/client/client.py Co-authored-by: Engel Nyst <enyst@users.noreply.github.com> * fix test case * fix integration tests * change deque to list * update integration tests * rename test runtime * fix docs * rename opendevin to openhands in tests --------- Co-authored-by: tobitege <tobitege@gmx.de> Co-authored-by: Graham Neubig <neubig@gmail.com> Co-authored-by: tobitege <10787084+tobitege@users.noreply.github.com> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
This commit is contained in:
parent
54546b1e29
commit
b19b724eae
@ -174,12 +174,15 @@ class RuntimeClient:
|
||||
encoding='utf-8',
|
||||
echo=False,
|
||||
)
|
||||
self.__bash_PS1 = r'[PEXPECT_BEGIN] \u@\h:\w [PEXPECT_END]'
|
||||
self.__bash_PS1 = (
|
||||
r'[PEXPECT_BEGIN]\n'
|
||||
r'$(which python >/dev/null 2>&1 && echo "[Python Interpreter: $(which python)]\n")'
|
||||
r'\u@\h:\w\n'
|
||||
r'[PEXPECT_END]'
|
||||
)
|
||||
|
||||
# This should NOT match "PS1=\u@\h:\w [PEXPECT]$" when `env` is executed
|
||||
self.__bash_expect_regex = (
|
||||
r'\[PEXPECT_BEGIN\] ([a-z0-9_-]*)@([a-zA-Z0-9.-]*):(.+) \[PEXPECT_END\]'
|
||||
)
|
||||
self.__bash_expect_regex = r'\[PEXPECT_BEGIN\]\s*(.*?)\s*([a-z0-9_-]*)@([a-zA-Z0-9.-]*):(.+)\s*\[PEXPECT_END\]'
|
||||
|
||||
self.shell.sendline(f'export PS1="{self.__bash_PS1}"; export PS2=""')
|
||||
self.shell.expect(self.__bash_expect_regex)
|
||||
@ -220,11 +223,12 @@ class RuntimeClient:
|
||||
assert (
|
||||
matched is not None
|
||||
), f'Failed to parse bash prompt: {ps1}. This should not happen.'
|
||||
username, hostname, working_dir = matched.groups()
|
||||
other_info, username, hostname, working_dir = matched.groups()
|
||||
working_dir = working_dir.rstrip()
|
||||
self.pwd = os.path.expanduser(working_dir)
|
||||
|
||||
# re-assemble the prompt
|
||||
prompt = f'{username}@{hostname}:{working_dir} '
|
||||
prompt = f'{other_info.strip()}\n{username}@{hostname}:{working_dir} '
|
||||
if username == 'root':
|
||||
prompt += '#'
|
||||
else:
|
||||
@ -273,7 +277,9 @@ class RuntimeClient:
|
||||
|
||||
async def run_action(self, action) -> Observation:
|
||||
action_type = action.action
|
||||
logger.debug(f'Running action: {action}')
|
||||
observation = await getattr(self, action_type)(action)
|
||||
logger.debug(f'Action output: {observation}')
|
||||
return observation
|
||||
|
||||
async def run(self, action: CmdRunAction) -> CmdOutputObservation:
|
||||
@ -327,6 +333,7 @@ class RuntimeClient:
|
||||
obs: IPythonRunCellObservation = await _jupyter_plugin.run(action)
|
||||
obs.content = obs.content.rstrip()
|
||||
obs.content += f'\n[Jupyter current working directory: {self.pwd}]'
|
||||
obs.content += f'\n[Jupyter Python interpreter: {_jupyter_plugin.python_interpreter_path}]'
|
||||
return obs
|
||||
else:
|
||||
raise RuntimeError(
|
||||
@ -472,6 +479,7 @@ if __name__ == '__main__':
|
||||
browsergym_eval_env=args.browsergym_eval_env,
|
||||
)
|
||||
await client.ainit()
|
||||
logger.info('Runtime client initialized.')
|
||||
yield
|
||||
# Clean up & release the resources
|
||||
client.close()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
import os
|
||||
import tempfile
|
||||
import threading
|
||||
import uuid
|
||||
from zipfile import ZipFile
|
||||
|
||||
@ -34,9 +35,65 @@ from openhands.runtime.utils import find_available_tcp_port
|
||||
from openhands.runtime.utils.runtime_build import build_runtime_image
|
||||
|
||||
|
||||
class LogBuffer:
|
||||
"""
|
||||
Synchronous buffer for Docker container logs.
|
||||
|
||||
This class provides a thread-safe way to collect, store, and retrieve logs
|
||||
from a Docker container. It uses a list to store log lines and provides methods
|
||||
for appending, retrieving, and clearing logs.
|
||||
"""
|
||||
|
||||
def __init__(self, container: docker.models.containers.Container):
|
||||
self.buffer: list[str] = []
|
||||
self.lock = threading.Lock()
|
||||
self.log_generator = container.logs(stream=True, follow=True)
|
||||
self.log_stream_thread = threading.Thread(target=self.stream_logs)
|
||||
self.log_stream_thread.daemon = True
|
||||
self.log_stream_thread.start()
|
||||
self._stop_event = threading.Event()
|
||||
|
||||
def append(self, log_line: str):
|
||||
with self.lock:
|
||||
self.buffer.append(log_line)
|
||||
|
||||
def get_and_clear(self) -> list[str]:
|
||||
with self.lock:
|
||||
logs = list(self.buffer)
|
||||
self.buffer.clear()
|
||||
return logs
|
||||
|
||||
def stream_logs(self):
|
||||
"""
|
||||
Stream logs from the Docker container in a separate thread.
|
||||
|
||||
This method runs in its own thread to handle the blocking
|
||||
operation of reading log lines from the Docker SDK's synchronous generator.
|
||||
"""
|
||||
try:
|
||||
for log_line in self.log_generator:
|
||||
if self._stop_event.is_set():
|
||||
break
|
||||
if log_line:
|
||||
self.append(log_line.decode('utf-8').rstrip())
|
||||
except Exception as e:
|
||||
logger.error(f'Error in stream_logs: {e}')
|
||||
|
||||
def __del__(self):
|
||||
if self.log_stream_thread.is_alive():
|
||||
logger.warn(
|
||||
"LogBuffer was not properly closed. Use 'log_buffer.close()' for clean shutdown."
|
||||
)
|
||||
self.close(timeout=5)
|
||||
|
||||
def close(self, timeout: float = 10.0):
|
||||
self._stop_event.set()
|
||||
self.log_stream_thread.join(timeout)
|
||||
|
||||
|
||||
class EventStreamRuntime(Runtime):
|
||||
"""This runtime will subscribe the event stream.
|
||||
When receive an event, it will send the event to od-runtime-client which run inside the docker environment.
|
||||
When receive an event, it will send the event to runtime-client which run inside the docker environment.
|
||||
"""
|
||||
|
||||
container_name_prefix = 'openhands-sandbox-'
|
||||
@ -74,6 +131,9 @@ class EventStreamRuntime(Runtime):
|
||||
self.runtime_builder = DockerRuntimeBuilder(self.docker_client)
|
||||
logger.debug(f'EventStreamRuntime `{sid}` config:\n{self.config}')
|
||||
|
||||
# Buffer for container logs
|
||||
self.log_buffer: LogBuffer | None = None
|
||||
|
||||
async def ainit(self, env_vars: dict[str, str] | None = None):
|
||||
if self.config.sandbox.runtime_extra_deps:
|
||||
logger.info(
|
||||
@ -174,6 +234,7 @@ class EventStreamRuntime(Runtime):
|
||||
environment={'DEBUG': 'true'} if self.config.debug else None,
|
||||
volumes=volumes,
|
||||
)
|
||||
self.log_buffer = LogBuffer(container)
|
||||
logger.info(f'Container started. Server url: {self.api_url}')
|
||||
return container
|
||||
except Exception as e:
|
||||
@ -193,20 +254,24 @@ class EventStreamRuntime(Runtime):
|
||||
)
|
||||
async def _wait_until_alive(self):
|
||||
logger.debug('Getting container logs...')
|
||||
container = self.docker_client.containers.get(self.container_name)
|
||||
# get logs
|
||||
_logs = container.logs(tail=10).decode('utf-8').split('\n')
|
||||
# add indent
|
||||
_logs = '\n'.join([f' |{log}' for log in _logs])
|
||||
logger.info(
|
||||
'\n'
|
||||
+ '-' * 30
|
||||
+ 'Container logs (last 10 lines):'
|
||||
+ '-' * 30
|
||||
+ f'\n{_logs}'
|
||||
+ '\n'
|
||||
+ '-' * 90
|
||||
)
|
||||
|
||||
# Print and clear the log buffer
|
||||
assert (
|
||||
self.log_buffer is not None
|
||||
), 'Log buffer is expected to be initialized when container is started'
|
||||
logs = self.log_buffer.get_and_clear()
|
||||
if logs:
|
||||
formatted_logs = '\n'.join([f' |{log}' for log in logs])
|
||||
logger.info(
|
||||
'\n'
|
||||
+ '-' * 30
|
||||
+ 'Container logs:'
|
||||
+ '-' * 30
|
||||
+ f'\n{formatted_logs}'
|
||||
+ '\n'
|
||||
+ '-' * 90
|
||||
)
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(f'{self.api_url}/alive') as response:
|
||||
if response.status == 200:
|
||||
@ -221,6 +286,9 @@ class EventStreamRuntime(Runtime):
|
||||
return self.config.workspace_mount_path_in_sandbox
|
||||
|
||||
async def close(self, close_client: bool = True):
|
||||
if self.log_buffer:
|
||||
self.log_buffer.close()
|
||||
|
||||
if self.session is not None and not self.session.closed:
|
||||
await self.session.close()
|
||||
|
||||
|
||||
@ -49,6 +49,10 @@ class JupyterPlugin(Plugin):
|
||||
logger.info(
|
||||
f'Jupyter kernel gateway started at port {self.kernel_gateway_port}. Output: {output}'
|
||||
)
|
||||
_obs = await self.run(
|
||||
IPythonRunCellAction(code='import sys; print(sys.executable)')
|
||||
)
|
||||
self.python_interpreter_path = _obs.content.strip()
|
||||
|
||||
async def _run(self, action: Action) -> IPythonRunCellObservation:
|
||||
"""Internal method to run a code cell in the jupyter kernel."""
|
||||
|
||||
@ -144,7 +144,7 @@ def prep_docker_build_folder(
|
||||
skip_init=skip_init,
|
||||
extra_deps=extra_deps,
|
||||
)
|
||||
logger.info(
|
||||
logger.debug(
|
||||
(
|
||||
f'===== Dockerfile content start =====\n'
|
||||
f'{dockerfile_content}\n'
|
||||
|
||||
@ -411,5 +411,6 @@ with open('/workspace/test.txt', 'w') as file:
|
||||
OBSERVATION:
|
||||
[Code executed successfully with no output]
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
ENVIRONMENT REMINDER: You have 13 turns left to complete the task. When finished reply with <finish></finish>.
|
||||
|
||||
@ -410,12 +410,12 @@ Sure! Let's start by installing the `pymsgbox` package.
|
||||
OBSERVATION:
|
||||
Collecting pymsgbox==1.0.9
|
||||
Downloading PyMsgBox-1.0.9.tar.gz (18 kB)
|
||||
Installing build dependencies ... [?25l- \ | / - \ done
|
||||
Installing build dependencies ... [?25l- \ | / - done
|
||||
[?25h Getting requirements to build wheel ... [?25l- done
|
||||
[?25h Preparing metadata (pyproject.toml) ... [?25l- done
|
||||
[?25hBuilding wheels for collected packages: pymsgbox
|
||||
Building wheel for pymsgbox (pyproject.toml) ... [?25l- done
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=aca10c2c34795d92bcf85b43c34a0f7eb39d1cf3a4edf8f69f65ed206619ae51
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=8561279053bc22a85928e69c2bb609aebc9c04526f2dbf420ed0b9c13f94131c
|
||||
Stored in directory: /home/openhands/.cache/pip/wheels/85/92/63/e126ee5f33d8f2ed04f96e43ef5df7270a2f331848752e8662
|
||||
Successfully built pymsgbox
|
||||
Installing collected packages: pymsgbox
|
||||
@ -425,5 +425,6 @@ Successfully installed pymsgbox-1.0.9
|
||||
[notice] To update, run: pip install --upgrade pip
|
||||
Note: you may need to restart the kernel to use updated packages.
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
ENVIRONMENT REMINDER: You have 13 turns left to complete the task. When finished reply with <finish></finish>.
|
||||
|
||||
@ -410,12 +410,12 @@ Sure! Let's start by installing the `pymsgbox` package.
|
||||
OBSERVATION:
|
||||
Collecting pymsgbox==1.0.9
|
||||
Downloading PyMsgBox-1.0.9.tar.gz (18 kB)
|
||||
Installing build dependencies ... [?25l- \ | / - \ done
|
||||
Installing build dependencies ... [?25l- \ | / - done
|
||||
[?25h Getting requirements to build wheel ... [?25l- done
|
||||
[?25h Preparing metadata (pyproject.toml) ... [?25l- done
|
||||
[?25hBuilding wheels for collected packages: pymsgbox
|
||||
Building wheel for pymsgbox (pyproject.toml) ... [?25l- done
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=aca10c2c34795d92bcf85b43c34a0f7eb39d1cf3a4edf8f69f65ed206619ae51
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=8561279053bc22a85928e69c2bb609aebc9c04526f2dbf420ed0b9c13f94131c
|
||||
Stored in directory: /home/openhands/.cache/pip/wheels/85/92/63/e126ee5f33d8f2ed04f96e43ef5df7270a2f331848752e8662
|
||||
Successfully built pymsgbox
|
||||
Installing collected packages: pymsgbox
|
||||
@ -425,6 +425,7 @@ Successfully installed pymsgbox-1.0.9
|
||||
[notice] To update, run: pip install --upgrade pip
|
||||
Note: you may need to restart the kernel to use updated packages.
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
----------
|
||||
|
||||
@ -443,5 +444,6 @@ with open('/workspace/test.txt', 'w') as file:
|
||||
OBSERVATION:
|
||||
[Code executed successfully with no output]
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
ENVIRONMENT REMINDER: You have 12 turns left to complete the task. When finished reply with <finish></finish>.
|
||||
|
||||
@ -410,12 +410,12 @@ Sure! Let's start by installing the `pymsgbox` package.
|
||||
OBSERVATION:
|
||||
Collecting pymsgbox==1.0.9
|
||||
Downloading PyMsgBox-1.0.9.tar.gz (18 kB)
|
||||
Installing build dependencies ... [?25l- \ | / - \ done
|
||||
Installing build dependencies ... [?25l- \ | / - done
|
||||
[?25h Getting requirements to build wheel ... [?25l- done
|
||||
[?25h Preparing metadata (pyproject.toml) ... [?25l- done
|
||||
[?25hBuilding wheels for collected packages: pymsgbox
|
||||
Building wheel for pymsgbox (pyproject.toml) ... [?25l- done
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=aca10c2c34795d92bcf85b43c34a0f7eb39d1cf3a4edf8f69f65ed206619ae51
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=8561279053bc22a85928e69c2bb609aebc9c04526f2dbf420ed0b9c13f94131c
|
||||
Stored in directory: /home/openhands/.cache/pip/wheels/85/92/63/e126ee5f33d8f2ed04f96e43ef5df7270a2f331848752e8662
|
||||
Successfully built pymsgbox
|
||||
Installing collected packages: pymsgbox
|
||||
@ -425,6 +425,7 @@ Successfully installed pymsgbox-1.0.9
|
||||
[notice] To update, run: pip install --upgrade pip
|
||||
Note: you may need to restart the kernel to use updated packages.
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
----------
|
||||
|
||||
@ -443,6 +444,7 @@ with open('/workspace/test.txt', 'w') as file:
|
||||
OBSERVATION:
|
||||
[Code executed successfully with no output]
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
----------
|
||||
|
||||
@ -456,6 +458,7 @@ cat /workspace/test.txt
|
||||
OBSERVATION:
|
||||
pymsgbox version: 1.0.9
|
||||
|
||||
[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
openhands@docker-desktop:/workspace $
|
||||
[Command -1 finished with exit code 0]
|
||||
|
||||
|
||||
@ -604,5 +604,6 @@ with open('/workspace/test.txt', 'w') as file:
|
||||
OBSERVATION:
|
||||
[Code executed successfully with no output]
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
ENVIRONMENT REMINDER: You have 13 turns left to complete the task. When finished reply with <finish></finish>.
|
||||
|
||||
@ -608,7 +608,7 @@ Collecting pymsgbox==1.0.9
|
||||
[?25h Preparing metadata (pyproject.toml) ... [?25l- done
|
||||
[?25hBuilding wheels for collected packages: pymsgbox
|
||||
Building wheel for pymsgbox (pyproject.toml) ... [?25l- done
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=65f1e9e680d728456ab0dc9e66affd01d7ade89ec5a2a8c3aa80ab24a71247ac
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=cd01971247caa14ba55cb76b476c8c2659d10c03ec9da34ba3a8bdb4bb626438
|
||||
Stored in directory: /home/openhands/.cache/pip/wheels/85/92/63/e126ee5f33d8f2ed04f96e43ef5df7270a2f331848752e8662
|
||||
Successfully built pymsgbox
|
||||
Installing collected packages: pymsgbox
|
||||
@ -618,5 +618,6 @@ Successfully installed pymsgbox-1.0.9
|
||||
[notice] To update, run: pip install --upgrade pip
|
||||
Note: you may need to restart the kernel to use updated packages.
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
ENVIRONMENT REMINDER: You have 13 turns left to complete the task. When finished reply with <finish></finish>.
|
||||
|
||||
@ -608,7 +608,7 @@ Collecting pymsgbox==1.0.9
|
||||
[?25h Preparing metadata (pyproject.toml) ... [?25l- done
|
||||
[?25hBuilding wheels for collected packages: pymsgbox
|
||||
Building wheel for pymsgbox (pyproject.toml) ... [?25l- done
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=65f1e9e680d728456ab0dc9e66affd01d7ade89ec5a2a8c3aa80ab24a71247ac
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=cd01971247caa14ba55cb76b476c8c2659d10c03ec9da34ba3a8bdb4bb626438
|
||||
Stored in directory: /home/openhands/.cache/pip/wheels/85/92/63/e126ee5f33d8f2ed04f96e43ef5df7270a2f331848752e8662
|
||||
Successfully built pymsgbox
|
||||
Installing collected packages: pymsgbox
|
||||
@ -618,6 +618,7 @@ Successfully installed pymsgbox-1.0.9
|
||||
[notice] To update, run: pip install --upgrade pip
|
||||
Note: you may need to restart the kernel to use updated packages.
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
----------
|
||||
|
||||
@ -638,5 +639,6 @@ version_info
|
||||
OBSERVATION:
|
||||
'1.0.9'
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
ENVIRONMENT REMINDER: You have 12 turns left to complete the task. When finished reply with <finish></finish>.
|
||||
|
||||
@ -608,7 +608,7 @@ Collecting pymsgbox==1.0.9
|
||||
[?25h Preparing metadata (pyproject.toml) ... [?25l- done
|
||||
[?25hBuilding wheels for collected packages: pymsgbox
|
||||
Building wheel for pymsgbox (pyproject.toml) ... [?25l- done
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=65f1e9e680d728456ab0dc9e66affd01d7ade89ec5a2a8c3aa80ab24a71247ac
|
||||
[?25h Created wheel for pymsgbox: filename=PyMsgBox-1.0.9-py3-none-any.whl size=7407 sha256=cd01971247caa14ba55cb76b476c8c2659d10c03ec9da34ba3a8bdb4bb626438
|
||||
Stored in directory: /home/openhands/.cache/pip/wheels/85/92/63/e126ee5f33d8f2ed04f96e43ef5df7270a2f331848752e8662
|
||||
Successfully built pymsgbox
|
||||
Installing collected packages: pymsgbox
|
||||
@ -618,6 +618,7 @@ Successfully installed pymsgbox-1.0.9
|
||||
[notice] To update, run: pip install --upgrade pip
|
||||
Note: you may need to restart the kernel to use updated packages.
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
----------
|
||||
|
||||
@ -638,6 +639,7 @@ version_info
|
||||
OBSERVATION:
|
||||
'1.0.9'
|
||||
[Jupyter current working directory: /workspace]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
|
||||
----------
|
||||
|
||||
@ -651,6 +653,7 @@ cat /workspace/test.txt
|
||||
OBSERVATION:
|
||||
pymsgbox version: 1.0.9
|
||||
|
||||
[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
openhands@docker-desktop:/workspace $
|
||||
[Command -1 finished with exit code 0]
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "run", "args": {"command": "ls", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "bad.txt\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "ls", "exit_code": 0}}]
|
||||
[{"source": "agent", "action": "run", "args": {"command": "ls", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "bad.txt\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "ls", "exit_code": 0}}]
|
||||
|
||||
## Format
|
||||
Your response MUST be in JSON format. It must be an object, and it must contain two fields:
|
||||
|
||||
@ -41,7 +41,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "run", "args": {"command": "ls", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "bad.txt\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "ls", "exit_code": 0}}, {"source": "agent", "action": "read", "args": {"path": "bad.txt", "start": 0, "end": -1, "thought": ""}}, {"source": "agent", "observation": "read", "content": "This is a stupid typoo.\nReally?\nNo mor typos!\nEnjoy!\n", "extras": {"path": "/workspace/bad.txt"}}]
|
||||
[{"source": "agent", "action": "run", "args": {"command": "ls", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "bad.txt\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "ls", "exit_code": 0}}, {"source": "agent", "action": "read", "args": {"path": "bad.txt", "start": 0, "end": -1, "thought": ""}}, {"source": "agent", "observation": "read", "content": "This is a stupid typoo.\nReally?\nNo mor typos!\nEnjoy!\n", "extras": {"path": "/workspace/bad.txt"}}]
|
||||
|
||||
## Format
|
||||
Your response MUST be in JSON format. It must be an object, and it must contain two fields:
|
||||
|
||||
@ -41,7 +41,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "run", "args": {"command": "ls", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "ls", "exit_code": 0}}]
|
||||
[{"source": "agent", "action": "run", "args": {"command": "ls", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "ls", "exit_code": 0}}]
|
||||
|
||||
## Format
|
||||
Your response MUST be in JSON format. It must be an object, and it must contain two fields:
|
||||
|
||||
@ -41,7 +41,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "write", "args": {"path": "hello.sh", "content": "#!/bin/bash\n\necho 'hello'", "start": 0, "end": -1, "thought": ""}}, {"source": "agent", "observation": "write", "content": "", "extras": {"path": "/workspace/hello.sh"}}, {"source": "agent", "action": "run", "args": {"command": "chmod +x hello.sh", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "chmod +x hello.sh", "exit_code": 0}}]
|
||||
[{"source": "agent", "action": "write", "args": {"path": "hello.sh", "content": "#!/bin/bash\n\necho 'hello'", "start": 0, "end": -1, "thought": ""}}, {"source": "agent", "observation": "write", "content": "", "extras": {"path": "/workspace/hello.sh"}}, {"source": "agent", "action": "run", "args": {"command": "chmod +x hello.sh", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "chmod +x hello.sh", "exit_code": 0}}]
|
||||
|
||||
## Format
|
||||
Your response MUST be in JSON format. It must be an object, and it must contain two fields:
|
||||
|
||||
@ -41,7 +41,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "write", "args": {"path": "hello.sh", "content": "#!/bin/bash\n\necho 'hello'", "start": 0, "end": -1, "thought": ""}}, {"source": "agent", "observation": "write", "content": "", "extras": {"path": "/workspace/hello.sh"}}, {"source": "agent", "action": "run", "args": {"command": "chmod +x hello.sh", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "chmod +x hello.sh", "exit_code": 0}}, {"source": "agent", "action": "run", "args": {"command": "./hello.sh", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "hello\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "./hello.sh", "exit_code": 0}}]
|
||||
[{"source": "agent", "action": "write", "args": {"path": "hello.sh", "content": "#!/bin/bash\n\necho 'hello'", "start": 0, "end": -1, "thought": ""}}, {"source": "agent", "observation": "write", "content": "", "extras": {"path": "/workspace/hello.sh"}}, {"source": "agent", "action": "run", "args": {"command": "chmod +x hello.sh", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "chmod +x hello.sh", "exit_code": 0}}, {"source": "agent", "action": "run", "args": {"command": "./hello.sh", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "hello\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "./hello.sh", "exit_code": 0}}]
|
||||
|
||||
## Format
|
||||
Your response MUST be in JSON format. It must be an object, and it must contain two fields:
|
||||
|
||||
@ -39,7 +39,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "read", "args": {"path": "hello.sh", "start": 0, "end": -1, "thought": ""}}, {"source": "agent", "observation": "read", "content": "#!/bin/bash\n\necho 'hello'\n", "extras": {"path": "/workspace/hello.sh"}}, {"source": "agent", "action": "run", "args": {"command": "bash hello.sh", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "hello\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "bash hello.sh", "exit_code": 0}}]
|
||||
[{"source": "agent", "action": "read", "args": {"path": "hello.sh", "start": 0, "end": -1, "thought": ""}}, {"source": "agent", "observation": "read", "content": "#!/bin/bash\n\necho 'hello'\n", "extras": {"path": "/workspace/hello.sh"}}, {"source": "agent", "action": "run", "args": {"command": "bash hello.sh", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "hello\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "bash hello.sh", "exit_code": 0}}]
|
||||
|
||||
## Format
|
||||
Your response MUST be in JSON format. It must be an object, and it must contain two fields:
|
||||
|
||||
@ -28,7 +28,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}]
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}]
|
||||
|
||||
If the last item in the history is an error, you should try to fix it.
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}]
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}]
|
||||
|
||||
If the last item in the history is an error, you should try to fix it.
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}]
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}]
|
||||
|
||||
If the last item in the history is an error, you should try to fix it.
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}]
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}]
|
||||
|
||||
If the last item in the history is an error, you should try to fix it.
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}]
|
||||
[{"source": "agent", "action": "run", "args": {"command": "git status", "thought": "", "keep_prompt": true, "is_confirmed": "confirmed"}}, {"source": "agent", "observation": "run", "content": "fatal: not a git repository (or any parent up to mount point /)\r\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ", "extras": {"command_id": -1, "command": "git status", "exit_code": 128}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}, {"source": "agent", "observation": "error", "content": "action={'action': 'reject', 'args': {'reason': 'Not a valid git repository.'}} has the wrong arguments", "extras": {}}]
|
||||
|
||||
If the last item in the history is an error, you should try to fix it.
|
||||
|
||||
|
||||
@ -205,7 +205,7 @@ ten actions--more happened before that.
|
||||
{
|
||||
"source": "agent",
|
||||
"observation": "run",
|
||||
"content": "hello\r\n\r\nopenhands@docker-desktop:/workspace $ ",
|
||||
"content": "hello\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ",
|
||||
"extras": {
|
||||
"command_id": -1,
|
||||
"command": "bash hello.sh",
|
||||
|
||||
@ -204,7 +204,7 @@ ten actions--more happened before that.
|
||||
{
|
||||
"source": "agent",
|
||||
"observation": "run",
|
||||
"content": "hello\r\n\r\nopenhands@docker-desktop:/workspace $ ",
|
||||
"content": "hello\r\n\r\n[Python Interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]\nopenhands@docker-desktop:/workspace $ ",
|
||||
"extras": {
|
||||
"command_id": -1,
|
||||
"command": "bash hello.sh",
|
||||
|
||||
@ -48,9 +48,10 @@ async def test_simple_cmd_ipython_and_fileop(temp_dir, box_class, run_as_openhan
|
||||
assert isinstance(obs, IPythonRunCellObservation)
|
||||
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert (
|
||||
obs.content.strip()
|
||||
== 'Hello, `World`!\n[Jupyter current working directory: /workspace]'
|
||||
assert obs.content.strip() == (
|
||||
'Hello, `World`!\n'
|
||||
'[Jupyter current working directory: /workspace]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
)
|
||||
|
||||
# Test read file (file should not exist)
|
||||
@ -122,7 +123,11 @@ async def test_ipython_multi_user(temp_dir, box_class, run_as_openhands):
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert (
|
||||
obs.content.strip()
|
||||
== '/workspace\n[Jupyter current working directory: /workspace]'
|
||||
== (
|
||||
'/workspace\n'
|
||||
'[Jupyter current working directory: /workspace]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
).strip()
|
||||
)
|
||||
|
||||
# write a file
|
||||
@ -134,7 +139,11 @@ async def test_ipython_multi_user(temp_dir, box_class, run_as_openhands):
|
||||
assert isinstance(obs, IPythonRunCellObservation)
|
||||
assert (
|
||||
obs.content.strip()
|
||||
== '[Code executed successfully with no output]\n[Jupyter current working directory: /workspace]'
|
||||
== (
|
||||
'[Code executed successfully with no output]\n'
|
||||
'[Jupyter current working directory: /workspace]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
).strip()
|
||||
)
|
||||
|
||||
# check file owner via bash
|
||||
@ -174,7 +183,14 @@ async def test_ipython_simple(temp_dir, box_class):
|
||||
obs = await runtime.run_action(action_ipython)
|
||||
assert isinstance(obs, IPythonRunCellObservation)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert obs.content.strip() == '1\n[Jupyter current working directory: /workspace]'
|
||||
assert (
|
||||
obs.content.strip()
|
||||
== (
|
||||
'1\n'
|
||||
'[Jupyter current working directory: /workspace]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
).strip()
|
||||
)
|
||||
|
||||
await runtime.close()
|
||||
await asyncio.sleep(1)
|
||||
@ -208,7 +224,8 @@ async def _test_ipython_agentskills_fileop_pwd_impl(
|
||||
'1|\n'
|
||||
'(this is the end of the file)\n'
|
||||
'[File hello.py created.]\n'
|
||||
'[Jupyter current working directory: /workspace]'
|
||||
'[Jupyter current working directory: /workspace]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
).strip().split('\n')
|
||||
|
||||
action = CmdRunAction(command='cd test')
|
||||
@ -231,7 +248,8 @@ async def _test_ipython_agentskills_fileop_pwd_impl(
|
||||
'1|\n'
|
||||
'(this is the end of the file)\n'
|
||||
'[File hello.py created.]\n'
|
||||
'[Jupyter current working directory: /workspace/test]'
|
||||
'[Jupyter current working directory: /workspace/test]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
).strip().split('\n')
|
||||
|
||||
if enable_auto_lint:
|
||||
@ -265,6 +283,7 @@ Your changes have NOT been applied. Please fix your edit command and try again.
|
||||
You either need to 1) Specify the correct start/end line arguments or 2) Correct your edit code.
|
||||
DO NOT re-run the same failed edit command. Running it again will lead to the same error.
|
||||
[Jupyter current working directory: /workspace/test]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
"""
|
||||
).strip().split('\n')
|
||||
|
||||
@ -284,6 +303,7 @@ DO NOT re-run the same failed edit command. Running it again will lead to the sa
|
||||
(this is the end of the file)
|
||||
[File updated (edited at line 1). Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary.]
|
||||
[Jupyter current working directory: /workspace/test]
|
||||
[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]
|
||||
"""
|
||||
).strip().split('\n')
|
||||
|
||||
@ -350,7 +370,8 @@ async def test_ipython_agentskills_fileop_pwd_with_userdir(temp_dir, box_class):
|
||||
'1|\n'
|
||||
'(this is the end of the file)\n'
|
||||
'[File hello.py created.]\n'
|
||||
'[Jupyter current working directory: /root]'
|
||||
'[Jupyter current working directory: /root]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
).strip().split('\n')
|
||||
|
||||
action = CmdRunAction(command='cd test')
|
||||
@ -373,7 +394,8 @@ async def test_ipython_agentskills_fileop_pwd_with_userdir(temp_dir, box_class):
|
||||
'1|\n'
|
||||
'(this is the end of the file)\n'
|
||||
'[File hello.py created.]\n'
|
||||
'[Jupyter current working directory: /root/test]'
|
||||
'[Jupyter current working directory: /root/test]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
).strip().split('\n')
|
||||
|
||||
await runtime.close()
|
||||
@ -407,9 +429,10 @@ async def test_ipython_package_install(temp_dir, box_class, run_as_openhands):
|
||||
obs = await runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
# import should not error out
|
||||
assert (
|
||||
obs.content.strip()
|
||||
== '[Code executed successfully with no output]\n[Jupyter current working directory: /workspace]'
|
||||
assert obs.content.strip() == (
|
||||
'[Code executed successfully with no output]\n'
|
||||
'[Jupyter current working directory: /workspace]\n'
|
||||
'[Jupyter Python interpreter: /openhands/poetry/openhands-5O4_aCHf-py3.11/bin/python]'
|
||||
)
|
||||
|
||||
await runtime.close()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user