🚀 WAIIDE Bootstrap - LLM Debugging Context
Calliope Integration: This component is integrated into the Calliope AI platform. Some features and configurations may differ from the upstream project.
🚨 CRITICAL DEVELOPMENT CONSTRAINTS
⛔ NEVER Modify Files Inside WAIIDE/ Submodule
THE RULE: The WAIIDE/ directory is a Git submodule tracking upstream Microsoft WAIIDE. ANY changes to files inside WAIIDE/src/ or WAIIDE/extensions/ will be overwritten when syncing with upstream.
WHY THIS MATTERS:
WAIIDE/tracks Microsoft’s WAIIDE repo- We keep it updated to get latest WAIIDE features & security patches
- Direct modifications break on
git submodule update
CORRECT APPROACH:
# ❌ WRONG - Will be overwritten on submodule update
vim WAIIDE/src/vs/platform/product/common/product.ts
# ✅ CORRECT - Outside submodule, injected at build time
vim WAIIDE/product.jsonIf You Need to Change WAIIDE Behavior:
- Branding: Edit
WAIIDE/product.json(outside src/, safe to modify) - Settings: Edit
assets/server-settings.jsonorassets/default-settings.json - Extensions: Modify
calliope-WAIIDE-agent/(our extension, not upstream) - Core changes: Consider if it can be done via extension API first
- Last resort: Document the patch needed and apply at build time
Check if File is in Submodule:
cd WAIIDE && git ls-files --error-unmatch path/to/file
# Exit 0 = tracked by submodule = DON'T TOUCH
# Exit non-zero = safe to modify⚠️ ALSO IMPORTANT: The documentation has port inconsistencies. This bootstrap file reflects the actual implementation from the WAIIDE. Default ports are 8070 (main) and 8071 (WAIIDE), NOT 8080 as some docs claim.
🎯 Quick Context
WAIIDE (Web AI IDE) is a containerized WAIIDE Server designed for JupyterHub integration. It runs WAIIDE in a web browser, allowing users to spawn multiple isolated development environments through JupyterHub.
🏗️ Architecture Overview
┌─────────────────────────────────────────────────────┐
│ WAIIDE Container │
├─────────────────────────────────────────────────────┤
│ │
│ Entrypoint: /usr/local/bin/entrypoint-jupyterhub.sh │
│ ├─ Detects JupyterHub environment variables │
│ ├─ Fixes permissions (root → UID 1000) │
│ └─ Starts appropriate services │
│ │
│ ┌───────────────────┬────────────────────────┐ │
│ │ JupyterHub Mode │ Standalone Mode │ │
│ ├───────────────────┼────────────────────────┤ │
│ │ jupyterhub- │ api_server.py │ │
│ │ singleuser │ (Custom proxy) │ │
│ │ Port: 8070* │ Port: 8070* │ │
│ │ │ │ │
│ │ jupyter-server- │ Proxies all requests │ │
│ │ proxy │ to WAIIDE │ │
│ └─────────┬─────────┴──────────┬─────────────┘ │
│ │ │ │
│ └────────┬───────────┘ │
│ ↓ │
│ ┌─────────────────────┐ │
│ │ WAIIDE Server │ │
│ │ Port: 8071* │ │
│ │ (localhost only) │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────┘
* Default ports - can be overridden with env vars🔧 Port Configuration (ACTUAL from WAIIDE)
| Service | Default Port | Environment Variable | Notes |
|---|---|---|---|
| Main Service | 8070 | PORT or JUPYTERHUB_PORT | External facing (JupyterHub/API) |
| WAIIDE Server | 8071 | VSCODE_PORT | Internal only (localhost) |
⚠️ Documentation Inconsistencies
- Some docs incorrectly claim port 8080 as default
- Various docs show different ports - trust the WAIIDE, not the docs
- Actual defaults: 8070 (main service) and 8071 (WAIIDE)
🚀 Operating Modes
1. JupyterHub Mode (Production)
Activated when these env vars are present:
JUPYTERHUB_SERVICE_PREFIX(e.g.,/user/alice/alice-waiide-abc123/)JUPYTERHUB_USER(e.g.,alice)JUPYTERHUB_API_TOKEN
What happens:
- Starts
jupyterhub-singleuseron port 8070 - Includes
jupyter-server-proxyfor routing - WAIIDE accessible at root URL via proxy
2. Standalone Mode (Development)
Activated when NO JupyterHub env vars detected.
What happens:
- Starts
api_server.pyon port 8070 - Provides JupyterHub-compatible API endpoints
- Proxies all non-API requests to WAIIDE
📁 Key Files & Their Purpose
/usr/local/bin/
├── entrypoint-jupyterhub.sh # Main entry - detects mode, fixes perms
└── api_server.py # Standalone proxy server
/opt/calliope/
├── WAIIDE-server/ # WAIIDE Server binaries (system-wide)
└── scripts/ # System scripts (jupyter_server_config.py, etc.)
/home/{username}/ # Dynamically created per user
├── workspace/ # User's WAIIDE and projects
└── .WAIIDE-server/ # User's WAIIDE data & extensions🔑 Critical Environment Variables
JupyterHub Sets These:
JUPYTERHUB_SERVICE_PREFIX=/user/alice/alice-waiide-abc123/
JUPYTERHUB_USER=alice
JUPYTERHUB_SERVER_NAME=alice-waiide-abc123 # Full instance name
JUPYTERHUB_API_TOKEN=<oauth-token>
JUPYTERHUB_API_URL=http://hub:8081/hub/apiContainer Configuration:
PORT=8070 # Override main service port
VSCODE_PORT=8071 # Override WAIIDE port
USE_ALL_COMPONENTS=true # Enable all services
LOG_LEVEL=INFO # Logging verbosity🌐 URL Routing & Multi-Instance
Modern Architecture (Current)
- Instance URLs:
https://hub.example.com/user/alice/alice-waiide-abc123/ - WAIIDE URL:
https://hub.example.com/user/alice/alice-waiide-abc123/ide/ - Unique naming:
username-service-hashformat - WAIIDE at /ide: Configured via jupyter-server-proxy
- Multiple instances: Each user can have unlimited instances
Request Flow
Browser → JupyterHub Proxy → Container:8070 → jupyterhub-singleuser
→ jupyter-server-proxy → WAIIDE:8071 → Response🔍 Common Debugging Commands
# Check running mode
docker exec <container> env | grep JUPYTER
# Verify services running
docker exec <container> ps aux | grep -E "(node|jupyter)"
# Check ports
docker exec <container> netstat -tlnp
# View logs
docker logs <container>
# Test API endpoints
curl http://localhost:8070/api/status
curl http://localhost:8070/api/services
# Access container
docker exec -it <container> /bin/bash🐛 Troubleshooting Checklist
Container Issues
- Check if port 8070 is already in use
- Verify Docker network exists (for JupyterHub)
- Ensure image is latest:
docker pull calliopeai/waiide:latest - Check container has sufficient memory (4GB recommended)
JupyterHub Integration
- Verify spawner sets correct environment variables
- Check
JUPYTERHUB_SERVER_NAMEmatches container name - Ensure OAuth scopes include server name for named instances
- Confirm network connectivity between Hub and container
WAIIDE Not Loading
- Wait 15-20 seconds for WAIIDE initialization
- Check WAIIDE process:
ps aux | grep node - Verify internal port 8071 is listening
- Check for JavaScript console errors in browser
🚀 ECS-Specific Issues
Common ECS Boot Errors
1. WAIIDE Server Missing
Error: Cannot find module '/opt/calliope/WAIIDE-server/out/server-main.js'Cause: Incomplete Docker image build or wrong architecture
Fix: Rebuild with --platform linux/amd64 and verify files exist
2. Scripts Missing
cp: cannot stat '/opt/calliope/scripts/jupyter_server_config.py'Cause: Scripts not properly copied during build
Fix: Verify /opt/calliope/scripts/ contains all files
3. Port Conflicts
Common Spawner Misconfiguration:
JUPYTERHUB_PORT=8070
JUPYTERHUB_SERVICE_URL=http://0.0.0.0:8071 # Wrong! Should match PORTSymptom: jupyterhub-singleuser fails with “port already in use”
Fix: Ensure spawner sets JUPYTERHUB_SERVICE_URL to use port 8070 (or whatever PORT is)
Correct Configuration:
# All should use the same main port (8070)
PORT=8070
JUPYTERHUB_PORT=8070
JUPYTERHUB_SERVICE_URL=http://0.0.0.0:8070
# WAIIDE uses different internal port
VSCODE_PORT=80714. File Collision Issues (v2.0)
Symptom:
cp: cannot create directory '/home/lmata/.WAIIDE-server/extensions/log': File existsCause: Extension copying without checking for existing files (v2.0 issue)
Fix in v2.1+:
- Pre-built template at
/opt/calliope/user-template/ - Uses rsync with
--ignore-existingor cp with-n(no-clobber) - Checks for existing directories before copying
Temporary Workaround for v2.0:
# Clear extensions and restart container
rm -rf /home/$USER/.WAIIDE-server/extensions/*5. Missing Built-in Extensions
Symptom:
[Error]: Unable to read file '/opt/calliope/.WAIIDE-server/extensions/clojure/package.json'
[Error]: Unable to read file '/opt/calliope/.WAIIDE-server/extensions/coffeescript/package.json'
... (many similar errors for built-in extensions)Cause: Template copy using --ignore-existing or -n flag prevents extensions from being copied when directory already exists
Fix in v2.2+:
- Extensions are copied separately without no-clobber flag
- Added fallback mechanism to verify and copy missing built-in extensions
- Enhanced extension verification in post-setup debugging
Temporary Workaround:
# Copy extensions manually from system location
cp -rf /opt/calliope/WAIIDE-server/extensions/* /opt/calliope/.WAIIDE-server/extensions/Note about CalliopeAI Agent Extension:
If the calliope-WAIIDE-agent extension error persists, it may not have been built during the Docker image creation. This can happen if:
- The calliope-WAIIDE-agent submodule wasn’t checked out
- The build script failed silently
- The extension wasn’t copied to the runtime image
To verify if the extension exists in the image:
ls -la /opt/calliope/WAIIDE-server/extensions/ | grep calliope6. CI Build Extension Issues
Symptom: Extensions missing in CI-built Docker images, showing errors like:
[Error]: Unable to read file '/opt/calliope/.WAIIDE-server/extensions/markdown-language-features/package.json'
[Error]: Unable to read file '/opt/calliope/.WAIIDE-server/extensions/calliope-WAIIDE-agent/package.json'Cause:
- Extensions not properly built or copied during CI Docker build
- Submodules not fully initialized in CI environment
- Build failures not properly reported
Fix in v2.3+:
- Added verification steps in Dockerfile to check extension copying
- Improved error reporting during build process
- Enhanced template copy mechanism to handle missing extensions
Immediate Workaround:
# Run the extension fix script inside the container
docker exec <container> fix-WAIIDE-extensions
# Or manually copy extensions
docker exec <container> bash -c "cp -rf /opt/calliope/WAIIDE-server/extensions/* /opt/calliope/.WAIIDE-server/extensions/"CI Build Verification: To ensure extensions are included in CI builds:
- Check CI logs for “Copying WAIIDE extensions to build output”
- Verify extension count is > 90
- Look for key extension verification (✓ marks)
ECS Build & Deploy Commands
# Build for ECS (amd64)
docker buildx build --platform linux/amd64 --no-cache -t waiide:ecs .
# Test locally with ECS-like environment
docker run -it --rm \
-e JUPYTERHUB_USER=testuser \
-e JUPYTERHUB_SERVICE_PREFIX=/user/testuser/waiide/ \
-e JUPYTERHUB_SERVICE_URL=http://0.0.0.0:8080/user/testuser/waiide/ \
-e PORT=8080 \
-p 8080:8080 \
waiide:ecs
# Verify critical files exist
docker run -it --rm waiide:ecs find /home -name "server-main.js" -o -name "jupyter_server_config.py"🏃 Quick Start Commands
Standalone Development
# Basic run (uses default ports 8070/8071)
docker run -p 8070:8070 calliopeai/waiide:latest
# With compose.yml (now uses default port 8070)
docker compose up
# Override to use port 8080 if needed
docker run -p 8080:8080 -e PORT=8080 calliopeai/waiide:latestJupyterHub Simulation
docker run -p 8070:8070 \
-e JUPYTERHUB_USER=testuser \
-e JUPYTERHUB_SERVICE_PREFIX=/user/testuser/testuser-waiide-abc123/ \
-e JUPYTERHUB_SERVER_NAME=testuser-waiide-abc123 \
calliopeai/waiide:latest📊 Health Check Endpoints
GET /api- Comprehensive service infoGET /api/status- Basic health checkGET /api/services- Service discovery with ports
🎯 Key Insights for Debugging
- Permission Dance: Container starts as root, fixes ownership, then drops to UID 1000
- Dynamic Home: Home directory set based on
JUPYTERHUB_USERor defaults - Port Flexibility: Main port can be 8070 (default), 8080, or any via PORT env
- OAuth Complexity: Named servers require proper scope configuration
- URL Rewriting: API server handles prefix stripping/adding in standalone mode
🚨 Known Issues
- Documentation Inconsistency: Some docs incorrectly show port 8080 - WAIIDE defaults to 8070
- OAuth with Named Servers: May need manual scope fixes for multi-instance
- Slow Startup (v2.0): Containers stuck in “Created” state for 10+ minutes - fixed in v2.1 with template approach
- Extension Limitations: Many desktop extensions don’t work in web version
- ECS Build Issues: Multi-stage builds may fail silently - always verify image contents
- Port Conflicts: Spawner misconfiguration can cause port conflicts between services
Remember: When debugging, always check the actual running processes and environment variables inside the container rather than relying solely on documentation.