mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Remove third-party runtimes (daytona, modal, e2b, runloop) from main codebase (#9213)
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>
This commit is contained in:
parent
6efb992bae
commit
c7dff3e4d2
@ -10,18 +10,7 @@
|
|||||||
# General core configurations
|
# General core configurations
|
||||||
##############################################################################
|
##############################################################################
|
||||||
[core]
|
[core]
|
||||||
# API key for E2B
|
# API keys and configuration for core services
|
||||||
#e2b_api_key = ""
|
|
||||||
|
|
||||||
# API key for Modal
|
|
||||||
#modal_api_token_id = ""
|
|
||||||
#modal_api_token_secret = ""
|
|
||||||
|
|
||||||
# API key for Daytona
|
|
||||||
#daytona_api_key = ""
|
|
||||||
|
|
||||||
# Daytona Target
|
|
||||||
#daytona_target = ""
|
|
||||||
|
|
||||||
# Base path for the workspace
|
# Base path for the workspace
|
||||||
#workspace_base = "./workspace"
|
#workspace_base = "./workspace"
|
||||||
|
|||||||
@ -3,9 +3,9 @@ repos:
|
|||||||
rev: v5.0.0
|
rev: v5.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
exclude: ^(docs/|modules/|python/|openhands-ui/)
|
exclude: ^(docs/|modules/|python/|openhands-ui/|third_party/)
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
exclude: ^(docs/|modules/|python/|openhands-ui/)
|
exclude: ^(docs/|modules/|python/|openhands-ui/|third_party/)
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
args: ["--allow-multiple-documents"]
|
args: ["--allow-multiple-documents"]
|
||||||
- id: debug-statements
|
- id: debug-statements
|
||||||
@ -28,10 +28,12 @@ repos:
|
|||||||
entry: ruff check --config dev_config/python/ruff.toml
|
entry: ruff check --config dev_config/python/ruff.toml
|
||||||
types_or: [python, pyi, jupyter]
|
types_or: [python, pyi, jupyter]
|
||||||
args: [--fix, --unsafe-fixes]
|
args: [--fix, --unsafe-fixes]
|
||||||
|
exclude: third_party/
|
||||||
# Run the formatter.
|
# Run the formatter.
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
entry: ruff format --config dev_config/python/ruff.toml
|
entry: ruff format --config dev_config/python/ruff.toml
|
||||||
types_or: [python, pyi, jupyter]
|
types_or: [python, pyi, jupyter]
|
||||||
|
exclude: third_party/
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v1.15.0
|
rev: v1.15.0
|
||||||
|
|||||||
@ -7,3 +7,5 @@ warn_unreachable = True
|
|||||||
warn_redundant_casts = True
|
warn_redundant_casts = True
|
||||||
no_implicit_optional = True
|
no_implicit_optional = True
|
||||||
strict_optional = True
|
strict_optional = True
|
||||||
|
# Exclude third-party runtime directory from type checking
|
||||||
|
exclude = third_party/
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
# Exclude third-party runtime directory from linting
|
||||||
|
exclude = ["third_party/"]
|
||||||
|
|
||||||
[lint]
|
[lint]
|
||||||
select = [
|
select = [
|
||||||
"E",
|
"E",
|
||||||
|
|||||||
@ -12,22 +12,6 @@ description: This page outlines all available configuration options for OpenHand
|
|||||||
|
|
||||||
The core configuration options are defined in the `[core]` section of the `config.toml` file.
|
The core configuration options are defined in the `[core]` section of the `config.toml` file.
|
||||||
|
|
||||||
### API Keys
|
|
||||||
- `e2b_api_key`
|
|
||||||
- Type: `str`
|
|
||||||
- Default: `""`
|
|
||||||
- Description: API key for E2B
|
|
||||||
|
|
||||||
- `modal_api_token_id`
|
|
||||||
- Type: `str`
|
|
||||||
- Default: `""`
|
|
||||||
- Description: API token ID for Modal
|
|
||||||
|
|
||||||
- `modal_api_token_secret`
|
|
||||||
- Type: `str`
|
|
||||||
- Default: `""`
|
|
||||||
- Description: API token secret for Modal
|
|
||||||
|
|
||||||
### Workspace
|
### Workspace
|
||||||
- `workspace_base` **(Deprecated)**
|
- `workspace_base` **(Deprecated)**
|
||||||
- Type: `str`
|
- Type: `str`
|
||||||
|
|||||||
@ -9,8 +9,6 @@ commands.
|
|||||||
By default, OpenHands uses a [Docker-based runtime](/usage/runtimes/docker), running on your local computer.
|
By default, OpenHands uses a [Docker-based runtime](/usage/runtimes/docker), running on your local computer.
|
||||||
This means you only have to pay for the LLM you're using, and your code is only ever sent to the LLM.
|
This means you only have to pay for the LLM you're using, and your code is only ever sent to the LLM.
|
||||||
|
|
||||||
We also support other runtimes, which are typically managed by third-parties.
|
|
||||||
|
|
||||||
Additionally, we provide a [Local Runtime](/usage/runtimes/local) that runs directly on your machine without Docker,
|
Additionally, we provide a [Local Runtime](/usage/runtimes/local) that runs directly on your machine without Docker,
|
||||||
which can be useful in controlled environments like CI pipelines.
|
which can be useful in controlled environments like CI pipelines.
|
||||||
|
|
||||||
@ -21,6 +19,18 @@ OpenHands supports several different runtime environments:
|
|||||||
- [Docker Runtime](/usage/runtimes/docker) - The default runtime that uses Docker containers for isolation (recommended for most users).
|
- [Docker Runtime](/usage/runtimes/docker) - The default runtime that uses Docker containers for isolation (recommended for most users).
|
||||||
- [OpenHands Remote Runtime](/usage/runtimes/remote) - Cloud-based runtime for parallel execution (beta).
|
- [OpenHands Remote Runtime](/usage/runtimes/remote) - Cloud-based runtime for parallel execution (beta).
|
||||||
- [Local Runtime](/usage/runtimes/local) - Direct execution on your local machine without Docker.
|
- [Local Runtime](/usage/runtimes/local) - Direct execution on your local machine without Docker.
|
||||||
- And more third-party runtimes:
|
|
||||||
- [Modal Runtime](/usage/runtimes/modal) - Runtime provided by our partners at Modal.
|
### Third-Party Runtimes
|
||||||
- [Daytona Runtime](/usage/runtimes/daytona) - Runtime provided by Daytona.
|
|
||||||
|
The following third-party runtimes are available when you install the `third_party_runtimes` extra:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install openhands-ai[third_party_runtimes]
|
||||||
|
```
|
||||||
|
|
||||||
|
- [E2B Runtime](/usage/runtimes/e2b) - Open source runtime using E2B sandboxes.
|
||||||
|
- [Modal Runtime](/usage/runtimes/modal) - Serverless runtime using Modal infrastructure.
|
||||||
|
- [Runloop Runtime](/usage/runtimes/runloop) - Cloud runtime using Runloop infrastructure.
|
||||||
|
- [Daytona Runtime](/usage/runtimes/daytona) - Development environment runtime using Daytona.
|
||||||
|
|
||||||
|
**Note**: These third-party runtimes are supported by their respective developers, not by the OpenHands team. For issues specific to these runtimes, please refer to their documentation or contact their support teams.
|
||||||
|
|||||||
@ -46,7 +46,6 @@ class OpenHandsConfig(BaseModel):
|
|||||||
run_as_openhands: Whether to run as openhands.
|
run_as_openhands: Whether to run as openhands.
|
||||||
max_iterations: Maximum number of iterations allowed.
|
max_iterations: Maximum number of iterations allowed.
|
||||||
max_budget_per_task: Maximum budget per task, agent stops if exceeded.
|
max_budget_per_task: Maximum budget per task, agent stops if exceeded.
|
||||||
e2b_api_key: E2B API key.
|
|
||||||
disable_color: Whether to disable terminal colors. For terminals that don't support color.
|
disable_color: Whether to disable terminal colors. For terminals that don't support color.
|
||||||
debug: Whether to enable debugging mode.
|
debug: Whether to enable debugging mode.
|
||||||
file_uploads_max_file_size_mb: Maximum file upload size in MB. `0` means unlimited.
|
file_uploads_max_file_size_mb: Maximum file upload size in MB. `0` means unlimited.
|
||||||
@ -88,19 +87,14 @@ class OpenHandsConfig(BaseModel):
|
|||||||
run_as_openhands: bool = Field(default=True)
|
run_as_openhands: bool = Field(default=True)
|
||||||
max_iterations: int = Field(default=OH_MAX_ITERATIONS)
|
max_iterations: int = Field(default=OH_MAX_ITERATIONS)
|
||||||
max_budget_per_task: float | None = Field(default=None)
|
max_budget_per_task: float | None = Field(default=None)
|
||||||
e2b_api_key: SecretStr | None = Field(default=None)
|
|
||||||
modal_api_token_id: SecretStr | None = Field(default=None)
|
|
||||||
modal_api_token_secret: SecretStr | None = Field(default=None)
|
|
||||||
disable_color: bool = Field(default=False)
|
disable_color: bool = Field(default=False)
|
||||||
jwt_secret: SecretStr | None = Field(default=None)
|
jwt_secret: SecretStr | None = Field(default=None)
|
||||||
debug: bool = Field(default=False)
|
debug: bool = Field(default=False)
|
||||||
file_uploads_max_file_size_mb: int = Field(default=0)
|
file_uploads_max_file_size_mb: int = Field(default=0)
|
||||||
file_uploads_restrict_file_types: bool = Field(default=False)
|
file_uploads_restrict_file_types: bool = Field(default=False)
|
||||||
file_uploads_allowed_extensions: list[str] = Field(default_factory=lambda: ['.*'])
|
file_uploads_allowed_extensions: list[str] = Field(default_factory=lambda: ['.*'])
|
||||||
runloop_api_key: SecretStr | None = Field(default=None)
|
|
||||||
daytona_api_key: SecretStr | None = Field(default=None)
|
|
||||||
daytona_api_url: str = Field(default='https://app.daytona.io/api')
|
|
||||||
daytona_target: str = Field(default='eu')
|
|
||||||
cli_multiline_input: bool = Field(default=False)
|
cli_multiline_input: bool = Field(default=False)
|
||||||
conversation_max_age_seconds: int = Field(default=864000) # 10 days in seconds
|
conversation_max_age_seconds: int = Field(default=864000) # 10 days in seconds
|
||||||
enable_default_condenser: bool = Field(default=True)
|
enable_default_condenser: bool = Field(default=True)
|
||||||
|
|||||||
@ -261,6 +261,7 @@ class SensitiveDataFilter(logging.Filter):
|
|||||||
'modal_api_token_secret',
|
'modal_api_token_secret',
|
||||||
'llm_api_key',
|
'llm_api_key',
|
||||||
'sandbox_env_github_token',
|
'sandbox_env_github_token',
|
||||||
|
'runloop_api_key',
|
||||||
'daytona_api_key',
|
'daytona_api_key',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -1,31 +1,84 @@
|
|||||||
|
import importlib
|
||||||
|
|
||||||
from openhands.runtime.base import Runtime
|
from openhands.runtime.base import Runtime
|
||||||
from openhands.runtime.impl.cli.cli_runtime import CLIRuntime
|
from openhands.runtime.impl.cli.cli_runtime import CLIRuntime
|
||||||
from openhands.runtime.impl.daytona.daytona_runtime import DaytonaRuntime
|
|
||||||
from openhands.runtime.impl.docker.docker_runtime import (
|
from openhands.runtime.impl.docker.docker_runtime import (
|
||||||
DockerRuntime,
|
DockerRuntime,
|
||||||
)
|
)
|
||||||
from openhands.runtime.impl.e2b.e2b_runtime import E2BRuntime
|
|
||||||
from openhands.runtime.impl.kubernetes.kubernetes_runtime import KubernetesRuntime
|
from openhands.runtime.impl.kubernetes.kubernetes_runtime import KubernetesRuntime
|
||||||
from openhands.runtime.impl.local.local_runtime import LocalRuntime
|
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.remote.remote_runtime import RemoteRuntime
|
||||||
from openhands.runtime.impl.runloop.runloop_runtime import RunloopRuntime
|
|
||||||
from openhands.utils.import_utils import get_impl
|
from openhands.utils.import_utils import get_impl
|
||||||
|
|
||||||
# mypy: disable-error-code="type-abstract"
|
# mypy: disable-error-code="type-abstract"
|
||||||
_DEFAULT_RUNTIME_CLASSES: dict[str, type[Runtime]] = {
|
_DEFAULT_RUNTIME_CLASSES: dict[str, type[Runtime]] = {
|
||||||
'eventstream': DockerRuntime,
|
'eventstream': DockerRuntime,
|
||||||
'docker': DockerRuntime,
|
'docker': DockerRuntime,
|
||||||
'e2b': E2BRuntime,
|
|
||||||
'remote': RemoteRuntime,
|
'remote': RemoteRuntime,
|
||||||
'modal': ModalRuntime,
|
|
||||||
'runloop': RunloopRuntime,
|
|
||||||
'local': LocalRuntime,
|
'local': LocalRuntime,
|
||||||
'daytona': DaytonaRuntime,
|
|
||||||
'kubernetes': KubernetesRuntime,
|
'kubernetes': KubernetesRuntime,
|
||||||
'cli': CLIRuntime,
|
'cli': CLIRuntime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Try to import third-party runtimes if available
|
||||||
|
_THIRD_PARTY_RUNTIME_CLASSES: dict[str, type[Runtime]] = {}
|
||||||
|
|
||||||
|
# Dynamically discover and import third-party runtimes
|
||||||
|
|
||||||
|
# Check if third_party package exists and discover runtimes
|
||||||
|
try:
|
||||||
|
import third_party.runtime.impl
|
||||||
|
|
||||||
|
third_party_base = 'third_party.runtime.impl'
|
||||||
|
|
||||||
|
# List of potential third-party runtime modules to try
|
||||||
|
# These are discovered from the third_party directory structure
|
||||||
|
potential_runtimes = []
|
||||||
|
try:
|
||||||
|
import pkgutil
|
||||||
|
|
||||||
|
for importer, modname, ispkg in pkgutil.iter_modules(
|
||||||
|
third_party.runtime.impl.__path__
|
||||||
|
):
|
||||||
|
if ispkg:
|
||||||
|
potential_runtimes.append(modname)
|
||||||
|
except Exception:
|
||||||
|
# If discovery fails, no third-party runtimes will be loaded
|
||||||
|
potential_runtimes = []
|
||||||
|
|
||||||
|
# Try to import each discovered runtime
|
||||||
|
for runtime_name in potential_runtimes:
|
||||||
|
try:
|
||||||
|
module_path = f'{third_party_base}.{runtime_name}.{runtime_name}_runtime'
|
||||||
|
module = importlib.import_module(module_path)
|
||||||
|
|
||||||
|
# Try different class name patterns
|
||||||
|
possible_class_names = [
|
||||||
|
f'{runtime_name.upper()}Runtime', # E2BRuntime
|
||||||
|
f'{runtime_name.capitalize()}Runtime', # E2bRuntime, DaytonaRuntime, etc.
|
||||||
|
]
|
||||||
|
|
||||||
|
runtime_class = None
|
||||||
|
for class_name in possible_class_names:
|
||||||
|
try:
|
||||||
|
runtime_class = getattr(module, class_name)
|
||||||
|
break
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if runtime_class:
|
||||||
|
_THIRD_PARTY_RUNTIME_CLASSES[runtime_name] = runtime_class
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# third_party package not available
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Combine core and third-party runtimes
|
||||||
|
_ALL_RUNTIME_CLASSES = {**_DEFAULT_RUNTIME_CLASSES, **_THIRD_PARTY_RUNTIME_CLASSES}
|
||||||
|
|
||||||
|
|
||||||
def get_runtime_cls(name: str) -> type[Runtime]:
|
def get_runtime_cls(name: str) -> type[Runtime]:
|
||||||
"""
|
"""
|
||||||
@ -33,26 +86,28 @@ def get_runtime_cls(name: str) -> type[Runtime]:
|
|||||||
Otherwise attempt to resolve name as subclass of Runtime and return it.
|
Otherwise attempt to resolve name as subclass of Runtime and return it.
|
||||||
Raise on invalid selections.
|
Raise on invalid selections.
|
||||||
"""
|
"""
|
||||||
if name in _DEFAULT_RUNTIME_CLASSES:
|
if name in _ALL_RUNTIME_CLASSES:
|
||||||
return _DEFAULT_RUNTIME_CLASSES[name]
|
return _ALL_RUNTIME_CLASSES[name]
|
||||||
try:
|
try:
|
||||||
return get_impl(Runtime, name)
|
return get_impl(Runtime, name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
known_keys = _DEFAULT_RUNTIME_CLASSES.keys()
|
known_keys = _ALL_RUNTIME_CLASSES.keys()
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f'Runtime {name} not supported, known are: {known_keys}'
|
f'Runtime {name} not supported, known are: {known_keys}'
|
||||||
) from e
|
) from e
|
||||||
|
|
||||||
|
|
||||||
|
# Build __all__ list dynamically based on available runtimes
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'Runtime',
|
'Runtime',
|
||||||
'E2BRuntime',
|
|
||||||
'RemoteRuntime',
|
'RemoteRuntime',
|
||||||
'ModalRuntime',
|
|
||||||
'RunloopRuntime',
|
|
||||||
'DockerRuntime',
|
'DockerRuntime',
|
||||||
'DaytonaRuntime',
|
|
||||||
'KubernetesRuntime',
|
'KubernetesRuntime',
|
||||||
'CLIRuntime',
|
'CLIRuntime',
|
||||||
|
'LocalRuntime',
|
||||||
'get_runtime_cls',
|
'get_runtime_cls',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Add third-party runtimes to __all__ if they're available
|
||||||
|
for runtime_name, runtime_class in _THIRD_PARTY_RUNTIME_CLASSES.items():
|
||||||
|
__all__.append(runtime_class.__name__)
|
||||||
|
|||||||
@ -100,11 +100,10 @@ class Runtime(FileEditRuntimeMixin):
|
|||||||
|
|
||||||
Built-in implementations include:
|
Built-in implementations include:
|
||||||
- DockerRuntime: Containerized environment using Docker
|
- DockerRuntime: Containerized environment using Docker
|
||||||
- E2BRuntime: Secure sandbox using E2B
|
|
||||||
- RemoteRuntime: Remote execution environment
|
- RemoteRuntime: Remote execution environment
|
||||||
- ModalRuntime: Scalable cloud environment using Modal
|
|
||||||
- LocalRuntime: Local execution for development
|
- LocalRuntime: Local execution for development
|
||||||
- DaytonaRuntime: Cloud development environment using Daytona
|
- KubernetesRuntime: Kubernetes-based execution environment
|
||||||
|
- CLIRuntime: Command-line interface runtime
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
sid: Session ID that uniquely identifies the current user session
|
sid: Session ID that uniquely identifies the current user session
|
||||||
|
|||||||
@ -6,22 +6,14 @@ from openhands.runtime.impl.action_execution.action_execution_client import (
|
|||||||
ActionExecutionClient,
|
ActionExecutionClient,
|
||||||
)
|
)
|
||||||
from openhands.runtime.impl.cli import CLIRuntime
|
from openhands.runtime.impl.cli import CLIRuntime
|
||||||
from openhands.runtime.impl.daytona.daytona_runtime import DaytonaRuntime
|
|
||||||
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
|
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
|
||||||
from openhands.runtime.impl.e2b.e2b_runtime import E2BRuntime
|
|
||||||
from openhands.runtime.impl.local.local_runtime import LocalRuntime
|
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.remote.remote_runtime import RemoteRuntime
|
||||||
from openhands.runtime.impl.runloop.runloop_runtime import RunloopRuntime
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'ActionExecutionClient',
|
'ActionExecutionClient',
|
||||||
'CLIRuntime',
|
'CLIRuntime',
|
||||||
'DaytonaRuntime',
|
|
||||||
'DockerRuntime',
|
'DockerRuntime',
|
||||||
'E2BRuntime',
|
|
||||||
'LocalRuntime',
|
'LocalRuntime',
|
||||||
'ModalRuntime',
|
|
||||||
'RemoteRuntime',
|
'RemoteRuntime',
|
||||||
'RunloopRuntime',
|
|
||||||
]
|
]
|
||||||
|
|||||||
67
poetry.lock
generated
67
poetry.lock
generated
@ -1,12 +1,13 @@
|
|||||||
# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aioboto3"
|
name = "aioboto3"
|
||||||
version = "14.3.0"
|
version = "14.3.0"
|
||||||
description = "Async boto3 wrapper"
|
description = "Async boto3 wrapper"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = "<4.0,>=3.8"
|
python-versions = "<4.0,>=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "aioboto3-14.3.0-py3-none-any.whl", hash = "sha256:aec5de94e9edc1ffbdd58eead38a37f00ddac59a519db749a910c20b7b81bca7"},
|
{file = "aioboto3-14.3.0-py3-none-any.whl", hash = "sha256:aec5de94e9edc1ffbdd58eead38a37f00ddac59a519db749a910c20b7b81bca7"},
|
||||||
{file = "aioboto3-14.3.0.tar.gz", hash = "sha256:1d18f88bb56835c607b62bb6cb907754d717bedde3ddfff6935727cb48a80135"},
|
{file = "aioboto3-14.3.0.tar.gz", hash = "sha256:1d18f88bb56835c607b62bb6cb907754d717bedde3ddfff6935727cb48a80135"},
|
||||||
@ -24,9 +25,10 @@ s3cse = ["cryptography (>=44.0.1)"]
|
|||||||
name = "aiobotocore"
|
name = "aiobotocore"
|
||||||
version = "2.22.0"
|
version = "2.22.0"
|
||||||
description = "Async client for aws services using botocore and aiohttp"
|
description = "Async client for aws services using botocore and aiohttp"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "aiobotocore-2.22.0-py3-none-any.whl", hash = "sha256:b4e6306f79df9d81daff1f9d63189a2dbee4b77ce3ab937304834e35eaaeeccf"},
|
{file = "aiobotocore-2.22.0-py3-none-any.whl", hash = "sha256:b4e6306f79df9d81daff1f9d63189a2dbee4b77ce3ab937304834e35eaaeeccf"},
|
||||||
{file = "aiobotocore-2.22.0.tar.gz", hash = "sha256:11091477266b75c2b5d28421c1f2bc9a87d175d0b8619cb830805e7a113a170b"},
|
{file = "aiobotocore-2.22.0.tar.gz", hash = "sha256:11091477266b75c2b5d28421c1f2bc9a87d175d0b8619cb830805e7a113a170b"},
|
||||||
@ -50,9 +52,10 @@ boto3 = ["boto3 (>=1.37.2,<1.37.4)"]
|
|||||||
name = "aiofiles"
|
name = "aiofiles"
|
||||||
version = "24.1.0"
|
version = "24.1.0"
|
||||||
description = "File support for asyncio."
|
description = "File support for asyncio."
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"},
|
{file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"},
|
||||||
{file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"},
|
{file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"},
|
||||||
@ -182,9 +185,10 @@ speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>
|
|||||||
name = "aiohttp-retry"
|
name = "aiohttp-retry"
|
||||||
version = "2.9.1"
|
version = "2.9.1"
|
||||||
description = "Simple retry client for aiohttp"
|
description = "Simple retry client for aiohttp"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "aiohttp_retry-2.9.1-py3-none-any.whl", hash = "sha256:66d2759d1921838256a05a3f80ad7e724936f083e35be5abb5e16eed6be6dc54"},
|
{file = "aiohttp_retry-2.9.1-py3-none-any.whl", hash = "sha256:66d2759d1921838256a05a3f80ad7e724936f083e35be5abb5e16eed6be6dc54"},
|
||||||
{file = "aiohttp_retry-2.9.1.tar.gz", hash = "sha256:8eb75e904ed4ee5c2ec242fefe85bf04240f685391c4879d8f541d6028ff01f1"},
|
{file = "aiohttp_retry-2.9.1.tar.gz", hash = "sha256:8eb75e904ed4ee5c2ec242fefe85bf04240f685391c4879d8f541d6028ff01f1"},
|
||||||
@ -197,9 +201,10 @@ aiohttp = "*"
|
|||||||
name = "aioitertools"
|
name = "aioitertools"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
description = "itertools and builtins for AsyncIO and mixed iterables"
|
description = "itertools and builtins for AsyncIO and mixed iterables"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "aioitertools-0.12.0-py3-none-any.whl", hash = "sha256:fc1f5fac3d737354de8831cbba3eb04f79dd649d8f3afb4c5b114925e662a796"},
|
{file = "aioitertools-0.12.0-py3-none-any.whl", hash = "sha256:fc1f5fac3d737354de8831cbba3eb04f79dd649d8f3afb4c5b114925e662a796"},
|
||||||
{file = "aioitertools-0.12.0.tar.gz", hash = "sha256:c2a9055b4fbb7705f561b9d86053e8af5d10cc845d22c32008c43490b2d8dd6b"},
|
{file = "aioitertools-0.12.0.tar.gz", hash = "sha256:c2a9055b4fbb7705f561b9d86053e8af5d10cc845d22c32008c43490b2d8dd6b"},
|
||||||
@ -462,7 +467,7 @@ description = "LTS Port of Python audioop"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.13"
|
python-versions = ">=3.13"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "python_version >= \"3.13\""
|
markers = "python_version == \"3.13\""
|
||||||
files = [
|
files = [
|
||||||
{file = "audioop_lts-0.2.1-cp313-abi3-macosx_10_13_universal2.whl", hash = "sha256:fd1345ae99e17e6910f47ce7d52673c6a1a70820d78b67de1b7abb3af29c426a"},
|
{file = "audioop_lts-0.2.1-cp313-abi3-macosx_10_13_universal2.whl", hash = "sha256:fd1345ae99e17e6910f47ce7d52673c6a1a70820d78b67de1b7abb3af29c426a"},
|
||||||
{file = "audioop_lts-0.2.1-cp313-abi3-macosx_10_13_x86_64.whl", hash = "sha256:e175350da05d2087e12cea8e72a70a1a8b14a17e92ed2022952a4419689ede5e"},
|
{file = "audioop_lts-0.2.1-cp313-abi3-macosx_10_13_x86_64.whl", hash = "sha256:e175350da05d2087e12cea8e72a70a1a8b14a17e92ed2022952a4419689ede5e"},
|
||||||
@ -1644,7 +1649,7 @@ files = [
|
|||||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
]
|
]
|
||||||
markers = {main = "platform_system == \"Windows\" or sys_platform == \"win32\" or os_name == \"nt\"", dev = "os_name == \"nt\" or sys_platform == \"win32\"", runtime = "sys_platform == \"win32\"", test = "platform_system == \"Windows\" or sys_platform == \"win32\""}
|
markers = {main = "platform_system == \"Windows\" or os_name == \"nt\" or sys_platform == \"win32\"", dev = "os_name == \"nt\" or sys_platform == \"win32\"", runtime = "sys_platform == \"win32\"", test = "platform_system == \"Windows\" or sys_platform == \"win32\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "comm"
|
name = "comm"
|
||||||
@ -2000,9 +2005,10 @@ vision = ["Pillow (>=9.4.0)"]
|
|||||||
name = "daytona"
|
name = "daytona"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
description = "Python SDK for Daytona"
|
description = "Python SDK for Daytona"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "daytona-0.21.1-py3-none-any.whl", hash = "sha256:1ce6b352f52ef92e667098b7bdaa60c22ffbfb8e686a8cbd12418bf7698ac834"},
|
{file = "daytona-0.21.1-py3-none-any.whl", hash = "sha256:1ce6b352f52ef92e667098b7bdaa60c22ffbfb8e686a8cbd12418bf7698ac834"},
|
||||||
{file = "daytona-0.21.1.tar.gz", hash = "sha256:01d83dd2b627f87e82491fb97f41845768d75c33f0767eaa44f6e8378bd58e60"},
|
{file = "daytona-0.21.1.tar.gz", hash = "sha256:01d83dd2b627f87e82491fb97f41845768d75c33f0767eaa44f6e8378bd58e60"},
|
||||||
@ -2032,9 +2038,10 @@ dev = ["black[jupyter] (>=23.1.0,<24.0.0)", "build (>=1.0.3)", "isort (>=5.10.0,
|
|||||||
name = "daytona-api-client"
|
name = "daytona-api-client"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
description = "Daytona"
|
description = "Daytona"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "daytona_api_client-0.21.0-py3-none-any.whl", hash = "sha256:a8ff1f0fb397368dbd6ddb224c28d679e599c657eab2ec5821cf0c972a60229a"},
|
{file = "daytona_api_client-0.21.0-py3-none-any.whl", hash = "sha256:a8ff1f0fb397368dbd6ddb224c28d679e599c657eab2ec5821cf0c972a60229a"},
|
||||||
{file = "daytona_api_client-0.21.0.tar.gz", hash = "sha256:92d591c5a1750a827b5850425ce483441609b72b05d35a618d5353fbbba50bca"},
|
{file = "daytona_api_client-0.21.0.tar.gz", hash = "sha256:92d591c5a1750a827b5850425ce483441609b72b05d35a618d5353fbbba50bca"},
|
||||||
@ -2050,9 +2057,10 @@ urllib3 = ">=1.25.3,<3.0.0"
|
|||||||
name = "daytona-api-client-async"
|
name = "daytona-api-client-async"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
description = "Daytona"
|
description = "Daytona"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "daytona_api_client_async-0.21.0-py3-none-any.whl", hash = "sha256:f5731963d0dd6c1e207b92bdc7f5b59952d3365444bc9dc8b013d77a4dddf377"},
|
{file = "daytona_api_client_async-0.21.0-py3-none-any.whl", hash = "sha256:f5731963d0dd6c1e207b92bdc7f5b59952d3365444bc9dc8b013d77a4dddf377"},
|
||||||
{file = "daytona_api_client_async-0.21.0.tar.gz", hash = "sha256:08a22c0d1616f82efa8d157d7be6c432554fd43d75560725c4e0cef0228607d6"},
|
{file = "daytona_api_client_async-0.21.0.tar.gz", hash = "sha256:08a22c0d1616f82efa8d157d7be6c432554fd43d75560725c4e0cef0228607d6"},
|
||||||
@ -2317,9 +2325,10 @@ files = [
|
|||||||
name = "e2b"
|
name = "e2b"
|
||||||
version = "1.5.2"
|
version = "1.5.2"
|
||||||
description = "E2B SDK that give agents cloud environments"
|
description = "E2B SDK that give agents cloud environments"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = "<4.0,>=3.9"
|
python-versions = "<4.0,>=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "e2b-1.5.2-py3-none-any.whl", hash = "sha256:8cf755f2ff04098daa7ac778f768eee1df730a6181637fe124210345999890b3"},
|
{file = "e2b-1.5.2-py3-none-any.whl", hash = "sha256:8cf755f2ff04098daa7ac778f768eee1df730a6181637fe124210345999890b3"},
|
||||||
{file = "e2b-1.5.2.tar.gz", hash = "sha256:29ed891ae04ffafff1744c57eff55901200f15030d34ac3fe76d6672e2bf7845"},
|
{file = "e2b-1.5.2.tar.gz", hash = "sha256:29ed891ae04ffafff1744c57eff55901200f15030d34ac3fe76d6672e2bf7845"},
|
||||||
@ -2349,9 +2358,10 @@ files = [
|
|||||||
name = "environs"
|
name = "environs"
|
||||||
version = "9.5.0"
|
version = "9.5.0"
|
||||||
description = "simplified environment variable parsing"
|
description = "simplified environment variable parsing"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "environs-9.5.0-py2.py3-none-any.whl", hash = "sha256:1e549569a3de49c05f856f40bce86979e7d5ffbbc4398e7f338574c220189124"},
|
{file = "environs-9.5.0-py2.py3-none-any.whl", hash = "sha256:1e549569a3de49c05f856f40bce86979e7d5ffbbc4398e7f338574c220189124"},
|
||||||
{file = "environs-9.5.0.tar.gz", hash = "sha256:a76307b36fbe856bdca7ee9161e6c466fd7fcffc297109a118c59b54e27e30c9"},
|
{file = "environs-9.5.0.tar.gz", hash = "sha256:a76307b36fbe856bdca7ee9161e6c466fd7fcffc297109a118c59b54e27e30c9"},
|
||||||
@ -3053,8 +3063,8 @@ files = [
|
|||||||
google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]}
|
google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]}
|
||||||
google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev"
|
google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev"
|
||||||
proto-plus = [
|
proto-plus = [
|
||||||
{version = ">=1.22.3,<2.0.0dev"},
|
|
||||||
{version = ">=1.25.0,<2.0.0dev", markers = "python_version >= \"3.13\""},
|
{version = ">=1.25.0,<2.0.0dev", markers = "python_version >= \"3.13\""},
|
||||||
|
{version = ">=1.22.3,<2.0.0dev"},
|
||||||
]
|
]
|
||||||
protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev"
|
protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev"
|
||||||
|
|
||||||
@ -3076,8 +3086,8 @@ googleapis-common-protos = ">=1.56.2,<2.0.0"
|
|||||||
grpcio = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}
|
grpcio = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}
|
||||||
grpcio-status = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}
|
grpcio-status = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}
|
||||||
proto-plus = [
|
proto-plus = [
|
||||||
{version = ">=1.22.3,<2.0.0"},
|
|
||||||
{version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""},
|
{version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""},
|
||||||
|
{version = ">=1.22.3,<2.0.0"},
|
||||||
]
|
]
|
||||||
protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0"
|
protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0"
|
||||||
requests = ">=2.18.0,<3.0.0"
|
requests = ">=2.18.0,<3.0.0"
|
||||||
@ -3295,8 +3305,8 @@ google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0", extras
|
|||||||
google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0"
|
google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0"
|
||||||
grpc-google-iam-v1 = ">=0.14.0,<1.0.0"
|
grpc-google-iam-v1 = ">=0.14.0,<1.0.0"
|
||||||
proto-plus = [
|
proto-plus = [
|
||||||
{version = ">=1.22.3,<2.0.0"},
|
|
||||||
{version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""},
|
{version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""},
|
||||||
|
{version = ">=1.22.3,<2.0.0"},
|
||||||
]
|
]
|
||||||
protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0"
|
protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0"
|
||||||
|
|
||||||
@ -3648,6 +3658,7 @@ groups = ["main", "evaluation"]
|
|||||||
files = [
|
files = [
|
||||||
{file = "grpclib-0.4.7.tar.gz", hash = "sha256:2988ef57c02b22b7a2e8e961792c41ccf97efc2ace91ae7a5b0de03c363823c3"},
|
{file = "grpclib-0.4.7.tar.gz", hash = "sha256:2988ef57c02b22b7a2e8e961792c41ccf97efc2ace91ae7a5b0de03c363823c3"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
h2 = ">=3.1.0,<5"
|
h2 = ">=3.1.0,<5"
|
||||||
@ -3710,6 +3721,7 @@ files = [
|
|||||||
{file = "h2-4.2.0-py3-none-any.whl", hash = "sha256:479a53ad425bb29af087f3458a61d30780bc818e4ebcf01f0b536ba916462ed0"},
|
{file = "h2-4.2.0-py3-none-any.whl", hash = "sha256:479a53ad425bb29af087f3458a61d30780bc818e4ebcf01f0b536ba916462ed0"},
|
||||||
{file = "h2-4.2.0.tar.gz", hash = "sha256:c8a52129695e88b1a0578d8d2cc6842bbd79128ac685463b887ee278126ad01f"},
|
{file = "h2-4.2.0.tar.gz", hash = "sha256:c8a52129695e88b1a0578d8d2cc6842bbd79128ac685463b887ee278126ad01f"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
hpack = ">=4.1,<5"
|
hpack = ">=4.1,<5"
|
||||||
@ -3748,6 +3760,7 @@ files = [
|
|||||||
{file = "hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496"},
|
{file = "hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496"},
|
||||||
{file = "hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca"},
|
{file = "hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "html2text"
|
name = "html2text"
|
||||||
@ -3885,6 +3898,7 @@ files = [
|
|||||||
{file = "hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5"},
|
{file = "hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5"},
|
||||||
{file = "hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08"},
|
{file = "hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "identify"
|
name = "identify"
|
||||||
@ -5389,6 +5403,7 @@ files = [
|
|||||||
{file = "marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c"},
|
{file = "marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c"},
|
||||||
{file = "marshmallow-3.26.1.tar.gz", hash = "sha256:e6d8affb6cb61d39d26402096dc0aee12d5a26d490a121f118d2e81dc0719dc6"},
|
{file = "marshmallow-3.26.1.tar.gz", hash = "sha256:e6d8affb6cb61d39d26402096dc0aee12d5a26d490a121f118d2e81dc0719dc6"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
packaging = ">=17.0"
|
packaging = ">=17.0"
|
||||||
@ -5580,6 +5595,7 @@ files = [
|
|||||||
{file = "modal-1.0.4-py3-none-any.whl", hash = "sha256:6c0d96bb49b09fa47e407a13e49545e32fe0803803b4330fbeb38de5e71209cc"},
|
{file = "modal-1.0.4-py3-none-any.whl", hash = "sha256:6c0d96bb49b09fa47e407a13e49545e32fe0803803b4330fbeb38de5e71209cc"},
|
||||||
{file = "modal-1.0.4.tar.gz", hash = "sha256:09a575ff5fcae1e690b10187bea6da7ff01430c38ec1785090bf7a7ccee7f408"},
|
{file = "modal-1.0.4.tar.gz", hash = "sha256:09a575ff5fcae1e690b10187bea6da7ff01430c38ec1785090bf7a7ccee7f408"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
aiohttp = "*"
|
aiohttp = "*"
|
||||||
@ -6586,8 +6602,8 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
googleapis-common-protos = ">=1.52,<2.0"
|
googleapis-common-protos = ">=1.52,<2.0"
|
||||||
grpcio = [
|
grpcio = [
|
||||||
{version = ">=1.63.2,<2.0.0", markers = "python_version < \"3.13\""},
|
|
||||||
{version = ">=1.66.2,<2.0.0", markers = "python_version >= \"3.13\""},
|
{version = ">=1.66.2,<2.0.0", markers = "python_version >= \"3.13\""},
|
||||||
|
{version = ">=1.63.2,<2.0.0", markers = "python_version < \"3.13\""},
|
||||||
]
|
]
|
||||||
opentelemetry-api = ">=1.15,<2.0"
|
opentelemetry-api = ">=1.15,<2.0"
|
||||||
opentelemetry-exporter-otlp-proto-common = "1.34.1"
|
opentelemetry-exporter-otlp-proto-common = "1.34.1"
|
||||||
@ -9056,9 +9072,10 @@ files = [
|
|||||||
name = "runloop-api-client"
|
name = "runloop-api-client"
|
||||||
version = "0.43.0"
|
version = "0.43.0"
|
||||||
description = "The official Python library for the runloop API"
|
description = "The official Python library for the runloop API"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
|
markers = "extra == \"third-party-runtimes\""
|
||||||
files = [
|
files = [
|
||||||
{file = "runloop_api_client-0.43.0-py3-none-any.whl", hash = "sha256:20b6098b8e0714bb48812a97d5f420f547a98748d52d90789d60a38fa37a2526"},
|
{file = "runloop_api_client-0.43.0-py3-none-any.whl", hash = "sha256:20b6098b8e0714bb48812a97d5f420f547a98748d52d90789d60a38fa37a2526"},
|
||||||
{file = "runloop_api_client-0.43.0.tar.gz", hash = "sha256:879ee6a3baaabd7fd9930fe0c187de8458d138afea4f50c1e428cbf73f2ef08a"},
|
{file = "runloop_api_client-0.43.0.tar.gz", hash = "sha256:879ee6a3baaabd7fd9930fe0c187de8458d138afea4f50c1e428cbf73f2ef08a"},
|
||||||
@ -9350,7 +9367,6 @@ files = [
|
|||||||
{file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"},
|
{file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"},
|
||||||
{file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"},
|
{file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"},
|
||||||
]
|
]
|
||||||
markers = {evaluation = "platform_system == \"Linux\" and platform_machine == \"x86_64\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""]
|
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""]
|
||||||
@ -9442,6 +9458,7 @@ files = [
|
|||||||
{file = "sigtools-4.0.1-py2.py3-none-any.whl", hash = "sha256:d216b4cf920bbab0fce636ddc429ed8463a5b533d9e1492acb45a2a1bc36ac6c"},
|
{file = "sigtools-4.0.1-py2.py3-none-any.whl", hash = "sha256:d216b4cf920bbab0fce636ddc429ed8463a5b533d9e1492acb45a2a1bc36ac6c"},
|
||||||
{file = "sigtools-4.0.1.tar.gz", hash = "sha256:4b8e135a9cd4d2ea00da670c093372d74e672ba3abb87f4c98d8e73dea54445c"},
|
{file = "sigtools-4.0.1.tar.gz", hash = "sha256:4b8e135a9cd4d2ea00da670c093372d74e672ba3abb87f4c98d8e73dea54445c"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
attrs = "*"
|
attrs = "*"
|
||||||
@ -9593,7 +9610,7 @@ description = "Standard library aifc redistribution. \"dead battery\"."
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "python_version >= \"3.13\""
|
markers = "python_version == \"3.13\""
|
||||||
files = [
|
files = [
|
||||||
{file = "standard_aifc-3.13.0-py3-none-any.whl", hash = "sha256:f7ae09cc57de1224a0dd8e3eb8f73830be7c3d0bc485de4c1f82b4a7f645ac66"},
|
{file = "standard_aifc-3.13.0-py3-none-any.whl", hash = "sha256:f7ae09cc57de1224a0dd8e3eb8f73830be7c3d0bc485de4c1f82b4a7f645ac66"},
|
||||||
{file = "standard_aifc-3.13.0.tar.gz", hash = "sha256:64e249c7cb4b3daf2fdba4e95721f811bde8bdfc43ad9f936589b7bb2fae2e43"},
|
{file = "standard_aifc-3.13.0.tar.gz", hash = "sha256:64e249c7cb4b3daf2fdba4e95721f811bde8bdfc43ad9f936589b7bb2fae2e43"},
|
||||||
@ -9610,7 +9627,7 @@ description = "Standard library chunk redistribution. \"dead battery\"."
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "python_version >= \"3.13\""
|
markers = "python_version == \"3.13\""
|
||||||
files = [
|
files = [
|
||||||
{file = "standard_chunk-3.13.0-py3-none-any.whl", hash = "sha256:17880a26c285189c644bd5bd8f8ed2bdb795d216e3293e6dbe55bbd848e2982c"},
|
{file = "standard_chunk-3.13.0-py3-none-any.whl", hash = "sha256:17880a26c285189c644bd5bd8f8ed2bdb795d216e3293e6dbe55bbd848e2982c"},
|
||||||
{file = "standard_chunk-3.13.0.tar.gz", hash = "sha256:4ac345d37d7e686d2755e01836b8d98eda0d1a3ee90375e597ae43aaf064d654"},
|
{file = "standard_chunk-3.13.0.tar.gz", hash = "sha256:4ac345d37d7e686d2755e01836b8d98eda0d1a3ee90375e597ae43aaf064d654"},
|
||||||
@ -9798,6 +9815,7 @@ files = [
|
|||||||
{file = "synchronicity-0.9.15-py3-none-any.whl", hash = "sha256:6e3008f54795d73d59fbd133c812734e7c83f4a6f44257cc2a3251237ee8921b"},
|
{file = "synchronicity-0.9.15-py3-none-any.whl", hash = "sha256:6e3008f54795d73d59fbd133c812734e7c83f4a6f44257cc2a3251237ee8921b"},
|
||||||
{file = "synchronicity-0.9.15.tar.gz", hash = "sha256:9451d0caef3509e9f980ba62885a3b8ba7ab247845618e9d9c9c8d11da7ee84b"},
|
{file = "synchronicity-0.9.15.tar.gz", hash = "sha256:9451d0caef3509e9f980ba62885a3b8ba7ab247845618e9d9c9c8d11da7ee84b"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
sigtools = ">=4.0.1"
|
sigtools = ">=4.0.1"
|
||||||
@ -10455,6 +10473,7 @@ files = [
|
|||||||
{file = "types-certifi-2021.10.8.3.tar.gz", hash = "sha256:72cf7798d165bc0b76e1c10dd1ea3097c7063c42c21d664523b928e88b554a4f"},
|
{file = "types-certifi-2021.10.8.3.tar.gz", hash = "sha256:72cf7798d165bc0b76e1c10dd1ea3097c7063c42c21d664523b928e88b554a4f"},
|
||||||
{file = "types_certifi-2021.10.8.3-py3-none-any.whl", hash = "sha256:b2d1e325e69f71f7c78e5943d410e650b4707bb0ef32e4ddf3da37f54176e88a"},
|
{file = "types_certifi-2021.10.8.3-py3-none-any.whl", hash = "sha256:b2d1e325e69f71f7c78e5943d410e650b4707bb0ef32e4ddf3da37f54176e88a"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "types-python-dateutil"
|
name = "types-python-dateutil"
|
||||||
@ -10843,6 +10862,7 @@ files = [
|
|||||||
{file = "watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0901429650652d3f0da90bad42bdafc1f9143ff3605633c455c999a2d786cac"},
|
{file = "watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0901429650652d3f0da90bad42bdafc1f9143ff3605633c455c999a2d786cac"},
|
||||||
{file = "watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9"},
|
{file = "watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9"},
|
||||||
]
|
]
|
||||||
|
markers = {main = "extra == \"third-party-runtimes\""}
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
anyio = ">=3.0.0"
|
anyio = ">=3.0.0"
|
||||||
@ -11769,7 +11789,10 @@ cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
cffi = ["cffi (>=1.11)"]
|
cffi = ["cffi (>=1.11)"]
|
||||||
|
|
||||||
|
[extras]
|
||||||
|
third-party-runtimes = ["daytona", "e2b", "modal", "runloop-api-client"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.1"
|
lock-version = "2.1"
|
||||||
python-versions = "^3.12,<3.14"
|
python-versions = "^3.12,<3.14"
|
||||||
content-hash = "a2cf9e6529f7ed81f96c6183607aa61f99293027bbd3b4a635733f7c3c8e52cb"
|
content-hash = "653c4cda22ec5ff95420d305386c53ba440714fe7c59a9f7f240fdf86b698031"
|
||||||
|
|||||||
@ -14,18 +14,19 @@ readme = "README.md"
|
|||||||
repository = "https://github.com/All-Hands-AI/OpenHands"
|
repository = "https://github.com/All-Hands-AI/OpenHands"
|
||||||
packages = [
|
packages = [
|
||||||
{ include = "openhands/**/*" },
|
{ include = "openhands/**/*" },
|
||||||
|
{ include = "third_party/**/*" },
|
||||||
{ include = "pyproject.toml", to = "openhands" },
|
{ include = "pyproject.toml", to = "openhands" },
|
||||||
{ include = "poetry.lock", to = "openhands" },
|
{ include = "poetry.lock", to = "openhands" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.12,<3.14"
|
python = "^3.12,<3.14"
|
||||||
litellm = "^1.60.0, !=1.64.4, !=1.67.*" # avoid 1.64.4 (known bug) & 1.67.* (known bug #10272)
|
litellm = "^1.60.0, !=1.64.4, !=1.67.*" # avoid 1.64.4 (known bug) & 1.67.* (known bug #10272)
|
||||||
aiohttp = ">=3.9.0,!=3.11.13" # Pin to avoid yanked version 3.11.13
|
aiohttp = ">=3.9.0,!=3.11.13" # Pin to avoid yanked version 3.11.13
|
||||||
google-generativeai = "*" # To use litellm with Gemini Pro API
|
google-generativeai = "*" # To use litellm with Gemini Pro API
|
||||||
google-api-python-client = "^2.164.0" # For Google Sheets API
|
google-api-python-client = "^2.164.0" # For Google Sheets API
|
||||||
google-auth-httplib2 = "*" # For Google Sheets authentication
|
google-auth-httplib2 = "*" # For Google Sheets authentication
|
||||||
google-auth-oauthlib = "*" # For Google Sheets OAuth
|
google-auth-oauthlib = "*" # For Google Sheets OAuth
|
||||||
termcolor = "*"
|
termcolor = "*"
|
||||||
docker = "*"
|
docker = "*"
|
||||||
fastapi = "*"
|
fastapi = "*"
|
||||||
@ -34,9 +35,9 @@ types-toml = "*"
|
|||||||
uvicorn = "*"
|
uvicorn = "*"
|
||||||
numpy = "*"
|
numpy = "*"
|
||||||
json-repair = "*"
|
json-repair = "*"
|
||||||
browsergym-core = "0.13.3" # integrate browsergym-core as the browsing interface
|
browsergym-core = "0.13.3" # integrate browsergym-core as the browsing interface
|
||||||
html2text = "*"
|
html2text = "*"
|
||||||
e2b = ">=1.0.5,<1.6.0"
|
|
||||||
pexpect = "*"
|
pexpect = "*"
|
||||||
jinja2 = "^3.1.3"
|
jinja2 = "^3.1.3"
|
||||||
python-multipart = "*"
|
python-multipart = "*"
|
||||||
@ -52,8 +53,7 @@ whatthepatch = "^1.0.6"
|
|||||||
protobuf = "^5.0.0,<6.0.0" # Updated to support newer opentelemetry
|
protobuf = "^5.0.0,<6.0.0" # Updated to support newer opentelemetry
|
||||||
opentelemetry-api = "^1.33.1"
|
opentelemetry-api = "^1.33.1"
|
||||||
opentelemetry-exporter-otlp-proto-grpc = "^1.33.1"
|
opentelemetry-exporter-otlp-proto-grpc = "^1.33.1"
|
||||||
modal = ">=0.66.26,<1.1.0"
|
|
||||||
runloop-api-client = "0.43.0"
|
|
||||||
libtmux = ">=0.37,<0.40"
|
libtmux = ">=0.37,<0.40"
|
||||||
pygithub = "^2.5.0"
|
pygithub = "^2.5.0"
|
||||||
joblib = "*"
|
joblib = "*"
|
||||||
@ -80,7 +80,7 @@ bashlex = "^0.18"
|
|||||||
# TODO: These are integrations that should probably be optional
|
# TODO: These are integrations that should probably be optional
|
||||||
redis = ">=5.2,<7.0"
|
redis = ">=5.2,<7.0"
|
||||||
minio = "^7.2.8"
|
minio = "^7.2.8"
|
||||||
daytona = "0.21.1"
|
|
||||||
stripe = ">=11.5,<13.0"
|
stripe = ">=11.5,<13.0"
|
||||||
google-cloud-aiplatform = "*"
|
google-cloud-aiplatform = "*"
|
||||||
anthropic = { extras = [ "vertex" ], version = "*" }
|
anthropic = { extras = [ "vertex" ], version = "*" }
|
||||||
@ -88,6 +88,15 @@ boto3 = "*"
|
|||||||
kubernetes = "^33.1.0"
|
kubernetes = "^33.1.0"
|
||||||
pyyaml = "^6.0.2"
|
pyyaml = "^6.0.2"
|
||||||
|
|
||||||
|
# Third-party runtime dependencies (optional)
|
||||||
|
e2b = { version = ">=1.0.5,<1.6.0", optional = true }
|
||||||
|
modal = { version = ">=0.66.26,<1.1.0", optional = true }
|
||||||
|
runloop-api-client = { version = "0.43.0", optional = true }
|
||||||
|
daytona = { version = "0.21.1", optional = true }
|
||||||
|
|
||||||
|
[tool.poetry.extras]
|
||||||
|
third_party_runtimes = [ "e2b", "modal", "runloop-api-client", "daytona" ]
|
||||||
|
|
||||||
[tool.poetry.group.dev]
|
[tool.poetry.group.dev]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
|
|||||||
@ -12,11 +12,9 @@ from openhands.core.logger import openhands_logger as logger
|
|||||||
from openhands.events import EventStream
|
from openhands.events import EventStream
|
||||||
from openhands.runtime.base import Runtime
|
from openhands.runtime.base import Runtime
|
||||||
from openhands.runtime.impl.cli.cli_runtime import CLIRuntime
|
from openhands.runtime.impl.cli.cli_runtime import CLIRuntime
|
||||||
from openhands.runtime.impl.daytona.daytona_runtime import DaytonaRuntime
|
|
||||||
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
|
from openhands.runtime.impl.docker.docker_runtime import DockerRuntime
|
||||||
from openhands.runtime.impl.local.local_runtime import LocalRuntime
|
from openhands.runtime.impl.local.local_runtime import LocalRuntime
|
||||||
from openhands.runtime.impl.remote.remote_runtime import RemoteRuntime
|
from openhands.runtime.impl.remote.remote_runtime import RemoteRuntime
|
||||||
from openhands.runtime.impl.runloop.runloop_runtime import RunloopRuntime
|
|
||||||
from openhands.runtime.plugins import AgentSkillsRequirement, JupyterRequirement
|
from openhands.runtime.plugins import AgentSkillsRequirement, JupyterRequirement
|
||||||
from openhands.storage import get_file_store
|
from openhands.storage import get_file_store
|
||||||
from openhands.utils.async_utils import call_async_from_sync
|
from openhands.utils.async_utils import call_async_from_sync
|
||||||
@ -130,10 +128,6 @@ def get_runtime_classes() -> list[type[Runtime]]:
|
|||||||
return [LocalRuntime]
|
return [LocalRuntime]
|
||||||
elif runtime.lower() == 'remote':
|
elif runtime.lower() == 'remote':
|
||||||
return [RemoteRuntime]
|
return [RemoteRuntime]
|
||||||
elif runtime.lower() == 'runloop':
|
|
||||||
return [RunloopRuntime]
|
|
||||||
elif runtime.lower() == 'daytona':
|
|
||||||
return [DaytonaRuntime]
|
|
||||||
elif runtime.lower() == 'cli':
|
elif runtime.lower() == 'cli':
|
||||||
return [CLIRuntime]
|
return [CLIRuntime]
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -990,34 +990,15 @@ def test_api_keys_repr_str():
|
|||||||
app_config = OpenHandsConfig(
|
app_config = OpenHandsConfig(
|
||||||
llms={'llm': llm_config},
|
llms={'llm': llm_config},
|
||||||
agents={'agent': agent_config},
|
agents={'agent': agent_config},
|
||||||
e2b_api_key='my_e2b_api_key',
|
search_api_key='my_search_api_key',
|
||||||
jwt_secret='my_jwt_secret',
|
|
||||||
modal_api_token_id='my_modal_api_token_id',
|
|
||||||
modal_api_token_secret='my_modal_api_token_secret',
|
|
||||||
runloop_api_key='my_runloop_api_key',
|
|
||||||
daytona_api_key='my_daytona_api_key',
|
|
||||||
)
|
)
|
||||||
assert 'my_e2b_api_key' not in repr(app_config)
|
|
||||||
assert 'my_e2b_api_key' not in str(app_config)
|
assert 'my_search_api_key' not in repr(app_config)
|
||||||
assert 'my_jwt_secret' not in repr(app_config)
|
assert 'my_search_api_key' not in str(app_config)
|
||||||
assert 'my_jwt_secret' not in str(app_config)
|
|
||||||
assert 'my_modal_api_token_id' not in repr(app_config)
|
|
||||||
assert 'my_modal_api_token_id' not in str(app_config)
|
|
||||||
assert 'my_modal_api_token_secret' not in repr(app_config)
|
|
||||||
assert 'my_modal_api_token_secret' not in str(app_config)
|
|
||||||
assert 'my_runloop_api_key' not in repr(app_config)
|
|
||||||
assert 'my_runloop_api_key' not in str(app_config)
|
|
||||||
assert 'my_daytona_api_key' not in repr(app_config)
|
|
||||||
assert 'my_daytona_api_key' not in str(app_config)
|
|
||||||
|
|
||||||
# Check that no other attrs in OpenHandsConfig have 'key' or 'token' in their name
|
# Check that no other attrs in OpenHandsConfig have 'key' or 'token' in their name
|
||||||
# This will fail when new attrs are added, and attract attention
|
# This will fail when new attrs are added, and attract attention
|
||||||
known_key_token_attrs_app = [
|
known_key_token_attrs_app = [
|
||||||
'e2b_api_key',
|
|
||||||
'modal_api_token_id',
|
|
||||||
'modal_api_token_secret',
|
|
||||||
'runloop_api_key',
|
|
||||||
'daytona_api_key',
|
|
||||||
'search_api_key',
|
'search_api_key',
|
||||||
]
|
]
|
||||||
for attr_name in OpenHandsConfig.model_fields.keys():
|
for attr_name in OpenHandsConfig.model_fields.keys():
|
||||||
|
|||||||
@ -84,11 +84,11 @@ def test_llm_config_attributes_masking(test_handler):
|
|||||||
|
|
||||||
def test_app_config_attributes_masking(test_handler):
|
def test_app_config_attributes_masking(test_handler):
|
||||||
logger, stream = test_handler
|
logger, stream = test_handler
|
||||||
app_config = OpenHandsConfig(e2b_api_key='e2b-xyz789')
|
app_config = OpenHandsConfig(search_api_key='search-xyz789')
|
||||||
logger.info(f'App Config: {app_config}')
|
logger.info(f'App Config: {app_config}')
|
||||||
log_output = stream.getvalue()
|
log_output = stream.getvalue()
|
||||||
assert 'github_token' not in log_output
|
assert 'github_token' not in log_output
|
||||||
assert 'e2b-xyz789' not in log_output
|
assert 'search-xyz789' not in log_output
|
||||||
assert 'ghp_abcdefghijklmnopqrstuvwxyz' not in log_output
|
assert 'ghp_abcdefghijklmnopqrstuvwxyz' not in log_output
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
14
third_party/__init__.py
vendored
Normal file
14
third_party/__init__.py
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
"""Third-party runtime implementations for OpenHands.
|
||||||
|
|
||||||
|
This module contains runtime implementations provided by third-party vendors.
|
||||||
|
These runtimes are optional and require additional dependencies to be installed.
|
||||||
|
|
||||||
|
To use third-party runtimes, install OpenHands with the third_party_runtimes extra:
|
||||||
|
pip install openhands-ai[third_party_runtimes]
|
||||||
|
|
||||||
|
Available third-party runtimes:
|
||||||
|
- daytona: Daytona cloud development environment
|
||||||
|
- e2b: E2B secure sandbox environment
|
||||||
|
- modal: Modal cloud compute platform
|
||||||
|
- runloop: Runloop AI sandbox environment
|
||||||
|
"""
|
||||||
1
third_party/runtime/__init__.py
vendored
Normal file
1
third_party/runtime/__init__.py
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Third-party runtime implementations."""
|
||||||
1
third_party/runtime/impl/__init__.py
vendored
Normal file
1
third_party/runtime/impl/__init__.py
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Third-party runtime implementation modules."""
|
||||||
7
third_party/runtime/impl/daytona/__init__.py
vendored
Normal file
7
third_party/runtime/impl/daytona/__init__.py
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""Daytona runtime implementation.
|
||||||
|
|
||||||
|
This runtime reads configuration directly from environment variables:
|
||||||
|
- DAYTONA_API_KEY: API key for Daytona authentication
|
||||||
|
- DAYTONA_API_URL: Daytona API URL endpoint (defaults to https://app.daytona.io/api)
|
||||||
|
- DAYTONA_TARGET: Daytona target region (defaults to 'eu')
|
||||||
|
"""
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
@ -45,7 +46,13 @@ class DaytonaRuntime(ActionExecutionClient):
|
|||||||
user_id: str | None = None,
|
user_id: str | None = None,
|
||||||
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = None,
|
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = None,
|
||||||
):
|
):
|
||||||
assert config.daytona_api_key, 'Daytona API key is required'
|
# Read Daytona configuration from environment variables
|
||||||
|
daytona_api_key = os.getenv('DAYTONA_API_KEY')
|
||||||
|
if not daytona_api_key:
|
||||||
|
raise ValueError('DAYTONA_API_KEY environment variable is required for Daytona runtime')
|
||||||
|
|
||||||
|
daytona_api_url = os.getenv('DAYTONA_API_URL', 'https://app.daytona.io/api')
|
||||||
|
daytona_target = os.getenv('DAYTONA_TARGET', 'eu')
|
||||||
|
|
||||||
self.config = config
|
self.config = config
|
||||||
self.sid = sid
|
self.sid = sid
|
||||||
@ -53,9 +60,9 @@ class DaytonaRuntime(ActionExecutionClient):
|
|||||||
self._vscode_url: str | None = None
|
self._vscode_url: str | None = None
|
||||||
|
|
||||||
daytona_config = DaytonaConfig(
|
daytona_config = DaytonaConfig(
|
||||||
api_key=config.daytona_api_key.get_secret_value(),
|
api_key=daytona_api_key,
|
||||||
server_url=config.daytona_api_url,
|
server_url=daytona_api_url,
|
||||||
target=config.daytona_target,
|
target=daytona_target,
|
||||||
)
|
)
|
||||||
self.daytona = Daytona(daytona_config)
|
self.daytona = Daytona(daytona_config)
|
||||||
|
|
||||||
5
third_party/runtime/impl/e2b/__init__.py
vendored
Normal file
5
third_party/runtime/impl/e2b/__init__.py
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"""E2B runtime implementation.
|
||||||
|
|
||||||
|
This runtime reads configuration directly from environment variables:
|
||||||
|
- E2B_API_KEY: API key for E2B authentication
|
||||||
|
"""
|
||||||
@ -16,8 +16,8 @@ from openhands.integrations.provider import PROVIDER_TOKEN_TYPE
|
|||||||
from openhands.runtime.impl.action_execution.action_execution_client import (
|
from openhands.runtime.impl.action_execution.action_execution_client import (
|
||||||
ActionExecutionClient,
|
ActionExecutionClient,
|
||||||
)
|
)
|
||||||
from openhands.runtime.impl.e2b.filestore import E2BFileStore
|
from third_party.runtime.impl.e2b.filestore import E2BFileStore
|
||||||
from openhands.runtime.impl.e2b.sandbox import E2BSandbox
|
from third_party.runtime.impl.e2b.sandbox import E2BSandbox
|
||||||
from openhands.runtime.plugins import PluginRequirement
|
from openhands.runtime.plugins import PluginRequirement
|
||||||
from openhands.runtime.utils.files import insert_lines, read_lines
|
from openhands.runtime.utils.files import insert_lines, read_lines
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ class E2BRuntime(ActionExecutionClient):
|
|||||||
git_provider_tokens,
|
git_provider_tokens,
|
||||||
)
|
)
|
||||||
if sandbox is None:
|
if sandbox is None:
|
||||||
self.sandbox = E2BSandbox()
|
self.sandbox = E2BSandbox(config.sandbox)
|
||||||
if not isinstance(self.sandbox, E2BSandbox):
|
if not isinstance(self.sandbox, E2BSandbox):
|
||||||
raise ValueError('E2BRuntime requires an E2BSandbox')
|
raise ValueError('E2BRuntime requires an E2BSandbox')
|
||||||
self.file_store = E2BFileStore(self.sandbox.filesystem)
|
self.file_store = E2BFileStore(self.sandbox.filesystem)
|
||||||
@ -19,11 +19,16 @@ class E2BBox:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
config: SandboxConfig,
|
config: SandboxConfig,
|
||||||
e2b_api_key: str,
|
|
||||||
template: str = 'openhands',
|
template: str = 'openhands',
|
||||||
):
|
):
|
||||||
self.config = copy.deepcopy(config)
|
self.config = copy.deepcopy(config)
|
||||||
self.initialize_plugins: bool = config.initialize_plugins
|
self.initialize_plugins: bool = config.initialize_plugins
|
||||||
|
|
||||||
|
# Read API key from environment variable
|
||||||
|
e2b_api_key = os.getenv('E2B_API_KEY')
|
||||||
|
if not e2b_api_key:
|
||||||
|
raise ValueError('E2B_API_KEY environment variable is required for E2B runtime')
|
||||||
|
|
||||||
self.sandbox = E2BSandbox(
|
self.sandbox = E2BSandbox(
|
||||||
api_key=e2b_api_key,
|
api_key=e2b_api_key,
|
||||||
template=template,
|
template=template,
|
||||||
@ -112,3 +117,7 @@ class E2BBox:
|
|||||||
|
|
||||||
def get_working_directory(self):
|
def get_working_directory(self):
|
||||||
return self.sandbox.cwd
|
return self.sandbox.cwd
|
||||||
|
|
||||||
|
|
||||||
|
# Alias for backward compatibility
|
||||||
|
E2BSandbox = E2BBox
|
||||||
6
third_party/runtime/impl/modal/__init__.py
vendored
Normal file
6
third_party/runtime/impl/modal/__init__.py
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
"""Modal runtime implementation.
|
||||||
|
|
||||||
|
This runtime reads configuration directly from environment variables:
|
||||||
|
- MODAL_TOKEN_ID: Modal API token ID for authentication
|
||||||
|
- MODAL_TOKEN_SECRET: Modal API token secret for authentication
|
||||||
|
"""
|
||||||
@ -57,16 +57,22 @@ class ModalRuntime(ActionExecutionClient):
|
|||||||
user_id: str | None = None,
|
user_id: str | None = None,
|
||||||
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = None,
|
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = None,
|
||||||
):
|
):
|
||||||
assert config.modal_api_token_id, 'Modal API token id is required'
|
# Read Modal API credentials from environment variables
|
||||||
assert config.modal_api_token_secret, 'Modal API token secret is required'
|
modal_token_id = os.getenv('MODAL_TOKEN_ID')
|
||||||
|
modal_token_secret = os.getenv('MODAL_TOKEN_SECRET')
|
||||||
|
|
||||||
|
if not modal_token_id:
|
||||||
|
raise ValueError('MODAL_TOKEN_ID environment variable is required for Modal runtime')
|
||||||
|
if not modal_token_secret:
|
||||||
|
raise ValueError('MODAL_TOKEN_SECRET environment variable is required for Modal runtime')
|
||||||
|
|
||||||
self.config = config
|
self.config = config
|
||||||
self.sandbox = None
|
self.sandbox = None
|
||||||
self.sid = sid
|
self.sid = sid
|
||||||
|
|
||||||
self.modal_client = modal.Client.from_credentials(
|
self.modal_client = modal.Client.from_credentials(
|
||||||
config.modal_api_token_id.get_secret_value(),
|
modal_token_id,
|
||||||
config.modal_api_token_secret.get_secret_value(),
|
modal_token_secret,
|
||||||
)
|
)
|
||||||
self.app = modal.App.lookup(
|
self.app = modal.App.lookup(
|
||||||
'openhands', create_if_missing=True, client=self.modal_client
|
'openhands', create_if_missing=True, client=self.modal_client
|
||||||
5
third_party/runtime/impl/runloop/__init__.py
vendored
Normal file
5
third_party/runtime/impl/runloop/__init__.py
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
"""Runloop runtime implementation.
|
||||||
|
|
||||||
|
This runtime reads configuration directly from environment variables:
|
||||||
|
- RUNLOOP_API_KEY: API key for Runloop authentication
|
||||||
|
"""
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
import tenacity
|
import tenacity
|
||||||
@ -40,11 +41,15 @@ class RunloopRuntime(ActionExecutionClient):
|
|||||||
user_id: str | None = None,
|
user_id: str | None = None,
|
||||||
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = None,
|
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = None,
|
||||||
):
|
):
|
||||||
assert config.runloop_api_key is not None, 'Runloop API key is required'
|
# Read Runloop API key from environment variable
|
||||||
|
runloop_api_key = os.getenv('RUNLOOP_API_KEY')
|
||||||
|
if not runloop_api_key:
|
||||||
|
raise ValueError('RUNLOOP_API_KEY environment variable is required for Runloop runtime')
|
||||||
|
|
||||||
self.devbox: DevboxView | None = None
|
self.devbox: DevboxView | None = None
|
||||||
self.config = config
|
self.config = config
|
||||||
self.runloop_api_client = Runloop(
|
self.runloop_api_client = Runloop(
|
||||||
bearer_token=config.runloop_api_key.get_secret_value(),
|
bearer_token=runloop_api_key,
|
||||||
)
|
)
|
||||||
self.container_name = CONTAINER_NAME_PREFIX + sid
|
self.container_name = CONTAINER_NAME_PREFIX + sid
|
||||||
super().__init__(
|
super().__init__(
|
||||||
Loading…
x
Reference in New Issue
Block a user