mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Fixes to unblock frontend (#11488)
Co-authored-by: Ray Myers <ray.myers@gmail.com>
This commit is contained in:
parent
eb954164a5
commit
4b303ec9b4
2
.github/workflows/ghcr-build.yml
vendored
2
.github/workflows/ghcr-build.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
||||
else
|
||||
json=$(jq -n -c '[
|
||||
{ image: "nikolaik/python-nodejs:python3.12-nodejs22", tag: "nikolaik" },
|
||||
{ image: "ghcr.io/all-hands-ai/python-nodejs:python3.13-nodejs22-trixie", tag: "trixie" },
|
||||
{ image: "ghcr.io/openhands/python-nodejs:python3.13-nodejs22-trixie", tag: "trixie" },
|
||||
{ image: "ubuntu:24.04", tag: "ubuntu" }
|
||||
]')
|
||||
fi
|
||||
|
||||
@ -159,7 +159,7 @@ poetry run pytest ./tests/unit/test_*.py
|
||||
To reduce build time (e.g., if no changes were made to the client-runtime component), you can use an existing Docker
|
||||
container image by setting the SANDBOX_RUNTIME_CONTAINER_IMAGE environment variable to the desired Docker image.
|
||||
|
||||
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.59-nikolaik`
|
||||
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/openhands/runtime:0.59-nikolaik`
|
||||
|
||||
## Develop inside Docker container
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ services:
|
||||
- SANDBOX_API_HOSTNAME=host.docker.internal
|
||||
- DOCKER_HOST_ADDR=host.docker.internal
|
||||
#
|
||||
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.59-nikolaik}
|
||||
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/openhands/runtime:0.59-nikolaik}
|
||||
- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
|
||||
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
|
||||
ports:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
ARG OPENHANDS_VERSION=latest
|
||||
ARG BASE="ghcr.io/all-hands-ai/openhands"
|
||||
ARG BASE="ghcr.io/openhands/openhands"
|
||||
FROM ${BASE}:${OPENHANDS_VERSION}
|
||||
|
||||
# Datadog labels
|
||||
|
||||
@ -64,7 +64,7 @@ python enterprise_local/convert_to_env.py
|
||||
You'll also need to set up the runtime image, so that the dev server doesn't try to rebuild it.
|
||||
|
||||
```
|
||||
export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:main-nikolaik
|
||||
export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/openhands/runtime:main-nikolaik
|
||||
docker pull $SANDBOX_RUNTIME_CONTAINER_IMAGE
|
||||
```
|
||||
|
||||
@ -203,7 +203,7 @@ And then invoking `printenv`. NOTE: _DO NOT DO THIS WITH PROD!!!_ (Hopefully by
|
||||
"REDIS_HOST": "localhost:6379",
|
||||
"OPENHANDS": "<YOUR LOCAL OSS OPENHANDS DIR>",
|
||||
"FRONTEND_DIRECTORY": "<YOUR LOCAL OSS OPENHANDS DIR>/frontend/build",
|
||||
"SANDBOX_RUNTIME_CONTAINER_IMAGE": "ghcr.io/all-hands-ai/runtime:main-nikolaik",
|
||||
"SANDBOX_RUNTIME_CONTAINER_IMAGE": "ghcr.io/openhands/runtime:main-nikolaik",
|
||||
"FILE_STORE_PATH": "<YOUR HOME DIRECTORY>>/.openhands-state",
|
||||
"OPENHANDS_CONFIG_CLS": "server.config.SaaSServerConfig",
|
||||
"GITHUB_APP_ID": "1062351",
|
||||
@ -237,7 +237,7 @@ And then invoking `printenv`. NOTE: _DO NOT DO THIS WITH PROD!!!_ (Hopefully by
|
||||
"REDIS_HOST": "localhost:6379",
|
||||
"OPENHANDS": "<YOUR LOCAL OSS OPENHANDS DIR>",
|
||||
"FRONTEND_DIRECTORY": "<YOUR LOCAL OSS OPENHANDS DIR>/frontend/build",
|
||||
"SANDBOX_RUNTIME_CONTAINER_IMAGE": "ghcr.io/all-hands-ai/runtime:main-nikolaik",
|
||||
"SANDBOX_RUNTIME_CONTAINER_IMAGE": "ghcr.io/openhands/runtime:main-nikolaik",
|
||||
"FILE_STORE_PATH": "<YOUR HOME DIRECTORY>>/.openhands-state",
|
||||
"OPENHANDS_CONFIG_CLS": "server.config.SaaSServerConfig",
|
||||
"GITHUB_APP_ID": "1062351",
|
||||
|
||||
@ -12,7 +12,7 @@ git clone -b $OH_SWE_BENCH_REPO_BRANCH $OH_SWE_BENCH_REPO_PATH $EVAL_WORKSPACE/O
|
||||
|
||||
# 2. Prepare DATA
|
||||
echo "==== Prepare SWE-bench data ===="
|
||||
EVAL_IMAGE=ghcr.io/all-hands-ai/eval-swe-bench:builder_with_conda
|
||||
EVAL_IMAGE=ghcr.io/openhands/eval-swe-bench:builder_with_conda
|
||||
EVAL_WORKSPACE=$(realpath $EVAL_WORKSPACE)
|
||||
chmod +x $EVAL_WORKSPACE/OH-SWE-bench/swebench/harness/prepare_data.sh
|
||||
if [ -d $EVAL_WORKSPACE/eval_data ]; then
|
||||
|
||||
@ -12,7 +12,7 @@ git clone -b $OH_SWE_BENCH_REPO_BRANCH $OH_SWE_BENCH_REPO_PATH $EVAL_WORKSPACE/O
|
||||
|
||||
# 2. Prepare DATA
|
||||
echo "==== Prepare SWE-bench data ===="
|
||||
EVAL_IMAGE=ghcr.io/all-hands-ai/eval-swe-bench:builder_with_conda
|
||||
EVAL_IMAGE=ghcr.io/openhands/eval-swe-bench:builder_with_conda
|
||||
EVAL_WORKSPACE=$(realpath $EVAL_WORKSPACE)
|
||||
chmod +x $EVAL_WORKSPACE/OH-SWE-bench/swebench/harness/prepare_data.sh
|
||||
if [ -d $EVAL_WORKSPACE/eval_data ]; then
|
||||
|
||||
@ -12,7 +12,7 @@ git clone -b $OH_SWE_BENCH_REPO_BRANCH $OH_SWE_BENCH_REPO_PATH $EVAL_WORKSPACE/O
|
||||
|
||||
# 2. Prepare DATA
|
||||
echo "==== Prepare SWE-bench data ===="
|
||||
EVAL_IMAGE=ghcr.io/all-hands-ai/eval-swe-bench:builder_with_conda
|
||||
EVAL_IMAGE=ghcr.io/openhands/eval-swe-bench:builder_with_conda
|
||||
EVAL_WORKSPACE=$(realpath $EVAL_WORKSPACE)
|
||||
chmod +x $EVAL_WORKSPACE/OH-SWE-bench/swebench/harness/prepare_data.sh
|
||||
if [ -d $EVAL_WORKSPACE/eval_data ]; then
|
||||
|
||||
@ -162,7 +162,7 @@ while IFS= read -r task_image; do
|
||||
|
||||
# Prune unused images and volumes
|
||||
docker image rm "$task_image"
|
||||
docker images "ghcr.io/all-hands-ai/runtime" -q | xargs -r docker rmi -f
|
||||
docker images "ghcr.io/openhands/runtime" -q | xargs -r docker rmi -f
|
||||
docker volume prune -f
|
||||
docker system prune -f
|
||||
done < "$temp_file"
|
||||
|
||||
@ -88,7 +88,10 @@ class AppConversationService(ABC):
|
||||
|
||||
@abstractmethod
|
||||
async def run_setup_scripts(
|
||||
self, task: AppConversationStartTask, workspace: Workspace
|
||||
self,
|
||||
task: AppConversationStartTask,
|
||||
workspace: Workspace,
|
||||
working_dir: str,
|
||||
) -> AsyncGenerator[AppConversationStartTask, None]:
|
||||
"""Run the setup scripts for the project and yield status updates"""
|
||||
yield task
|
||||
|
||||
@ -36,23 +36,25 @@ class GitAppConversationService(AppConversationService, ABC):
|
||||
self,
|
||||
task: AppConversationStartTask,
|
||||
workspace: AsyncRemoteWorkspace,
|
||||
working_dir: str,
|
||||
) -> AsyncGenerator[AppConversationStartTask, None]:
|
||||
task.status = AppConversationStartTaskStatus.PREPARING_REPOSITORY
|
||||
yield task
|
||||
await self.clone_or_init_git_repo(task, workspace)
|
||||
await self.clone_or_init_git_repo(task, workspace, working_dir)
|
||||
|
||||
task.status = AppConversationStartTaskStatus.RUNNING_SETUP_SCRIPT
|
||||
yield task
|
||||
await self.maybe_run_setup_script(workspace)
|
||||
await self.maybe_run_setup_script(workspace, working_dir)
|
||||
|
||||
task.status = AppConversationStartTaskStatus.SETTING_UP_GIT_HOOKS
|
||||
yield task
|
||||
await self.maybe_setup_git_hooks(workspace)
|
||||
await self.maybe_setup_git_hooks(workspace, working_dir)
|
||||
|
||||
async def clone_or_init_git_repo(
|
||||
self,
|
||||
task: AppConversationStartTask,
|
||||
workspace: AsyncRemoteWorkspace,
|
||||
working_dir: str,
|
||||
):
|
||||
request = task.request
|
||||
|
||||
@ -61,7 +63,7 @@ class GitAppConversationService(AppConversationService, ABC):
|
||||
_logger.debug('Initializing a new git repository in the workspace.')
|
||||
await workspace.execute_command(
|
||||
'git init && git config --global --add safe.directory '
|
||||
+ workspace.working_dir
|
||||
+ working_dir
|
||||
)
|
||||
else:
|
||||
_logger.info('Not initializing a new git repository.')
|
||||
@ -77,7 +79,7 @@ class GitAppConversationService(AppConversationService, ABC):
|
||||
|
||||
# Clone the repo - this is the slow part!
|
||||
clone_command = f'git clone {remote_repo_url} {dir_name}'
|
||||
await workspace.execute_command(clone_command, workspace.working_dir)
|
||||
await workspace.execute_command(clone_command, working_dir)
|
||||
|
||||
# Checkout the appropriate branch
|
||||
if request.selected_branch:
|
||||
@ -87,14 +89,15 @@ class GitAppConversationService(AppConversationService, ABC):
|
||||
random_str = base62.encodebytes(os.urandom(16))
|
||||
openhands_workspace_branch = f'openhands-workspace-{random_str}'
|
||||
checkout_command = f'git checkout -b {openhands_workspace_branch}'
|
||||
await workspace.execute_command(checkout_command, workspace.working_dir)
|
||||
await workspace.execute_command(checkout_command, working_dir)
|
||||
|
||||
async def maybe_run_setup_script(
|
||||
self,
|
||||
workspace: AsyncRemoteWorkspace,
|
||||
working_dir: str,
|
||||
):
|
||||
"""Run .openhands/setup.sh if it exists in the workspace or repository."""
|
||||
setup_script = workspace.working_dir + '/.openhands/setup.sh'
|
||||
setup_script = working_dir + '/.openhands/setup.sh'
|
||||
|
||||
await workspace.execute_command(
|
||||
f'chmod +x {setup_script} && source {setup_script}', timeout=600
|
||||
@ -108,10 +111,11 @@ class GitAppConversationService(AppConversationService, ABC):
|
||||
async def maybe_setup_git_hooks(
|
||||
self,
|
||||
workspace: AsyncRemoteWorkspace,
|
||||
working_dir: str,
|
||||
):
|
||||
"""Set up git hooks if .openhands/pre-commit.sh exists in the workspace or repository."""
|
||||
command = 'mkdir -p .git/hooks && chmod +x .openhands/pre-commit.sh'
|
||||
result = await workspace.execute_command(command, workspace.working_dir)
|
||||
result = await workspace.execute_command(command, working_dir)
|
||||
if result.exit_code:
|
||||
return
|
||||
|
||||
@ -127,9 +131,7 @@ class GitAppConversationService(AppConversationService, ABC):
|
||||
f'mv {PRE_COMMIT_HOOK} {PRE_COMMIT_LOCAL} &&'
|
||||
f'chmod +x {PRE_COMMIT_LOCAL}'
|
||||
)
|
||||
result = await workspace.execute_command(
|
||||
command, workspace.working_dir
|
||||
)
|
||||
result = await workspace.execute_command(command, working_dir)
|
||||
if result.exit_code != 0:
|
||||
_logger.error(
|
||||
f'Failed to preserve existing pre-commit hook: {result.stderr}',
|
||||
|
||||
@ -181,11 +181,11 @@ class LiveStatusAppConversationService(GitAppConversationService):
|
||||
|
||||
# Run setup scripts
|
||||
workspace = AsyncRemoteWorkspace(
|
||||
working_dir=sandbox_spec.working_dir,
|
||||
server_url=agent_server_url,
|
||||
session_api_key=sandbox.session_api_key,
|
||||
host=agent_server_url, api_key=sandbox.session_api_key
|
||||
)
|
||||
async for updated_task in self.run_setup_scripts(task, workspace):
|
||||
async for updated_task in self.run_setup_scripts(
|
||||
task, workspace, sandbox_spec.working_dir
|
||||
):
|
||||
yield updated_task
|
||||
|
||||
# Build the start request
|
||||
|
||||
@ -90,7 +90,8 @@ class DockerSandboxService(SandboxService):
|
||||
status_mapping = {
|
||||
'running': SandboxStatus.RUNNING,
|
||||
'paused': SandboxStatus.PAUSED,
|
||||
'exited': SandboxStatus.MISSING,
|
||||
# The stop button was pressed in the docker console
|
||||
'exited': SandboxStatus.PAUSED,
|
||||
'created': SandboxStatus.STARTING,
|
||||
'restarting': SandboxStatus.STARTING,
|
||||
'removing': SandboxStatus.MISSING,
|
||||
|
||||
@ -222,7 +222,7 @@ class IssueResolver:
|
||||
and not is_experimental
|
||||
):
|
||||
runtime_container_image = (
|
||||
f'ghcr.io/all-hands-ai/runtime:{openhands.__version__}-nikolaik'
|
||||
f'ghcr.io/openhands/runtime:{openhands.__version__}-nikolaik'
|
||||
)
|
||||
|
||||
# Convert container image values to string or None
|
||||
|
||||
@ -25,7 +25,7 @@ class BuildFromImageType(Enum):
|
||||
|
||||
|
||||
def get_runtime_image_repo() -> str:
|
||||
return os.getenv('OH_RUNTIME_RUNTIME_IMAGE_REPO', 'ghcr.io/all-hands-ai/runtime')
|
||||
return os.getenv('OH_RUNTIME_RUNTIME_IMAGE_REPO', 'ghcr.io/openhands/runtime')
|
||||
|
||||
|
||||
def _generate_dockerfile(
|
||||
|
||||
@ -1139,25 +1139,29 @@ def _to_conversation_info(app_conversation: AppConversation) -> ConversationInfo
|
||||
app_conversation.sandbox_status, ConversationStatus.STOPPED
|
||||
)
|
||||
|
||||
runtime_status_mapping = {
|
||||
AgentExecutionStatus.ERROR: RuntimeStatus.ERROR,
|
||||
AgentExecutionStatus.IDLE: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.RUNNING: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.PAUSED: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.WAITING_FOR_CONFIRMATION: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.FINISHED: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.STUCK: RuntimeStatus.ERROR,
|
||||
}
|
||||
runtime_status = runtime_status_mapping.get(
|
||||
app_conversation.agent_status, RuntimeStatus.ERROR
|
||||
)
|
||||
if conversation_status == ConversationStatus.RUNNING:
|
||||
runtime_status_mapping = {
|
||||
AgentExecutionStatus.ERROR: RuntimeStatus.ERROR,
|
||||
AgentExecutionStatus.IDLE: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.RUNNING: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.PAUSED: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.WAITING_FOR_CONFIRMATION: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.FINISHED: RuntimeStatus.READY,
|
||||
AgentExecutionStatus.STUCK: RuntimeStatus.ERROR,
|
||||
}
|
||||
runtime_status = runtime_status_mapping.get(
|
||||
app_conversation.agent_status, RuntimeStatus.ERROR
|
||||
)
|
||||
else:
|
||||
runtime_status = None
|
||||
|
||||
title = (
|
||||
app_conversation.title
|
||||
or f'Conversation {base62.encodebytes(app_conversation.id.bytes)}'
|
||||
)
|
||||
|
||||
return ConversationInfo(
|
||||
conversation_id=str(app_conversation.id),
|
||||
conversation_id=app_conversation.id.hex,
|
||||
title=title,
|
||||
last_updated_at=app_conversation.updated_at,
|
||||
status=conversation_status,
|
||||
|
||||
@ -601,7 +601,7 @@ class TestDockerSandboxService:
|
||||
service._docker_status_to_sandbox_status('paused') == SandboxStatus.PAUSED
|
||||
)
|
||||
assert (
|
||||
service._docker_status_to_sandbox_status('exited') == SandboxStatus.MISSING
|
||||
service._docker_status_to_sandbox_status('exited') == SandboxStatus.PAUSED
|
||||
)
|
||||
assert (
|
||||
service._docker_status_to_sandbox_status('created')
|
||||
|
||||
@ -10,7 +10,7 @@ from openhands.resolver.issue_resolver import IssueResolver
|
||||
def assert_sandbox_config(
|
||||
config: SandboxConfig,
|
||||
base_container_image=SandboxConfig.model_fields['base_container_image'].default,
|
||||
runtime_container_image='ghcr.io/all-hands-ai/runtime:mock-nikolaik', # Default to mock version
|
||||
runtime_container_image='ghcr.io/openhands/runtime:mock-nikolaik', # Default to mock version
|
||||
local_runtime_url=SandboxConfig.model_fields['local_runtime_url'].default,
|
||||
enable_auto_lint=False,
|
||||
):
|
||||
@ -38,7 +38,7 @@ def test_setup_sandbox_config_default():
|
||||
|
||||
assert_sandbox_config(
|
||||
openhands_config.sandbox,
|
||||
runtime_container_image='ghcr.io/all-hands-ai/runtime:mock-nikolaik',
|
||||
runtime_container_image='ghcr.io/openhands/runtime:mock-nikolaik',
|
||||
)
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user