mirror of https://github.com/kortix-ai/suna.git
change to exec in deploy
This commit is contained in:
parent
8271e0dbd3
commit
4d5d93e943
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"],
|
||||
|
|
|
@ -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"]
|
Loading…
Reference in New Issue