fix new page opening in browser; latest container wip

This commit is contained in:
marko-kraemer 2025-05-09 05:08:29 +02:00
parent 0b51c6507c
commit fead1c831b
7 changed files with 53 additions and 35 deletions

View File

@ -88,7 +88,7 @@ You'll need the following components:
- Redis database for caching and session management
- Daytona sandbox for secure agent execution
- Python 3.11 for the API backend
- API keys for LLM providers (Anthropic)
- API keys for LLM providers (Anthropic, OpenRouter)
- Tavily API key for enhanced search capabilities
- Firecrawl API key for web scraping capabilities
@ -99,23 +99,16 @@ You'll need the following components:
- Save your project's API URL, anon key, and service role key for later use
- Install the [Supabase CLI](https://supabase.com/docs/guides/cli/getting-started)
2. **Redis**: Set up a Redis instance using one of these options:
- [Upstash Redis](https://upstash.com/) (recommended for cloud deployments)
- Local installation:
- [Mac](https://formulae.brew.sh/formula/redis): `brew install redis`
- [Linux](https://redis.io/docs/getting-started/installation/install-redis-on-linux/): Follow distribution-specific instructions
- [Windows](https://redis.io/docs/getting-started/installation/install-redis-on-windows/): Use WSL2 or Docker
- Docker Compose (included in our setup):
- If you're using our Docker Compose setup, Redis is included and configured automatically
- No additional installation is needed
- Save your Redis connection details for later use (not needed if using Docker Compose)
2. **Redis**:
- Go to the `/backend` folder
- Run `docker compose up redis`
3. **Daytona**:
- Create an account on [Daytona](https://app.daytona.io/)
- Generate an API key from your account settings
- Go to [Images](https://app.daytona.io/dashboard/images)
- Click "Add Image"
- Enter `adamcohenhillel/kortix-suna:0.0.20` as the image name
- Enter `kortix/suna:0.1` as the image name
- Set `/usr/bin/supervisord -n -c /etc/supervisor/conf.d/supervisord.conf` as the Entrypoint
4. **LLM API Keys**:

32
backend/sandbox/README.md Normal file
View File

@ -0,0 +1,32 @@
# Agent Sandbox
This directory contains the agent sandbox implementation - a Docker-based virtual environment that agents use as their own computer to execute tasks, access the web, and manipulate files.
## Overview
The sandbox provides a complete containerized Linux environment with:
- Chrome browser for web interactions
- VNC server for accessing the Web User
- Web server for serving content (port 8080) -> loading html files from the /workspace directory
- Full file system access
- Full sudo access
## Customizing the Sandbox
You can modify the sandbox environment for development or to add new capabilities:
1. Edit files in the `docker/` directory
2. Build a custom image:
```
cd backend/sandbox/docker
docker-compose build
```
3. Test your changes locally using docker-compose
## Using a Custom Image
To use your custom sandbox image:
1. Change the `image` parameter in `docker-compose.yml` (that defines the image name `kortix/suna:___`)
2. Update the same image name in `backend/sandbox/sandbox.py` in the `create_sandbox` function
3. If using Daytona for deployment, update the image reference there as well

View File

@ -7,7 +7,6 @@ from pydantic import BaseModel
from utils.logger import logger
from utils.auth_utils import get_optional_user_id
from sandbox.sandbox import get_or_start_sandbox
from services.supabase import DBConnection
from agent.api import get_or_create_project_sandbox
@ -97,13 +96,7 @@ async def get_sandbox_by_id_safely(client, sandbox_id: str):
try:
# Get the sandbox
sandbox, retrieved_sandbox_id, sandbox_pass = await get_or_create_project_sandbox(client, project_id)
# Verify we got the right sandbox
if retrieved_sandbox_id != sandbox_id:
logger.warning(f"Retrieved sandbox ID {retrieved_sandbox_id} doesn't match requested ID {sandbox_id} for project {project_id}")
# Fall back to the direct method if IDs don't match (shouldn't happen but just in case)
sandbox = await get_or_start_sandbox(sandbox_id)
sandbox = await get_or_create_project_sandbox(client, project_id)
return sandbox
except Exception as e:

View File

@ -1,10 +1,11 @@
from fastapi import FastAPI, APIRouter, HTTPException, Body
from playwright.async_api import async_playwright, Browser, Page
from playwright.async_api import async_playwright, Browser, Page, ElementHandle
from pydantic import BaseModel
from typing import Optional, List, Dict, Any
from typing import Optional, List, Dict, Any, Union
import asyncio
import json
import logging
import re
import base64
from dataclasses import dataclass, field
from datetime import datetime
@ -356,13 +357,13 @@ class BrowserAutomation:
self.current_page_index = 0
except Exception as page_error:
print(f"Error finding existing page, creating new one. ( {page_error})")
page = await self.browser.new_page()
# page = await self.browser.new_page()
print("New page created successfully")
self.pages.append(page)
# self.pages.append(page)
self.current_page_index = 0
# Navigate to about:blank to ensure page is ready
# await page.goto("google.com", timeout=30000)
print("Navigated to google.com")
# print("Navigated to google.com")
print("Browser initialization completed successfully")
except Exception as e:

View File

@ -6,7 +6,7 @@ services:
dockerfile: ${DOCKERFILE:-Dockerfile}
args:
TARGETPLATFORM: ${TARGETPLATFORM:-linux/amd64}
image: adamcohenhillel/kortix-suna:0.0.20
image: kortix/suna:0.1
ports:
- "6080:6080" # noVNC web interface
- "5901:5901" # VNC port

View File

@ -1,6 +1,5 @@
fastapi==0.115.12
uvicorn==0.34.0
pyautogui==0.9.54
pillow==10.2.0
pydantic==2.6.1
pytesseract==0.3.13
fastapi
uvicorn
pillow
pydantic
pytesseract

View File

@ -97,7 +97,7 @@ def create_sandbox(password: str, project_id: str = None):
labels = {'id': project_id}
params = CreateSandboxParams(
image="adamcohenhillel/kortix-suna:0.0.20",
image="kortix/suna:0.1",
public=True,
labels=labels,
env_vars={
@ -169,7 +169,7 @@ class SandboxToolsBase(Tool):
self._sandbox_pass = sandbox_info.get('pass')
# Get or start the sandbox
self._sandbox = await get_or_start_sandbox(self._sandbox_id)
# self._sandbox = await get_or_start_sandbox(self._sandbox_id)
# # Log URLs if not already printed
# if not SandboxToolsBase._urls_printed: