Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(fix) EventStreamRuntime: fix config passing on init (fixes test_runtime.py errors) #3233

Merged
merged 1 commit into from
Aug 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions opendevin/runtime/client/runtime.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import copy
import os
import tempfile
import uuid
Expand Down Expand Up @@ -49,6 +50,7 @@ def __init__(
plugins: list[PluginRequirement] | None = None,
container_image: str | None = None,
):
self.config = copy.deepcopy(config)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is actually done it is parent constructor super().__init__() if I'm not remembering wrong?

Copy link
Collaborator

@xingyaoww xingyaoww Aug 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nvm i think i got it? Very good catch!!

EventStreamRuntime config is output for each test, but Runtime config: only for the first test, thus retaining original values and the 2nd test is still run internally with opendevin instead of root and failing.

I just don't get where does the second run get the config from...

super().__init__(
config, event_stream, sid, plugins
) # will initialize the event stream
Expand Down Expand Up @@ -136,12 +138,15 @@ async def _init_container(

if mount_dir is not None:
volumes = {mount_dir: {'bind': sandbox_workspace_dir, 'mode': 'rw'}}
logger.info(f'Mount dir: {sandbox_workspace_dir}')
else:
logger.warn(
'Mount dir is not set, will not mount the workspace directory to the container.'
)
volumes = None

logger.info(f'run_as_devin: `{self.config.run_as_devin}`')

container = self.docker_client.containers.run(
self.container_image,
command=(
Expand Down Expand Up @@ -170,26 +175,25 @@ async def _init_container(
raise e

async def _ensure_session(self):
await asyncio.sleep(1)
if self.session is None or self.session.closed:
self.session = aiohttp.ClientSession()
return self.session

@tenacity.retry(
stop=tenacity.stop_after_attempt(10),
wait=tenacity.wait_exponential(multiplier=2, min=4, max=600),
wait=tenacity.wait_exponential(multiplier=2, min=4, max=60),
)
async def _wait_until_alive(self):
logger.info('Reconnecting session')
async with aiohttp.ClientSession() as session:
async with session.get(f'{self.api_url}/alive') as response:
if response.status == 200:
return
else:
logger.error(
f'Action execution API is not alive. Response: {response}'
)
raise RuntimeError(
f'Action execution API is not alive. Response: {response}'
)
msg = f'Action execution API is not alive. Response: {response}'
logger.error(msg)
raise RuntimeError(msg)

@property
def sandbox_workspace_dir(self):
Expand Down Expand Up @@ -278,12 +282,14 @@ async def run_action(self, action: Action) -> Observation:
f'Action {action_type} is not supported in the current runtime.'
)

logger.info('Awaiting session')
session = await self._ensure_session()
await self._wait_until_alive()

assert action.timeout is not None

try:
logger.info('Executing command')
async with session.post(
f'{self.api_url}/execute_action',
json={'action': event_to_dict(action)},
Expand Down