Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexCuadron committed Oct 28, 2024
2 parents 4a7ef31 + a20da54 commit 32c69af
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 133 deletions.
6 changes: 4 additions & 2 deletions Development.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ Otherwise, you can clone the OpenHands project directly.

## Start the server for development
### 1. Requirements
* Linux, Mac OS, or [WSL on Windows](https://learn.microsoft.com/en-us/windows/wsl/install) [ Ubuntu <= 22.04]
* Linux, Mac OS, or [WSL on Windows](https://learn.microsoft.com/en-us/windows/wsl/install) [Ubuntu <= 22.04]
* [Docker](https://docs.docker.com/engine/install/) (For those on MacOS, make sure to allow the default Docker socket to be used from advanced settings!)
* [Python](https://www.python.org/downloads/) = 3.12
* [NodeJS](https://nodejs.org/en/download/package-manager) >= 18.17.1
* [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) >= 1.8
* netcat => sudo apt-get install netcat
* OS-specific dependencies:
- Ubuntu: build-essential => `sudo apt-get install build-essential`
- WSL: netcat => `sudo apt-get install netcat`

Make sure you have all these dependencies installed before moving on to `make build`.

Expand Down
19 changes: 11 additions & 8 deletions openhands/controller/agent_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,11 @@ async def _handle_observation(self, observation: Observation):
if self.state.agent_state == AgentState.ERROR:
self.state.metrics.merge(self.state.local_metrics)
elif isinstance(observation, FatalErrorObservation):
await self.report_error(
'There was a fatal error during agent execution: ' + str(observation)
self.state.last_error = (
f'There was a fatal error during agent execution: {str(observation)}'
)
await self.set_agent_state_to(AgentState.ERROR)
self.state.metrics.merge(self.state.local_metrics)
await self.set_agent_state_to(AgentState.ERROR)

async def _handle_message_action(self, action: MessageAction):
"""Handles message actions from the event stream.
Expand Down Expand Up @@ -406,6 +406,14 @@ async def _step(self) -> None:
await asyncio.sleep(1)
return

# check if agent got stuck before taking any action
if self._is_stuck():
# This need to go BEFORE report_error to sync metrics
self.event_stream.add_event(
FatalErrorObservation('Agent got stuck in a loop'), EventSource.USER
)
return

if self.delegate is not None:
assert self.delegate != self
if self.delegate.get_agent_state() == AgentState.PAUSED:
Expand Down Expand Up @@ -467,11 +475,6 @@ async def _step(self) -> None:
await self.update_state_after_step()
logger.info(action, extra={'msg_type': 'ACTION'})

if self._is_stuck():
# This need to go BEFORE report_error to sync metrics
await self.set_agent_state_to(AgentState.ERROR)
await self.report_error('Agent got stuck in a loop')

async def _delegate_step(self):
"""Executes a single step of the delegate agent."""
logger.debug(f'[Agent Controller {self.id}] Delegate not none, awaiting...')
Expand Down
20 changes: 7 additions & 13 deletions openhands/events/stream.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import threading
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from typing import Callable, Iterable
Expand Down Expand Up @@ -29,24 +30,17 @@ def session_exists(sid: str, file_store: FileStore) -> bool:
return False


@dataclass
class EventStream:
sid: str
file_store: FileStore
# For each subscriber ID, there is a stack of callback functions - useful
# when there are agent delegates
_subscribers: dict[str, list[Callable]]
_cur_id: int
_lock: threading.Lock

def __init__(self, sid: str, file_store: FileStore):
self.sid = sid
self.file_store = file_store
self._subscribers = {}
self._cur_id = 0
self._lock = threading.Lock()
self._reinitialize_from_file_store()
_subscribers: dict[str, list[Callable]] = field(default_factory=dict)
_cur_id: int = 0
_lock: threading.Lock = field(default_factory=threading.Lock)

def _reinitialize_from_file_store(self) -> None:
def __post_init__(self) -> None:
try:
events = self.file_store.list(f'sessions/{self.sid}/events')
except FileNotFoundError:
Expand Down Expand Up @@ -173,4 +167,4 @@ def clear(self):
self.file_store.delete(f'sessions/{self.sid}')
self._cur_id = 0
# self._subscribers = {}
self._reinitialize_from_file_store()
self.__post_init__()
4 changes: 2 additions & 2 deletions openhands/runtime/builder/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self, docker_client: docker.DockerClient):
self.docker_client = docker_client

version_info = self.docker_client.version()
server_version = version_info.get('Version', '')
server_version = version_info.get('Version', '').replace('-', '.')
if tuple(map(int, server_version.split('.'))) < (18, 9):
raise RuntimeError('Docker server version must be >= 18.09 to use BuildKit')

Expand Down Expand Up @@ -53,7 +53,7 @@ def build(
"""
self.docker_client = docker.from_env()
version_info = self.docker_client.version()
server_version = version_info.get('Version', '')
server_version = version_info.get('Version', '').replace('-', '.')
if tuple(map(int, server_version.split('.'))) < (18, 9):
raise RuntimeError('Docker server version must be >= 18.09 to use BuildKit')

Expand Down
Loading

0 comments on commit 32c69af

Please sign in to comment.