change to exec in deploy

This commit is contained in:
marko-kraemer 2025-04-23 14:43:57 +01:00
parent 8271e0dbd3
commit 4d5d93e943
4 changed files with 69 additions and 19 deletions

View File

@ -18,7 +18,6 @@ from agent.tools.sb_files_tool import SandboxFilesTool
from agent.tools.sb_browser_tool import SandboxBrowserTool
from agent.tools.data_providers_tool import DataProvidersTool
from agent.prompt import get_system_prompt
from sandbox.sandbox import create_sandbox, get_or_start_sandbox
from utils import logger
from utils.billing import check_billing_status, get_account_id_from_thread
@ -39,7 +38,7 @@ async def run_agent(
"""Run the development agent with specified configuration."""
thread_manager = ThreadManager()
client = await thread_manager.db.client
# Get account ID from thread for billing checks

View File

@ -3,7 +3,6 @@ from dotenv import load_dotenv
from agentpress.tool import ToolResult, openapi_schema, xml_schema
from sandbox.sandbox import SandboxToolsBase, Sandbox
from utils.files_utils import clean_path
from agent.tools.sb_shell_tool import SandboxShellTool
from agentpress.thread_manager import ThreadManager
# Load environment variables
@ -16,7 +15,6 @@ class SandboxDeployTool(SandboxToolsBase):
super().__init__(project_id, thread_manager)
self.workspace_path = "/workspace" # Ensure we're always operating in /workspace
self.cloudflare_api_token = os.getenv("CLOUDFLARE_API_TOKEN")
self.shell_tool = SandboxShellTool(project_id, thread_manager)
def clean_path(self, path: str) -> str:
"""Clean and normalize a path to be relative to /workspace"""
@ -99,27 +97,23 @@ class SandboxDeployTool(SandboxToolsBase):
# Single command that creates the project if it doesn't exist and then deploys
project_name = f"{self.sandbox_id}-{name}"
deploy_cmd = f'''export CLOUDFLARE_API_TOKEN={self.cloudflare_api_token} &&
deploy_cmd = f'''cd {self.workspace_path} && export CLOUDFLARE_API_TOKEN={self.cloudflare_api_token} &&
(npx wrangler pages deploy {full_path} --project-name {project_name} ||
(npx wrangler pages project create {project_name} --production-branch production &&
npx wrangler pages deploy {full_path} --project-name {project_name}))'''
# Execute command using shell_tool.execute_command
response = await self.shell_tool.execute_command(
command=deploy_cmd,
folder=None, # Use the workspace root
timeout=300 # Increased timeout for deployments
)
# Execute the command directly using the sandbox's process.exec method
response = self.sandbox.process.exec(deploy_cmd, timeout=300)
print(f"Deployment response: {response}")
print(f"Deployment command output: {response.result}")
if response.success:
if response.exit_code == 0:
return self.success_response({
"message": f"Website deployed successfully",
"output": response.output
"output": response.result
})
else:
return self.fail_response(f"Deployment failed: {response.output}")
return self.fail_response(f"Deployment failed with exit code {response.exit_code}: {response.result}")
except Exception as e:
return self.fail_response(f"Error during deployment: {str(e)}")
except Exception as e:

View File

@ -1,5 +1,6 @@
from fastapi import FastAPI
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from contextlib import asynccontextmanager
from agentpress.thread_manager import ThreadManager
from services.supabase import DBConnection
@ -8,6 +9,8 @@ from dotenv import load_dotenv
import asyncio
from utils.logger import logger
import uuid
import time
from collections import OrderedDict
# Import the agent API module
from agent import api as agent_api
@ -21,6 +24,10 @@ db = DBConnection()
thread_manager = None
instance_id = str(uuid.uuid4())[:8] # Generate instance ID at module load time
# Rate limiter state
ip_tracker = OrderedDict()
MAX_CONCURRENT_IPS = 25
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
@ -57,9 +64,56 @@ async def lifespan(app: FastAPI):
app = FastAPI(lifespan=lifespan)
# @app.middleware("http")
# async def log_requests_middleware(request: Request, call_next):
# client_ip = request.client.host
# logger.info(f"Request from IP {client_ip} to {request.method} {request.url.path}")
# response = await call_next(request)
# return response
# @app.middleware("http")
# async def throw_error_middleware(request: Request, call_next):
# client_ip = request.client.host
# if client_ip != "109.49.168.102":
# logger.warning(f"Request blocked from IP {client_ip} to {request.method} {request.url.path}")
# return JSONResponse(
# status_code=403,
# content={"error": "Request blocked", "message": "Test DDoS protection"}
# )
# return await call_next(request)
# @app.middleware("http")
# async def rate_limit_middleware(request: Request, call_next):
# global ip_tracker
# client_ip = request.client.host
# # Clean up old entries (older than 5 minutes)
# current_time = time.time()
# ip_tracker = OrderedDict((ip, ts) for ip, ts in ip_tracker.items()
# if current_time - ts < 300)
# # Check if IP is already tracked
# if client_ip in ip_tracker:
# ip_tracker[client_ip] = current_time
# return await call_next(request)
# # Check if we've hit the limit
# if len(ip_tracker) >= MAX_CONCURRENT_IPS:
# logger.warning(f"Rate limit exceeded. Current IPs: {len(ip_tracker)}")
# return JSONResponse(
# status_code=429,
# content={"error": "Too many concurrent connections",
# "message": "Maximum number of concurrent connections reached"}
# )
# # Add new IP
# ip_tracker[client_ip] = current_time
# logger.info(f"New connection from IP {client_ip}. Total connections: {len(ip_tracker)}")
# return await call_next(request)
app.add_middleware(
CORSMiddleware,
allow_origins=["https://www.suna.so", "https://suna.so", "https://staging.suna.so", "http://localhost:3000"],
allow_origins=["https://www.suna.so", "https://suna.so", "https://staging.suna.so"], #http://localhost:3000
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization"],

View File

@ -14,13 +14,16 @@ COPY . .
ENV PYTHONPATH=/app
# Default environment variables
# These should be overridden at runtime with actual values
ENV DAYTONA_API_KEY=""
ENV DAYTONA_SERVER_URL=""
ENV DAYTONA_TARGET=""
ENV ANTHROPIC_API_KEY=""
ENV OPENAI_API_KEY=""
ENV MODEL_TO_USE=""
ENV TAVILY_API_KEY=""
ENV RAPID_API_KEY=""
ENV CLOUDFLARE_API_TOKEN=""
ENV SUPABASE_URL=""
ENV SUPABASE_ANON_KEY=""
@ -35,4 +38,4 @@ ENV REDIS_SSL=""
EXPOSE 8000
# Command to run the application with Uvicorn directly
CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "32", "--log-level", "info", "--timeout-keep-alive", "500", "--proxy-headers", "--forwarded-allow-ips", "*"]
CMD ["gunicorn", "api:app", "--workers", "24", "--worker-class", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000", "--timeout", "600", "--graceful-timeout", "300", "--keep-alive", "250", "--max-requests", "1000", "--max-requests-jitter", "50", "--log-level", "info", "--forwarded-allow-ips", "*", "--worker-connections", "1000", "--worker-tmp-dir", "/dev/shm", "--preload"]