Skip to content

Commit

Permalink
feat: Add LocalRuntime (#5284)
Browse files Browse the repository at this point in the history
Co-authored-by: openhands <[email protected]>
Co-authored-by: Engel Nyst <[email protected]>
  • Loading branch information
3 people authored and chuckbutkus committed Feb 7, 2025
1 parent 30e1423 commit 0b908d3
Show file tree
Hide file tree
Showing 23 changed files with 661 additions and 145 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ghcr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ jobs:
run: pipx install poetry
- name: Install Python dependencies using Poetry
run: make install-python-dependencies
- name: Run runtime tests
- name: Run docker runtime tests
run: |
# We install pytest-xdist in order to run tests across CPUs
poetry run pip install pytest-xdist
Expand Down
18 changes: 18 additions & 0 deletions openhands/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,27 @@ Key features:
- Real-time logging and debugging capabilities
- Direct access to the local file system
- Faster execution due to local resources
- Container isolation for security

This is the default runtime used within OpenHands.

### Local Runtime

The Local Runtime is designed for direct execution on the local machine. Currently only supports running as the local user:

- Runs the action_execution_server directly on the host
- No Docker container overhead
- Direct access to local system resources
- Ideal for development and testing when Docker is not available or desired

Key features:
- Minimal setup required
- Direct access to local resources
- No container overhead
- Fastest execution speed

**Important: This runtime provides no isolation as it runs directly on the host machine. All actions are executed with the same permissions as the user running OpenHands. For secure execution with proper isolation, use the Docker Runtime instead.**

### Remote Runtime

The Remote Runtime is designed for execution in a remote environment:
Expand Down
3 changes: 3 additions & 0 deletions openhands/runtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
DockerRuntime,
)
from openhands.runtime.impl.e2b.sandbox import E2BBox
from openhands.runtime.impl.local.local_runtime import LocalRuntime
from openhands.runtime.impl.modal.modal_runtime import ModalRuntime
from openhands.runtime.impl.remote.remote_runtime import RemoteRuntime
from openhands.runtime.impl.runloop.runloop_runtime import RunloopRuntime
Expand All @@ -21,6 +22,8 @@ def get_runtime_cls(name: str):
return ModalRuntime
elif name == 'runloop':
return RunloopRuntime
elif name == 'local':
return LocalRuntime
else:
raise ValueError(f'Runtime {name} not supported')

Expand Down
9 changes: 5 additions & 4 deletions openhands/runtime/action_execution_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ class ActionRequest(BaseModel):


ROOT_GID = 0
INIT_COMMANDS = [
'git config --global user.name "openhands" && git config --global user.email "[email protected]" && alias git="git --no-pager"',
]

SESSION_API_KEY = os.environ.get('SESSION_API_KEY')
api_key_header = APIKeyHeader(name='X-Session-API-Key', auto_error=False)
Expand Down Expand Up @@ -163,6 +160,11 @@ async def _init_plugin(self, plugin: Plugin):
)

async def _init_bash_commands(self):
INIT_COMMANDS = [
'git config --file ./.git_config user.name "openhands" && git config --file ./.git_config user.email "[email protected]" && alias git="git --no-pager" && export GIT_CONFIG=$(pwd)/.git_config'
if os.environ.get('LOCAL_RUNTIME_MODE') == '1'
else 'git config --global user.name "openhands" && git config --global user.email "[email protected]" && alias git="git --no-pager"'
]
logger.debug(f'Initializing by running {len(INIT_COMMANDS)} bash commands...')
for command in INIT_COMMANDS:
action = CmdRunAction(command=command)
Expand All @@ -174,7 +176,6 @@ async def _init_bash_commands(self):
f'Init command outputs (exit code: {obs.exit_code}): {obs.content}'
)
assert obs.exit_code == 0

logger.debug('Bash init commands completed')

async def run_action(self, action) -> Observation:
Expand Down
Loading

0 comments on commit 0b908d3

Please sign in to comment.