Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 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
68 changes: 3 additions & 65 deletions src/agentscope_runtime/common/container_clients/agentrun_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import string
import time
from http.client import HTTPS_PORT
from typing import List, Optional, Dict
from urllib.parse import urlparse

from alibabacloud_agentrun20250910.models import (
Expand All @@ -23,74 +22,13 @@
from alibabacloud_agentrun20250910.client import Client
from alibabacloud_tea_openapi import models as open_api_models

from agentscope_runtime.sandbox.model import SandboxManagerEnvConfig
from .base_client import BaseClient
from .utils import SessionManager
from ...sandbox.model import SandboxManagerEnvConfig

logger = logging.getLogger(__name__)


class AgentRunSessionManager:
"""
Manager for AgentRun sessions that handles creation, retrieval,
updating, and deletion of sessions.
"""

def __init__(self):
"""Initialize the session manager with an empty session dictionary."""
self.sessions = {}
logger.debug("AgentRunSessionManager initialized")

def create_session(self, session_id: str, session_data: Dict):
"""Create a new session with the given session_id and session_data.

Args:
session_id (str): Unique identifier for the session.
session_data (Dict): Data to store in the session.
"""
self.sessions[session_id] = session_data
logger.info(f"Created AgentRun session: {session_id}")

def get_session(self, session_id: str) -> Optional[Dict]:
"""Retrieve session data by session_id.

Args:
session_id (str): Unique identifier for the session.

Returns:
Optional[Dict]: Session data if found, None otherwise.
"""
return self.sessions.get(session_id)

def update_session(self, session_id: str, updates: Dict):
"""Update an existing session with new data.

Args:
session_id (str): Unique identifier for the session.
updates (Dict): Data to update in the session.
"""
if session_id in self.sessions:
self.sessions[session_id].update(updates)
logger.debug(f"Updated AgentRun session: {session_id}")

def delete_session(self, session_id: str):
"""Delete a session by session_id.

Args:
session_id (str): Unique identifier for the session.
"""
if session_id in self.sessions:
del self.sessions[session_id]
logger.info(f"Deleted AgentRun session: {session_id}")

def list_sessions(self) -> List[str]:
"""List all session IDs.

Returns:
List[str]: List of all session IDs.
"""
return list(self.sessions.keys())


class AgentRunClient(BaseClient):
"""
Client for managing AgentRun containers in the sandbox environment.
Expand All @@ -117,7 +55,7 @@ def __init__(self, config: SandboxManagerEnvConfig):
"""
self.config = config
self.client = self._create_agent_run_client()
self.session_manager = AgentRunSessionManager()
self.session_manager = SessionManager(config)
self.agent_run_prefix = config.agent_run_prefix or "agentscope-sandbox"
self._get_agent_runtime_status_max_attempts = (
self.GET_AGENT_RUNTIME_STATUS_MAX_ATTEMPTS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def __init__(self, config=None):
raise RuntimeError(
f"BoxLite client initialization failed: {str(e)}\n"
"Solutions:\n"
"• Switch to the sync SDK (async is not supported yet)\n"
"• Ensure BoxLite is properly installed\n"
"• Check BoxLite runtime configuration",
) from e
Expand Down
65 changes: 2 additions & 63 deletions src/agentscope_runtime/common/container_clients/fc_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import string
import time
from http.client import HTTPS_PORT
from typing import List, Dict, Optional
from urllib.parse import urlparse

from alibabacloud_fc20230330 import models as fc20230330_models
Expand All @@ -18,71 +17,11 @@

from agentscope_runtime.sandbox.model import SandboxManagerEnvConfig
from .base_client import BaseClient
from .utils import SessionManager

logger = logging.getLogger(__name__)


class FCSessionManager:
"""Manager for Function Compute sessions that handles creation, retrieval,
updating, and deletion of sessions.
"""

def __init__(self):
"""Initialize the session manager with an empty session dictionary."""
self.sessions = {}
logger.debug("FC Session Manager initialized")

def create_session(self, session_id: str, session_data: Dict):
"""Create a new session with the given session_id and session_data.

Args:
session_id (str): Unique identifier for the session.
session_data (Dict): Data to store in the session.
"""
self.sessions[session_id] = session_data
logger.debug(f"Created FC session: {session_id}")

def get_session(self, session_id: str) -> Optional[Dict]:
"""Retrieve session data by session_id.

Args:
session_id (str): Unique identifier for the session.

Returns:
Optional[Dict]: Session data if found, None otherwise.
"""
return self.sessions.get(session_id)

def update_session(self, session_id: str, updates: Dict):
"""Update an existing session with new data.

Args:
session_id (str): Unique identifier for the session.
updates (Dict): Data to update in the session.
"""
if session_id in self.sessions:
self.sessions[session_id].update(updates)
logger.debug(f"Updated FC session: {session_id}")

def delete_session(self, session_id: str):
"""Delete a session by session_id.

Args:
session_id (str): Unique identifier for the session.
"""
if session_id in self.sessions:
del self.sessions[session_id]
logger.debug(f"Deleted FC session: {session_id}")

def list_sessions(self) -> List[str]:
"""List all session IDs.

Returns:
List[str]: List of all session IDs.
"""
return list(self.sessions.keys())


class FCClient(BaseClient):
"""Client for managing Function Compute containers in the sandbox environment.

Expand All @@ -102,7 +41,7 @@ def __init__(self, config: SandboxManagerEnvConfig):
"""
self.config = config
self.fc_client = self._create_fc_client()
self.session_manager = FCSessionManager()
self.session_manager = SessionManager(config)
self.function_prefix = config.fc_prefix or "agentscope-sandbox"

logger.info(
Expand Down
69 changes: 69 additions & 0 deletions src/agentscope_runtime/common/container_clients/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
import logging
from typing import Dict, Optional, List

from ..collections import RedisMapping, InMemoryMapping

logger = logging.getLogger(__name__)


class SessionManager:
"""Manager for sessions that handles creation, retrieval,
updating, and deletion of sessions.
"""

def __init__(self, config):
"""Initialize the session manager with an empty session dictionary."""
self.config = config
Comment thread
rayrayraykk marked this conversation as resolved.

if self.config.redis_enabled:
import redis

redis_client = redis.Redis(
host=self.config.redis_server,
port=self.config.redis_port,
db=self.config.redis_db,
username=self.config.redis_user,
password=self.config.redis_password,
decode_responses=True,
)
try:
redis_client.ping()
except ConnectionError as e:
raise RuntimeError(
"Unable to connect to the Redis server.",
) from e

self.sessions = RedisMapping(
redis_client,
prefix="container_session_manager", # TODO: Configurable
)
else:
self.sessions = InMemoryMapping()

logger.debug("Session Manager initialized")

def create_session(self, session_id: str, session_data: Dict):
"""Create a new session with the given session_id and session_data."""
self.sessions.set(session_id, session_data)
logger.debug(f"Created session: {session_id}")
Comment thread
rayrayraykk marked this conversation as resolved.

def get_session(self, session_id: str) -> Optional[Dict]:
"""Retrieve session data by session_id."""
return self.sessions.get(session_id)
Comment thread
rayrayraykk marked this conversation as resolved.

def update_session(self, session_id: str, updates: Dict):
"""Update an existing session with new data."""
if self.sessions.get(session_id):
self.sessions.set(session_id, updates)
Comment thread
rayrayraykk marked this conversation as resolved.
logger.debug(f"Updated session: {session_id}")
Comment thread
rayrayraykk marked this conversation as resolved.
Comment on lines +55 to +59
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

update_session() currently overwrites the stored session with updates instead of merging into the existing session data. Callers (e.g., AgentRunClient/FCClient) store identifiers like agent_runtime_id in the session; overwriting with {"status": ...} will discard those fields and break later operations. Merge updates into the existing session dict before saving (or implement a mapping-level partial update).

Copilot uses AI. Check for mistakes.

def delete_session(self, session_id: str):
"""Delete a session by session_id."""
if self.sessions.get(session_id):
self.sessions.delete(session_id)
logger.debug(f"Deleted session: {session_id}")
Comment thread
rayrayraykk marked this conversation as resolved.

def list_sessions(self) -> List[str]:
"""List all session IDs."""
return list(self.sessions.scan())
Comment thread
rayrayraykk marked this conversation as resolved.
Comment thread
rayrayraykk marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
import os
from typing import Any, Dict, Optional

from ..cloud.cloud_sandbox import CloudSandbox
from ...registry import SandboxRegistry
from ...enums import SandboxType
from ..cloud.cloud_sandbox import CloudSandbox
from ...constant import TIMEOUT

logger = logging.getLogger(__name__)

Expand All @@ -20,7 +21,7 @@
"agentbay-cloud", # Virtual image name indicating cloud service
sandbox_type=SandboxType.AGENTBAY,
security_level="high",
timeout=300,
timeout=TIMEOUT,
description="AgentBay Cloud Sandbox Environment",
)
class AgentbaySandbox(CloudSandbox):
Expand All @@ -42,7 +43,6 @@ class AgentbaySandbox(CloudSandbox):
def __init__(
self,
sandbox_id: Optional[str] = None,
timeout: int = 3000,
base_url: Optional[str] = None,
bearer_token: Optional[str] = None,
sandbox_type: SandboxType = SandboxType.AGENTBAY,
Expand All @@ -56,7 +56,6 @@ def __init__(

Args:
sandbox_id: Optional sandbox ID for existing sessions
timeout: Timeout for operations in seconds
base_url: Base URL for AgentBay API (optional)
bearer_token: Authentication token (deprecated, use api_key)
sandbox_type: Type of sandbox (default: AGENTBAY)
Expand All @@ -80,7 +79,6 @@ def __init__(

super().__init__(
sandbox_id=sandbox_id,
timeout=timeout,
base_url=base_url,
bearer_token=self.api_key,
sandbox_type=sandbox_type,
Expand Down
4 changes: 0 additions & 4 deletions src/agentscope_runtime/sandbox/box/base/base_sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ class BaseSandbox(Sandbox):
def __init__(
self,
sandbox_id: Optional[str] = None,
timeout: int = 3000,
base_url: Optional[str] = None,
bearer_token: Optional[str] = None,
sandbox_type: SandboxType = SandboxType.BASE,
workspace_dir: Optional[str] = None,
):
super().__init__(
sandbox_id,
timeout,
base_url,
bearer_token,
sandbox_type,
Expand Down Expand Up @@ -64,15 +62,13 @@ class BaseSandboxAsync(SandboxAsync):
def __init__(
self,
sandbox_id: Optional[str] = None,
timeout: int = 3000,
base_url: Optional[str] = None,
bearer_token: Optional[str] = None,
sandbox_type: SandboxType = SandboxType.BASE_ASYNC,
workspace_dir: Optional[str] = None,
):
super().__init__(
sandbox_id,
timeout,
base_url,
bearer_token,
sandbox_type,
Expand Down
4 changes: 0 additions & 4 deletions src/agentscope_runtime/sandbox/box/browser/browser_sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,13 @@ class BrowserSandbox(GUIMixin, BaseSandbox):
def __init__( # pylint: disable=useless-parent-delegation
self,
sandbox_id: Optional[str] = None,
timeout: int = 3000,
base_url: Optional[str] = None,
bearer_token: Optional[str] = None,
sandbox_type: SandboxType = SandboxType.BROWSER,
workspace_dir: Optional[str] = None,
):
super().__init__(
sandbox_id,
timeout,
base_url,
bearer_token,
sandbox_type,
Expand Down Expand Up @@ -314,15 +312,13 @@ class BrowserSandboxAsync(GUIMixin, AsyncGUIMixin, BaseSandboxAsync):
def __init__( # pylint: disable=useless-parent-delegation
self,
sandbox_id: Optional[str] = None,
timeout: int = 3000,
base_url: Optional[str] = None,
bearer_token: Optional[str] = None,
sandbox_type: SandboxType = SandboxType.BROWSER_ASYNC,
workspace_dir: Optional[str] = None,
):
super().__init__(
sandbox_id,
timeout,
base_url,
bearer_token,
sandbox_type,
Expand Down
Loading
Loading