Skip to content

feat deploy toolkit #2145

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
39 changes: 39 additions & 0 deletions camel/deploy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
from typing import Any, Dict

from .config import validate_e2b_config
from .platforms.e2b import E2BDeployer


class DeployToolkit:
"""Main deployment toolkit interface"""

def __init__(self, platform: str, config: Dict[str, Any]):
self.platform = platform
self.config = config

if platform == "e2b":
self.config = validate_e2b_config(config)
self.deployer = E2BDeployer(self.config)
else:
raise ValueError(f"Unsupported platform: {platform}")

async def deploy(self) -> Dict[str, Any]:
"""Deploy the application"""
return await self.deployer.deploy()

async def destroy(self, session_id: str):
"""Destroy a deployment"""
await self.deployer.destroy(session_id)
31 changes: 31 additions & 0 deletions camel/deploy/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
from typing import Any, Dict

from pydantic import BaseModel


class E2BConfig(BaseModel):
"""E2B configuration model"""

api_key: str
project_name: str
runtime: str = "python3.9"
requirements_path: str = "requirements.txt"
app_path: str = "app.py"


def validate_e2b_config(config: Dict[str, Any]) -> E2BConfig:
"""Validate E2B configuration"""
return E2BConfig(**config)
101 changes: 101 additions & 0 deletions camel/deploy/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
class DeployError(Exception):
"""Base exception for deployment errors"""

pass


class ConfigurationError(DeployError):
"""Raised when there is a configuration error"""

pass


class PlatformError(DeployError):
"""Raised when there is a platform-specific error"""

pass


class E2BError(PlatformError):
"""Base exception for E2B-specific errors"""

pass


class E2BConnectionError(E2BError):
"""Raised when there is a connection error with E2B"""

pass


class E2BAuthenticationError(E2BError):
"""Raised when there is an authentication error with E2B"""

pass


class E2BDeploymentError(E2BError):
"""Raised when deployment to E2B fails"""

pass


class E2BRuntimeError(E2BError):
"""Raised when there is a runtime error in E2B environment"""

pass


class ResourceNotFoundError(DeployError):
"""Raised when a required resource is not found"""

pass


class ValidationError(DeployError):
"""Raised when validation fails"""

pass


class TimeoutError(DeployError):
"""Raised when an operation times out"""

pass


# usage example:
"""
try:
if not api_key:
raise E2BAuthenticationError("API key is required")
if not os.path.exists(requirements_path):
# 将长行拆分成多行
error_msg = f"Requirements file not found: {requirements_path}"
raise ResourceNotFoundError(error_msg)
except E2BAuthenticationError as e:
logger.error(f"Authentication failed: {str(e)}")
raise
except ResourceNotFoundError as e:
logger.error(f"Resource error: {str(e)}")
raise
except E2BError as e:
logger.error(f"E2B error: {str(e)}")
raise
except DeployError as e:
logger.error(f"Deployment error: {str(e)}")
raise
"""
82 changes: 82 additions & 0 deletions camel/deploy/platforms/e2b.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
from typing import Any, Dict

import e2b

from ..exceptions import DeployError


class E2BDeployer:
"""E2B deployment implementation"""

def __init__(self, config: Dict[str, Any]):
"""
Initialize E2B deployer

Args:
config: Configuration dictionary containing:
- api_key: E2B API key
- project_name: Name of the project
- runtime: Python runtime version
"""
self.config = config
self.api_key = config.get('api_key')
if not self.api_key:
raise DeployError("E2B API key is required")

# Initialize E2B client
e2b.init(api_key=self.api_key)

async def deploy(self) -> Dict[str, Any]:
"""
Deploy the application to E2B

Returns:
Dict containing deployment information
"""
try:
# Create new deployment
session = await e2b.Session.create(
id="camel-deployment",
runtime=self.config.get('runtime', 'python3.9'),
)

# Install dependencies
await session.run("pip install -r requirements.txt")

# Start the application
await session.daemon("python app.py")

return {
"status": "success",
"url": session.url,
"session_id": session.id,
}

except Exception as e:
raise DeployError(f"E2B deployment failed: {e!s}")

async def destroy(self, session_id: str):
"""
Destroy a deployment

Args:
session_id: ID of the session to destroy
"""
try:
session = await e2b.Session.get(session_id)
await session.close()
except Exception as e:
raise DeployError(f"Failed to destroy deployment: {e!s}")
Loading
Loading