Skip to content

Commit b861033

Browse files
authored
Merge pull request #5 from BrowserOperator/feat/twilio-followup
Feat/twilio followup
2 parents 2253697 + 3e81cf8 commit b861033

File tree

224 files changed

+22321
-33
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

224 files changed

+22321
-33
lines changed

Dockerfile.cloudrun

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,19 @@ RUN git remote add upstream https://github.com/BrowserOperator/browser-operator-
4949
RUN git fetch upstream
5050
RUN git checkout upstream/main
5151

52-
# Build Browser Operator version
52+
# Enable AUTOMATED_MODE for Docker deployment
53+
RUN sed -i 's/AUTOMATED_MODE: false/AUTOMATED_MODE: true/' front_end/panels/ai_chat/core/BuildConfig.ts
54+
55+
# Build Browser Operator version with AUTOMATED_MODE enabled
5356
RUN npm run build
5457

58+
# Eval-Server build stage
59+
FROM node:22-bullseye-slim AS eval-server-builder
60+
WORKDIR /eval-server
61+
COPY eval-server/nodejs/package*.json ./
62+
RUN npm install --production
63+
COPY eval-server/nodejs/ ./
64+
5565
# Multi-stage build using kernel-images as base
5666
FROM docker.io/golang:1.25.0 AS server-builder
5767
WORKDIR /workspace/server
@@ -143,7 +153,16 @@ RUN apt-get update && \
143153
netcat \
144154
nginx \
145155
# PPA req
146-
software-properties-common && \
156+
software-properties-common \
157+
# Node.js for eval-server
158+
ca-certificates \
159+
gnupg && \
160+
# Install Node.js 22.x for eval-server
161+
mkdir -p /etc/apt/keyrings && \
162+
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
163+
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
164+
apt-get update && \
165+
apt-get install -y nodejs && \
147166
# Disable nginx auto-start to prevent conflicts with custom config
148167
systemctl disable nginx || true && \
149168
systemctl mask nginx || true && \
@@ -187,7 +206,7 @@ ENV USERNAME=kernel
187206
RUN set -eux; \
188207
apt-get update; \
189208
apt-get install -y --no-install-recommends \
190-
wget ca-certificates python2 supervisor xclip xdotool \
209+
wget ca-certificates python2 python3 python-is-python3 supervisor xclip xdotool \
191210
pulseaudio dbus-x11 xserver-xorg-video-dummy \
192211
libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 \
193212
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
@@ -256,6 +275,20 @@ COPY --from=devtools-builder /workspace/devtools/devtools-frontend/out/Default/g
256275
# Set permissions for DevTools files
257276
RUN chown -R kernel:kernel /usr/share/nginx/devtools
258277

278+
# ============================================================================
279+
# Eval-Server Integration
280+
# ============================================================================
281+
282+
# Copy eval-server from builder
283+
COPY --from=eval-server-builder /eval-server /opt/eval-server
284+
285+
# Copy custom eval-server startup script INTO eval-server directory
286+
COPY eval-server-start.js /opt/eval-server/start-cloudrun.js
287+
RUN chmod +x /opt/eval-server/start-cloudrun.js
288+
289+
# Set permissions for eval-server
290+
RUN chown -R kernel:kernel /opt/eval-server
291+
259292
# Cloud Run specific: wrapper scripts (nginx config is inline)
260293
# DO NOT copy nginx.conf to avoid auto-start conflicts
261294
COPY cloudrun-wrapper.sh /cloudrun-wrapper.sh
@@ -268,6 +301,7 @@ COPY supervisor/services-cloudrun/xorg.conf /etc/supervisor/conf.d/services-clou
268301
COPY supervisor/services-cloudrun/neko.conf /etc/supervisor/conf.d/services-cloudrun/neko.conf
269302
COPY supervisor/services-cloudrun/chromium.conf /etc/supervisor/conf.d/services-cloudrun/chromium.conf
270303
COPY supervisor/services-cloudrun/devtools-frontend.conf /etc/supervisor/conf.d/services-cloudrun/devtools-frontend.conf
304+
COPY supervisor/services-cloudrun/eval-server.conf /etc/supervisor/conf.d/services-cloudrun/eval-server.conf
271305

272306
# Create nginx temp directories for non-root execution
273307
RUN mkdir -p /tmp/nginx_client_temp /tmp/nginx_proxy_temp /tmp/nginx_fastcgi_temp \
@@ -279,7 +313,7 @@ RUN mkdir -p /tmp/nginx_client_temp /tmp/nginx_proxy_temp /tmp/nginx_fastcgi_tem
279313
# Create supervisor log directories
280314
RUN mkdir -p /var/log/supervisord/chromium /var/log/supervisord/neko /var/log/supervisord/xorg \
281315
/var/log/supervisord/dbus /var/log/supervisord/kernel-images-api /var/log/supervisord/mutter \
282-
/var/log/supervisord/nginx /var/log/supervisord/devtools-frontend && \
316+
/var/log/supervisord/nginx /var/log/supervisord/devtools-frontend /var/log/supervisord/eval-server && \
283317
chown -R kernel:kernel /var/log/supervisord
284318

285319
# Create health check endpoint

Readme.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,16 +227,35 @@ Example: 1 hour session ≈ $0.50-1.00
227227

228228
The `cloudbuild.yaml` provides:
229229
1. Submodule initialization
230-
2. Docker image build
230+
2. Docker image build with caching
231231
3. Container Registry push
232232
4. Cloud Run deployment
233233
5. Traffic routing
234234

235-
Trigger builds via:
235+
### Build Commands
236+
236237
```bash
238+
# Normal build (with cache) - recommended for development
237239
gcloud builds submit --config cloudbuild.yaml
240+
241+
# Force rebuild without cache - use when dependencies change
242+
gcloud builds submit --config cloudbuild.yaml --substitutions=_NO_CACHE=true
243+
244+
# Automated deployment with Twilio TURN server setup
245+
./deploy.sh
238246
```
239247

248+
### Cache Control
249+
250+
The build system uses Docker layer caching by default to reduce build times and costs:
251+
- **With cache**: ~5-10 minutes, lower cost
252+
- **Without cache**: ~30+ minutes, higher cost (~$3-5 per build)
253+
254+
Use `_NO_CACHE=true` only when:
255+
- Dependencies have changed significantly
256+
- Base images need updating
257+
- Debugging build issues
258+
240259
## 📚 Additional Resources
241260

242261
- [kernel-images Documentation](https://github.com/onkernel/kernel-images)

browser-operator-core

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 3aaef1ef13cede9dd2b443ee5eddf7102be8cc24

cloudbuild.yaml

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# Cloud Build configuration for kernel-browser
2+
# Usage: gcloud builds submit --substitutions=_NO_CACHE=true (to disable cache)
3+
substitutions:
4+
_NO_CACHE: 'false'
5+
26
steps:
37
# Step 1: Verify kernel-images directory exists
48
- name: 'gcr.io/cloud-builders/docker'
@@ -17,22 +21,36 @@ steps:
1721
args:
1822
- '-c'
1923
- |
20-
echo "Attempting to pull previous image for caching..."
21-
docker pull us-docker.pkg.dev/$PROJECT_ID/gcr.io/kernel-browser:latest || echo "No previous image found for caching"
24+
if [ "${_NO_CACHE}" = "true" ]; then
25+
echo "⚠️ Cache disabled by _NO_CACHE=true flag"
26+
else
27+
echo "Attempting to pull previous image for caching..."
28+
docker pull us-docker.pkg.dev/$PROJECT_ID/gcr.io/kernel-browser:latest || echo "No previous image found for caching"
29+
fi
2230
2331
# Step 3: Build the Docker image with caching (using cloudrun Dockerfile)
2432
- name: 'gcr.io/cloud-builders/docker'
33+
entrypoint: 'bash'
2534
args:
26-
- 'build'
27-
- '--file'
28-
- 'Dockerfile.cloudrun'
29-
- '--cache-from'
30-
- 'us-docker.pkg.dev/$PROJECT_ID/gcr.io/kernel-browser:latest'
31-
- '--build-arg'
32-
- 'CACHE_BUST=$BUILD_ID'
33-
- '--tag'
34-
- 'us-docker.pkg.dev/$PROJECT_ID/gcr.io/kernel-browser:latest'
35-
- '.'
35+
- '-c'
36+
- |
37+
if [ "${_NO_CACHE}" = "true" ]; then
38+
echo "🔨 Building without cache..."
39+
docker build \
40+
--file Dockerfile.cloudrun \
41+
--no-cache \
42+
--build-arg CACHE_BUST=$BUILD_ID \
43+
--tag us-docker.pkg.dev/$PROJECT_ID/gcr.io/kernel-browser:latest \
44+
.
45+
else
46+
echo "🚀 Building with cache from previous image..."
47+
docker build \
48+
--file Dockerfile.cloudrun \
49+
--cache-from us-docker.pkg.dev/$PROJECT_ID/gcr.io/kernel-browser:latest \
50+
--build-arg CACHE_BUST=$BUILD_ID \
51+
--tag us-docker.pkg.dev/$PROJECT_ID/gcr.io/kernel-browser:latest \
52+
.
53+
fi
3654
timeout: '3600s' # Allow 1 hour for build (it's a large image)
3755

3856
# Step 4: Push the image to Artifact Registry
@@ -48,12 +66,14 @@ steps:
4866
- '-c'
4967
- |
5068
# Check if Twilio secrets exist and choose appropriate service file
51-
if gcloud secrets describe twilio-account-sid --project=$PROJECT_ID >/dev/null 2>&1 && \
52-
gcloud secrets describe twilio-auth-token --project=$PROJECT_ID >/dev/null 2>&1; then
53-
echo "Using service-secrets.yaml with Secret Manager references"
69+
echo "Checking for Twilio secrets..."
70+
if gcloud secrets describe twilio-account-sid --project=$PROJECT_ID && \
71+
gcloud secrets describe twilio-auth-token --project=$PROJECT_ID; then
72+
echo "✅ Twilio secrets found! Using service-secrets.yaml with Secret Manager references"
5473
cp service-secrets.yaml temp-service.yaml
5574
else
56-
echo "Using standard service.yaml (secrets not configured)"
75+
echo "⚠️ Twilio secrets NOT found. Using standard service.yaml (secrets not configured)"
76+
echo "To use Twilio TURN servers, run: ./deploy.sh to set up secrets"
5777
cp service.yaml temp-service.yaml
5878
fi
5979

cloudrun-wrapper.sh

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ export HEIGHT=768
1313
export WIDTH=1024
1414
export NEKO_BIND=:8081
1515

16+
# WebRTC Cloud Run configuration - force relay-only mode
17+
export NEKO_WEBRTC_ICE_LITE=true
18+
export NEKO_WEBRTC_ICE_POLICY=relay
19+
export NEKO_WEBRTC_MDNS=false
20+
export NEKO_WEBRTC_ICE_INTERFACES=""
21+
1622
# Get fresh Twilio TURN credentials if available
1723
if [ -f /twilio-credential-updater.sh ]; then
1824
echo "[cloudrun-wrapper] Getting fresh Twilio TURN credentials..."
@@ -23,7 +29,7 @@ fi
2329

2430
# Port configuration for Cloud Run
2531
export PORT=${PORT:-8080}
26-
export CHROMIUM_FLAGS="${CHROMIUM_FLAGS:---user-data-dir=/home/kernel/user-data --disable-dev-shm-usage --disable-gpu --start-maximized --disable-software-rasterizer --remote-allow-origins=* --no-sandbox --disable-setuid-sandbox --disable-features=VizDisplayCompositor --custom-devtools-frontend=http://localhost:8001/ https://www.google.com}"
32+
export CHROMIUM_FLAGS="${CHROMIUM_FLAGS:---user-data-dir=/home/kernel/user-data --disable-dev-shm-usage --disable-gpu --start-maximized --disable-software-rasterizer --remote-allow-origins=* --no-sandbox --disable-setuid-sandbox --disable-features=VizDisplayCompositor --custom-devtools-frontend=http://localhost:8001/ --auto-open-devtools-for-tabs https://www.google.com}"
2733

2834
# Setup directories with proper permissions
2935
mkdir -p /tmp/nginx_client_temp /tmp/nginx_proxy_temp /tmp/nginx_fastcgi_temp \
@@ -51,6 +57,8 @@ http {
5157
include /etc/nginx/mime.types;
5258
default_type application/octet-stream;
5359
60+
# Configure log files to use /tmp for non-root execution
61+
access_log /tmp/cloudrun-nginx-access.log;
5462
# Create temp directories for nginx (non-root execution)
5563
client_body_temp_path /tmp/nginx_client_temp;
5664
proxy_temp_path /tmp/nginx_proxy_temp;
@@ -120,6 +128,7 @@ http {
120128
# Chrome DevTools Protocol HTTP endpoints
121129
location /json {
122130
proxy_pass http://127.0.0.1:9223/json;
131+
proxy_http_version 1.1;
123132
proxy_set_header Host \$host;
124133
proxy_set_header X-Real-IP \$remote_addr;
125134
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
@@ -129,6 +138,7 @@ http {
129138
# Chrome DevTools Protocol HTTP endpoints (with trailing slash)
130139
location /json/ {
131140
proxy_pass http://127.0.0.1:9223/json/;
141+
proxy_http_version 1.1;
132142
proxy_set_header Host \$host;
133143
proxy_set_header X-Real-IP \$remote_addr;
134144
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
@@ -157,6 +167,50 @@ http {
157167
proxy_send_timeout 86400;
158168
}
159169
170+
# Eval-Server HTTP API endpoints
171+
location /v1/responses {
172+
proxy_pass http://127.0.0.1:8083/v1/responses;
173+
proxy_http_version 1.1;
174+
proxy_set_header Host \$host;
175+
proxy_set_header X-Real-IP \$remote_addr;
176+
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
177+
proxy_set_header X-Forwarded-Proto \$scheme;
178+
proxy_read_timeout 1800;
179+
proxy_send_timeout 1800;
180+
}
181+
182+
# Eval-Server status endpoint
183+
location /eval/status {
184+
proxy_pass http://127.0.0.1:8083/status;
185+
proxy_http_version 1.1;
186+
proxy_set_header Host \$host;
187+
proxy_set_header X-Real-IP \$remote_addr;
188+
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
189+
proxy_set_header X-Forwarded-Proto \$scheme;
190+
}
191+
192+
# Eval-Server clients endpoint
193+
location /eval/clients {
194+
proxy_pass http://127.0.0.1:8083/clients;
195+
proxy_http_version 1.1;
196+
proxy_set_header Host \$host;
197+
proxy_set_header X-Real-IP \$remote_addr;
198+
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
199+
proxy_set_header X-Forwarded-Proto \$scheme;
200+
}
201+
202+
# Eval-Server evaluate endpoint
203+
location /eval/evaluate {
204+
proxy_pass http://127.0.0.1:8083/evaluate;
205+
proxy_http_version 1.1;
206+
proxy_set_header Host \$host;
207+
proxy_set_header X-Real-IP \$remote_addr;
208+
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
209+
proxy_set_header X-Forwarded-Proto \$scheme;
210+
proxy_read_timeout 1800;
211+
proxy_send_timeout 1800;
212+
}
213+
160214
# Enhanced DevTools Frontend
161215
location /devtools/ {
162216
proxy_pass http://127.0.0.1:8001/;

deploy.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,29 @@ setup_secrets() {
149149
--project="$PROJECT_ID" \
150150
--quiet
151151

152+
# Grant Cloud Build service account permission to view secrets (needed for cloudbuild.yaml)
153+
local project_number=$(gcloud projects describe "$PROJECT_ID" --format="value(projectNumber)")
154+
local cb_sa_email="${project_number}@cloudbuild.gserviceaccount.com"
155+
156+
info "Granting Secret Manager viewer access to Cloud Build service account..."
157+
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
158+
--member="serviceAccount:$cb_sa_email" \
159+
--role="roles/secretmanager.viewer" \
160+
--project="$PROJECT_ID" \
161+
--quiet
162+
163+
gcloud secrets add-iam-policy-binding twilio-account-sid \
164+
--member="serviceAccount:$cb_sa_email" \
165+
--role="roles/secretmanager.secretAccessor" \
166+
--project="$PROJECT_ID" \
167+
--quiet
168+
169+
gcloud secrets add-iam-policy-binding twilio-auth-token \
170+
--member="serviceAccount:$cb_sa_email" \
171+
--role="roles/secretmanager.secretAccessor" \
172+
--project="$PROJECT_ID" \
173+
--quiet
174+
152175
# Set flag to use secrets-enabled service.yaml
153176
export USE_SECRETS=true
154177

eval-server-start.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env node
2+
3+
// Custom eval-server startup script for Cloud Run
4+
// Uses environment variables for port configuration
5+
6+
import { EvalServer } from './src/lib/EvalServer.js';
7+
import { HTTPWrapper } from './src/lib/HTTPWrapper.js';
8+
9+
const WS_PORT = parseInt(process.env.EVAL_SERVER_WS_PORT || '8082');
10+
const HTTP_PORT = parseInt(process.env.EVAL_SERVER_HTTP_PORT || '8083');
11+
const HOST = process.env.EVAL_SERVER_HOST || '127.0.0.1';
12+
13+
console.log('🔧 Creating EvalServer...');
14+
const evalServer = new EvalServer({
15+
// No authKey - authentication disabled for automated mode
16+
host: HOST,
17+
port: WS_PORT
18+
});
19+
20+
console.log('🔧 Creating HTTP wrapper...');
21+
const httpWrapper = new HTTPWrapper(evalServer, {
22+
port: HTTP_PORT,
23+
host: HOST
24+
});
25+
26+
console.log('🔧 Starting EvalServer...');
27+
await evalServer.start();
28+
console.log(`✅ EvalServer started on ws://${HOST}:${WS_PORT}`);
29+
30+
console.log('🔧 Starting HTTP wrapper...');
31+
await httpWrapper.start();
32+
console.log(`✅ HTTP API started on http://${HOST}:${HTTP_PORT}`);
33+
34+
console.log('⏳ Waiting for DevTools client to connect...');
35+
console.log(` WebSocket URL: ws://${HOST}:${WS_PORT}`);
36+
console.log(` HTTP API URL: http://${HOST}:${HTTP_PORT}`);
37+
console.log(' Auth: Disabled (automated mode)');
38+
39+
// Add periodic status check
40+
setInterval(() => {
41+
const evalServerStatus = evalServer.getStatus();
42+
const httpWrapperStatus = httpWrapper.getStatus();
43+
console.log(`📊 EvalServer: ${evalServerStatus.connectedClients} clients, ${evalServerStatus.readyClients} ready`);
44+
console.log(`📊 HTTP API: ${httpWrapperStatus.isRunning ? 'running' : 'stopped'} on ${httpWrapperStatus.url}`);
45+
}, 30000);

eval-server/.env.example

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# WebSocket Server Configuration
2+
PORT=8080
3+
HOST=localhost
4+
5+
# LLM Judge Configuration
6+
OPENAI_API_KEY=your-openai-api-key-here
7+
JUDGE_MODEL=gpt-4
8+
JUDGE_TEMPERATURE=0.1
9+
10+
# Logging Configuration
11+
LOG_LEVEL=info
12+
LOG_DIR=./logs
13+
14+
# RPC Configuration
15+
RPC_TIMEOUT=30000
16+
MAX_CONCURRENT_EVALUATIONS=10

eval-server/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.env
2+
node_modules
3+
*.log

0 commit comments

Comments
 (0)