mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com> Co-authored-by: Engel Nyst <engel.nyst@gmail.com>
79 lines
2.9 KiB
Python
79 lines
2.9 KiB
Python
from typing import Callable
|
|
|
|
from openhands.core.config import OpenHandsConfig
|
|
from openhands.events.action import (
|
|
FileReadAction,
|
|
FileWriteAction,
|
|
)
|
|
from openhands.events.observation import (
|
|
ErrorObservation,
|
|
FileReadObservation,
|
|
FileWriteObservation,
|
|
Observation,
|
|
)
|
|
from openhands.events.stream import EventStream
|
|
from openhands.integrations.provider import PROVIDER_TOKEN_TYPE
|
|
from openhands.runtime.impl.action_execution.action_execution_client import (
|
|
ActionExecutionClient,
|
|
)
|
|
from third_party.runtime.impl.e2b.filestore import E2BFileStore
|
|
from third_party.runtime.impl.e2b.sandbox import E2BSandbox
|
|
from openhands.runtime.plugins import PluginRequirement
|
|
from openhands.runtime.utils.files import insert_lines, read_lines
|
|
|
|
|
|
class E2BRuntime(ActionExecutionClient):
|
|
def __init__(
|
|
self,
|
|
config: OpenHandsConfig,
|
|
event_stream: EventStream,
|
|
sid: str = 'default',
|
|
plugins: list[PluginRequirement] | None = None,
|
|
env_vars: dict[str, str] | None = None,
|
|
status_callback: Callable | None = None,
|
|
attach_to_existing: bool = False,
|
|
headless_mode: bool = True,
|
|
user_id: str | None = None,
|
|
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = None,
|
|
sandbox: E2BSandbox | None = None,
|
|
):
|
|
super().__init__(
|
|
config,
|
|
event_stream,
|
|
sid,
|
|
plugins,
|
|
env_vars,
|
|
status_callback,
|
|
attach_to_existing,
|
|
headless_mode,
|
|
user_id,
|
|
git_provider_tokens,
|
|
)
|
|
if sandbox is None:
|
|
self.sandbox = E2BSandbox(config.sandbox)
|
|
if not isinstance(self.sandbox, E2BSandbox):
|
|
raise ValueError('E2BRuntime requires an E2BSandbox')
|
|
self.file_store = E2BFileStore(self.sandbox.filesystem)
|
|
|
|
def read(self, action: FileReadAction) -> Observation:
|
|
content = self.file_store.read(action.path)
|
|
lines = read_lines(content.split('\n'), action.start, action.end)
|
|
code_view = ''.join(lines)
|
|
return FileReadObservation(code_view, path=action.path)
|
|
|
|
def write(self, action: FileWriteAction) -> Observation:
|
|
if action.start == 0 and action.end == -1:
|
|
self.file_store.write(action.path, action.content)
|
|
return FileWriteObservation(content='', path=action.path)
|
|
files = self.file_store.list(action.path)
|
|
if action.path in files:
|
|
all_lines = self.file_store.read(action.path).split('\n')
|
|
new_file = insert_lines(
|
|
action.content.split('\n'), all_lines, action.start, action.end
|
|
)
|
|
self.file_store.write(action.path, ''.join(new_file))
|
|
return FileWriteObservation('', path=action.path)
|
|
else:
|
|
# FIXME: we should create a new file here
|
|
return ErrorObservation(f'File not found: {action.path}')
|