support use existing sandbox by id

This commit is contained in:
GhostC
2025-07-20 16:02:18 +08:00
parent 398ae434ed
commit 3301d54625
4 changed files with 178 additions and 16 deletions
+61 -8
View File
@@ -17,7 +17,8 @@ from app.tool.python_execute import PythonExecute
from app.tool.str_replace_editor import StrReplaceEditor
from app.tool.sb_browser_tool import SandboxBrowserTool
from app.daytona.sandbox import create_sandbox
from app.daytona.sandbox import create_sandbox,get_or_start_sandbox
import daytona
class SandboxManus(ToolCallAgent):
"""A versatile general-purpose agent with support for both local and MCP tools."""
@@ -53,6 +54,7 @@ class SandboxManus(ToolCallAgent):
default_factory=dict
) # server_id -> url/command
_initialized: bool = False
sandbox_link: Optional[dict[str, dict[str, str]]] = Field(default_factory=dict)
@model_validator(mode="after")
def initialize_helper(self) -> "SandboxManus":
@@ -65,16 +67,67 @@ class SandboxManus(ToolCallAgent):
"""Factory method to create and properly initialize a Manus instance."""
instance = cls(**kwargs)
await instance.initialize_mcp_servers()
instance.initialize_sandbox_tools()
await instance.initialize_sandbox_tools()
instance._initialized = True
return instance
def initialize_sandbox_tools(self,password="123456") -> None:
sandbox = create_sandbox(password=password)
print(f"VNC link: {sandbox.get_preview_link(6080)}")
computer_tool = SandboxBrowserTool.create_with_sandbox(sandbox)
sandbox_tools=[computer_tool]
self.available_tools.add_tools(*sandbox_tools)
async def initialize_sandbox_tools(self, sandbox_id: str = config.daytona.sandbox_id, password:str = config.daytona.VNC_password) -> None:
try:
if sandbox_id:
sandbox = await get_or_start_sandbox(sandbox_id)
# Initialize sandbox_link if not exists
if not self.sandbox_link:
self.sandbox_link = {}
# Check if URLs are already cached
if sandbox_id in self.sandbox_link:
vnc_url = self.sandbox_link[sandbox_id]["vnc"]
website_url = self.sandbox_link[sandbox_id]["website"]
logger.info(f"Using cached URLs - VNC: {vnc_url}, Website: {website_url}")
else:
# Get URLs from sandbox and cache them
vnc_link = sandbox.get_preview_link(6080)
website_link = sandbox.get_preview_link(8080)
vnc_url = vnc_link.url if hasattr(vnc_link, 'url') else str(vnc_link)
website_url = website_link.url if hasattr(website_link, 'url') else str(website_link)
# Cache the URLs
self.sandbox_link[sandbox_id] = {
"vnc": str(vnc_url),
"website": str(website_url)
}
logger.info(f"Cached new URLs - VNC: {vnc_url}, Website: {website_url}")
logger.info(f"VNC URL: {vnc_url}")
logger.info(f"Website URL: {website_url}")
else:
# 创建新沙箱
if password:
sandbox = create_sandbox(password=password)
else:
raise ValueError("Sandbox ID or password must be provided")
vnc_link = sandbox.get_preview_link(6080)
website_link = sandbox.get_preview_link(8080)
vnc_url = vnc_link.url if hasattr(vnc_link, 'url') else str(vnc_link)
website_url = website_link.url if hasattr(website_link, 'url') else str(website_link)
# Get the actual sandbox_id from the created sandbox
actual_sandbox_id = sandbox.id if hasattr(sandbox, 'id') else 'new_sandbox'
if not self.sandbox_link:
self.sandbox_link = {}
self.sandbox_link[actual_sandbox_id] = {
"vnc": vnc_url,
"website": website_url,
}
logger.info(f"VNC URL: {vnc_url}")
logger.info(f"Website URL: {website_url}")
computer_tool = SandboxBrowserTool.create_with_sandbox(sandbox)
self.available_tools.add_tools(computer_tool)
except Exception as e:
logger.error(f"Error initializing sandbox tools: {e}")
raise
async def initialize_mcp_servers(self) -> None:
"""Initialize connections to configured MCP servers."""
+2
View File
@@ -111,6 +111,8 @@ class DaytonaSettings(BaseModel):
daytona_target: Optional[str] = Field("us", description="enum ['asia', 'eu', 'us']")
sandbox_image_name: Optional[str]= Field("kortix/suna:0.1.3", description="")
sandbox_entrypoint: Optional[str]= Field("/usr/bin/supervisord -n -c /etc/supervisor/conf.d/supervisord.conf", description="")
sandbox_id: Optional[str] = Field(None, description="ID of the daytona sandbox to use, if any")
VNC_password: Optional[str] = Field("123456", description="VNC password for the vnc service in sandbox")
class MCPServerConfig(BaseModel):
"""Configuration for a single MCP server"""
+115
View File
@@ -0,0 +1,115 @@
# Global LLM configuration
[llm]
model = "claude-3-7-sonnet-20250219" # The LLM model to use
base_url = "https://api.anthropic.com/v1/" # API endpoint URL
api_key = "YOUR_API_KEY" # Your API key
max_tokens = 8192 # Maximum number of tokens in the response
temperature = 0.0 # Controls randomness
# [llm] # Amazon Bedrock
# api_type = "aws" # Required
# model = "us.anthropic.claude-3-7-sonnet-20250219-v1:0" # Bedrock supported modelID
# base_url = "bedrock-runtime.us-west-2.amazonaws.com" # Not used now
# max_tokens = 8192
# temperature = 1.0
# api_key = "bear" # Required but not used for Bedrock
# [llm] #AZURE OPENAI:
# api_type= 'azure'
# model = "YOUR_MODEL_NAME" #"gpt-4o-mini"
# base_url = "{YOUR_AZURE_ENDPOINT.rstrip('/')}/openai/deployments/{AZURE_DEPLOYMENT_ID}"
# api_key = "AZURE API KEY"
# max_tokens = 8096
# temperature = 0.0
# api_version="AZURE API VERSION" #"2024-08-01-preview"
# [llm] #OLLAMA:
# api_type = 'ollama'
# model = "llama3.2"
# base_url = "http://localhost:11434/v1"
# api_key = "ollama"
# max_tokens = 4096
# temperature = 0.0
# Optional configuration for specific LLM models
[llm.vision]
model = "claude-3-7-sonnet-20250219" # The vision model to use
base_url = "https://api.anthropic.com/v1/" # API endpoint URL for vision model
api_key = "YOUR_API_KEY" # Your API key for vision model
max_tokens = 8192 # Maximum number of tokens in the response
temperature = 0.0 # Controls randomness for vision model
# [llm.vision] #OLLAMA VISION:
# api_type = 'ollama'
# model = "llama3.2-vision"
# base_url = "http://localhost:11434/v1"
# api_key = "ollama"
# max_tokens = 4096
# temperature = 0.0
# Optional configuration for specific browser configuration
# [browser]
# Whether to run browser in headless mode (default: false)
#headless = false
# Disable browser security features (default: true)
#disable_security = true
# Extra arguments to pass to the browser
#extra_chromium_args = []
# Path to a Chrome instance to use to connect to your normal browser
# e.g. '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
#chrome_instance_path = ""
# Connect to a browser instance via WebSocket
#wss_url = ""
# Connect to a browser instance via CDP
#cdp_url = ""
# Optional configuration, Proxy settings for the browser
# [browser.proxy]
# server = "http://proxy-server:port"
# username = "proxy-username"
# password = "proxy-password"
# Optional configuration, Search settings.
# [search]
# Search engine for agent to use. Default is "Google", can be set to "Baidu" or "DuckDuckGo" or "Bing".
#engine = "Google"
# Fallback engine order. Default is ["DuckDuckGo", "Baidu", "Bing"] - will try in this order after primary engine fails.
#fallback_engines = ["DuckDuckGo", "Baidu", "Bing"]
# Seconds to wait before retrying all engines again when they all fail due to rate limits. Default is 60.
#retry_delay = 60
# Maximum number of times to retry all engines when all fail. Default is 3.
#max_retries = 3
# Language code for search results. Options: "en" (English), "zh" (Chinese), etc.
#lang = "en"
# Country code for search results. Options: "us" (United States), "cn" (China), etc.
#country = "us"
## Sandbox configuration
#[sandbox]
#use_sandbox = false
#image = "python:3.12-slim"
#work_dir = "/workspace"
#memory_limit = "1g" # 512m
#cpu_limit = 2.0
#timeout = 300
#network_enabled = true
# Daytona configuration
#[daytona]
#daytona_api_key = ""
#daytona_server_url = "https://app.daytona.io/api"
#daytona_target = "us"
#sandbox_image_name = "kortix/suna:0.1.3"
#sandbox_entrypoint =
#sandbox_id =
#VNC_password =
# MCP (Model Context Protocol) configuration
[mcp]
server_reference = "app.mcp.server" # default server module reference
# Optional Runflow configuration
# Your can add additional agents into run-flow workflow to solve different-type tasks.
[runflow]
use_data_analysis_agent = false # The Data Analysi Agent to solve various data analysis tasks
-8
View File
@@ -95,14 +95,6 @@ temperature = 0.0 # Controls randomness for vision mode
#timeout = 300
#network_enabled = true
# Daytona configuration
[daytona]
daytona_api_key = ""
daytona_server_url = "https://app.daytona.io/api"
daytona_target = "us"
#sandbox_image_name =
#sandbox_entrypoint =
# MCP (Model Context Protocol) configuration
[mcp]
server_reference = "app.mcp.server" # default server module reference