Skip to main content
  • Component: Web UI Packaging System
  • Module: installer/ directory
  • Source: installer/

Related: Electron Integration, NSIS Installer

Overview

The Web UI Packaging System is GAIA’s infrastructure for creating standalone desktop applications from Python-based web UIs. It combines Electron packaging, embedded Python distribution, and NSIS Windows installers to deliver turnkey AI applications. Key Features:
  • Python embedding (no system Python required)
  • Electron-based desktop app generation
  • NSIS installer creation
  • Multi-app support (Jira, Chat, Docker)
  • Automatic dependency installation

Requirements

Functional Requirements

  1. Python Embedding
    • Download Python embedded distribution (3.10.9)
    • Install pip in embedded environment
    • Configure site-packages access
    • Install GAIA and dependencies
  2. File Packaging
    • Exclude development files (.git, .pyc)
    • Include installer scripts
    • Package GAIA source code
    • Create bin directory structure
  3. Dependency Management
    • Handle package installations
    • Support optional dependencies
    • Manage version compatibility
    • Track installation failures
  4. Post-Install Configuration
    • PATH environment updates
    • Desktop shortcut creation
    • Launch script installation
    • Optional component installation (RAUX)

Non-Functional Requirements

  1. Reliability
    • Robust error handling
    • Installation logging
    • Retry logic for downloads
    • Cleanup on failure
  2. Performance
    • Parallel downloads where possible
    • Progress indication
    • Timeout management
    • Efficient file operations
  3. User Experience
    • Silent install mode support
    • Clear progress messages
    • Error reporting
    • Manual fallback options

System Architecture

Component Diagram

┌─────────────────────────────────────────────────────────┐
│                   NSIS Installer                         │
│                  (Installer.nsi)                         │
└────────────────────┬────────────────────────────────────┘

        ┌────────────┴───────────┐
        │                        │
┌───────▼──────────┐    ┌────────▼──────────┐
│ Python Embedding │    │  GAIA Packaging   │
│   (install.bat)  │    │  (File Layout)    │
└──────────────────┘    └────────┬──────────┘

                    ┌────────────┴───────────┐
                    │                        │
           ┌────────▼─────────┐    ┌────────▼─────────┐
           │ Launch Scripts   │    │  Electron Apps   │
           │ (launch_gaia.bat)│    │  (src/gaia/apps) │
           └──────────────────┘    └──────────────────┘

Directory Structure

gaia-windows-setup.exe (NSIS installer)

    └─→ Extract to: $LOCALAPPDATA\GAIA\
            ├── bin/
            │   └── launch_gaia.bat
            ├── python/
            │   ├── python.exe (embedded)
            │   ├── Scripts/
            │   │   ├── pip.exe
            │   │   └── gaia.exe
            │   └── Lib/site-packages/
            ├── src/
            │   └── gaia/
            │       ├── apps/
            │       │   ├── jira/webui/
            │       │   ├── chat/webui/
            │       │   └── docker/webui/
            │       └── electron/
            │           ├── package.json
            │           └── src/main.js
            └── installer/
                ├── install.bat
                ├── launch_gaia.bat
                └── installer_utils.py

API Specification

install.bat

Purpose: Install GAIA package in embedded Python environment Parameters:
  • %1: Path to python.exe
  • %2: Installation directory
Process:
@echo off
setlocal

set PYTHON_EXE=%1
set INSTALL_DIR=%2

REM Upgrade pip
"%PYTHON_EXE%" -m pip install --upgrade pip

REM Install GAIA with all extras
"%PYTHON_EXE%" -m pip install -e "%INSTALL_DIR%\src\gaia[dev,rag,jira]"

REM Check installation
"%PYTHON_EXE%" -c "import gaia; print(gaia.__version__)"

exit /b 0
Exit Codes:
  • 0: Success
  • 1: Python executable not found
  • 2: Pip upgrade failed
  • 3: GAIA installation failed
  • 4: Verification failed

launch_gaia.bat

Purpose: Launch GAIA CLI with embedded Python Parameters:
  • --cli: Launch CLI mode
  • --app <name>: Launch specific app
  • All other args passed to GAIA
Process:
@echo off
setlocal EnableDelayedExpansion

set GAIA_DIR=%~dp0..
set PYTHON_EXE=%GAIA_DIR%\python\python.exe
set GAIA_CLI=%GAIA_DIR%\python\Scripts\gaia.exe

REM Check for --cli flag
if "%1"=="--cli" (
    start "GAIA CLI" "%PYTHON_EXE%" -m gaia %2 %3 %4 %5
    exit /b 0
)

REM Default: Pass all args to GAIA
"%GAIA_CLI%" %*
exit /b %ERRORLEVEL%

installer_utils.py

Purpose: Utility functions for installer validation Key Functions:
def check_version_compatibility(
    expected_version: str,
    actual_version: str
) -> tuple[bool, str]:
    """
    Compare version strings for major.minor compatibility.

    Args:
        expected_version: Expected version (e.g., "8.0.1")
        actual_version: Actual version output

    Returns:
        (is_compatible, extracted_version)
    """
    pass

def get_lemonade_version() -> str:
    """
    Get lemonade-server version.

    Returns:
        Version string or None if not installed
    """
    pass

Implementation Details

Python Embedding Process

Step 1: Download Embedded Python
# NSIS uses curl
url = "https://www.python.org/ftp/python/3.10.9/python-3.10.9-embed-amd64.zip"
output = "$INSTDIR\python\python.zip"
Step 2: Extract and Configure
# Extract zip
powershell -Command "Expand-Archive -Path 'python.zip' -DestinationPath 'python'"

# Modify python310._pth to enable site-packages
FileOpen $2 "$INSTDIR\python\python310._pth" a
FileSeek $2 0 END
FileWrite $2 "$\r$\nLib$\r$\n"
FileWrite $2 "$\r$\nLib\site-packages$\r$\n"
FileClose $2
Step 3: Install pip
# Download get-pip.py
curl -sSL "https://bootstrap.pypa.io/get-pip.py" -o "python\get-pip.py"

# Install pip
python\python.exe python\get-pip.py --no-warn-script-location

Package Installation Strategy

Priority 1: Core Dependencies
# Must succeed
pip install --upgrade pip setuptools wheel packaging
Priority 2: GAIA Package
# Install with extras
pip install -e "src/gaia[dev,rag,jira]"

# Extras breakdown:
# - dev: Development tools (pytest, black, etc.)
# - rag: Document retrieval (faiss, sentence-transformers)
# - jira: Jira integration (aiohttp)
Priority 3: Optional Components
# Non-blocking installs
pip install watchdog  # File monitoring
pip install ffmpeg-python  # Audio processing

Error Handling

Network Failures:
ExecWait 'curl --retry 3 --retry-delay 2 -o "$TEMP\file" "$URL"' $0
${If} $0 != 0
    DetailPrint "Download failed, attempting mirror..."
    ExecWait 'curl -o "$TEMP\file" "$MIRROR_URL"' $0
${EndIf}
Installation Failures:
REM install.bat error handling
pip install -e "." >gaia_install.log 2>&1
if %ERRORLEVEL% NEQ 0 (
    echo ERROR: Installation failed. See gaia_install.log
    exit /b 3
)

Testing Requirements

Unit Tests

File: tests/installer/test_installer_utils.py
import pytest
from installer.installer_utils import check_version_compatibility

def test_version_compatibility_exact_match():
    """Test exact version match."""
    result, version = check_version_compatibility("8.0.1", "8.0.1")
    assert result is True
    assert version == "8.0.1"

def test_version_compatibility_minor_mismatch():
    """Test minor version mismatch."""
    result, version = check_version_compatibility("8.0.1", "8.1.0")
    assert result is False

def test_version_compatibility_patch_ok():
    """Test patch version difference is acceptable."""
    result, version = check_version_compatibility("8.0.1", "8.0.2")
    assert result is True
    assert version == "8.0.2"

def test_version_with_prefix():
    """Test version with 'v' prefix."""
    result, version = check_version_compatibility("v8.0.1", "8.0.1")
    assert result is True

def test_version_extraction_from_output():
    """Test extracting version from command output."""
    output = "Lemonade Server v8.0.1 (build 12345)"
    result, version = check_version_compatibility("8.0.1", output)
    assert result is True
    assert version == "8.0.1"

Integration Tests

Manual Test Procedure:
  1. Clean Install Test
    # Remove existing installation
    Remove-Item -Recurse -Force "$env:LOCALAPPDATA\GAIA"
    
    # Run installer
    .\gaia-windows-setup.exe /S
    
    # Verify installation
    & "$env:LOCALAPPDATA\GAIA\python\Scripts\gaia.exe" --version
    
  2. Upgrade Test
    # Install version A
    .\gaia-windows-setup-v1.0.0.exe /S
    
    # Install version B (should replace)
    .\gaia-windows-setup-v1.1.0.exe /S
    
    # Verify upgrade
    & "$env:LOCALAPPDATA\GAIA\python\Scripts\gaia.exe" --version
    
  3. Silent Install Test
    # Silent install with log
    Start-Process -Wait -FilePath "gaia-windows-setup.exe" -ArgumentList "/S /D=C:\CustomPath\GAIA"
    
    # Verify custom path
    Test-Path "C:\CustomPath\GAIA\python\python.exe"
    
  4. PATH Verification Test
    # Check PATH contains bin and Scripts
    $env:PATH -split ";" | Where-Object { $_ -like "*GAIA*" }
    
    # Test command availability
    Get-Command gaia -ErrorAction Stop
    
  5. Launch Script Test
    # Test CLI launch
    & "$env:LOCALAPPDATA\GAIA\bin\launch_gaia.bat" --cli --help
    
    # Test direct command
    & "$env:LOCALAPPDATA\GAIA\bin\launch_gaia.bat" --version
    

Dependencies

Build Dependencies

# Build machine requirements
[build-requires]
nsis = ">=3.08"  # NSIS compiler
curl = "*"  # File downloads
powershell = ">=5.1"  # Archive extraction

Runtime Dependencies

# Embedded in installer
[runtime-embedded]
python = "3.10.9"  # Embedded distribution
pip = ">=23.0"  # Package installer
setuptools = "*"  # Package tools
wheel = "*"  # Wheel format support

Optional Dependencies

; Optional components
lemonade-server = "8.0.x"  # LLM inference server
ffmpeg = "*"  # Audio processing

Configuration

NSIS Build Variables

; installer/Installer.nsi
!define PYTHON_VERSION "3.10.9"
!define PYTHON_EMBED_URL "https://www.python.org/ftp/python/3.10.9/python-3.10.9-embed-amd64.zip"
!define GET_PIP_URL "https://bootstrap.pypa.io/get-pip.py"
!define LEMONADE_VERSION "8.0.4"
!define RAUX_VERSION "v0.6.5+raux.0.2.4"

Environment Variables

Installer Sets:
PATH = $INSTDIR\bin;$INSTDIR\python\Scripts;%PATH%
GAIA_HOME = $INSTDIR
User Can Set:
GAIA_APP_NAME = jira|chat|docker  # App to launch
GAIA_APP_MODE = production|development  # Run mode

Usage Examples

Example 1: Building Installer

# Install NSIS
winget install NSIS.NSIS

# Set version
$version = "1.0.0"
echo "!define GAIA_VERSION `"$version`"" > installer/version.nsh

# Build installer
makensis installer/Installer.nsi

# Output: gaia-windows-setup.exe

Example 2: Silent Deployment

# Enterprise deployment script
$installerUrl = "https://releases.gaia.ai/gaia-windows-setup.exe"
$installerPath = "$env:TEMP\gaia-setup.exe"

# Download installer
Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath

# Install silently to standard location
Start-Process -Wait -FilePath $installerPath -ArgumentList "/S"

# Verify installation
if (Test-Path "$env:LOCALAPPDATA\GAIA\python\Scripts\gaia.exe") {
    Write-Host "✓ GAIA installed successfully"
} else {
    Write-Error "Installation failed"
    exit 1
}

# Cleanup
Remove-Item $installerPath

Example 3: Custom Installation Path

# Install to custom directory
$customPath = "D:\MyApps\GAIA"

Start-Process -Wait -FilePath "gaia-windows-setup.exe" `
    -ArgumentList "/S", "/D=$customPath"

# Update PATH for custom location
$env:PATH = "$customPath\bin;$customPath\python\Scripts;$env:PATH"

# Test
gaia --version

Error Handling

Common Errors

Error: Python download failed
DetailPrint "ERROR: Failed to download Python"
MessageBox MB_OK "Network error: Could not download Python. Check internet connection."
Quit
Error: Pip installation failed
REM install.bat
echo ERROR: Pip installation failed
echo Check gaia_install.log for details
exit /b 2
Error: GAIA package not found
REM install.bat
if not exist "%INSTALL_DIR%\src\gaia\setup.py" (
    echo ERROR: GAIA source not found at %INSTALL_DIR%\src\gaia
    exit /b 3
)

Recovery Procedures

Incomplete Installation:
# Manual cleanup
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\GAIA"

# Re-run installer
.\gaia-windows-setup.exe
PATH Not Updated:
# Manual PATH update
$gaiaPath = "$env:LOCALAPPDATA\GAIA"
[Environment]::SetEnvironmentVariable(
    "Path",
    "$gaiaPath\bin;$gaiaPath\python\Scripts;" + $env:PATH,
    [EnvironmentVariableTarget]::User
)

Documentation Updates Required

installer/README.md

Add packaging documentation:
# GAIA Installer System

This directory contains the Windows installer packaging system.

## Building the Installer

1. Install NSIS 3.08 or later
2. Set version in `version.nsh`
3. Run: `makensis Installer.nsi`
4. Output: `gaia-windows-setup.exe`

## Installer Components

- **Installer.nsi**: Main NSIS script
- **install.bat**: Python package installation
- **launch_gaia.bat**: GAIA launch wrapper
- **installer_utils.py**: Version checking utilities

## Testing

See `docs/spec/web-ui-packaging.md` for complete test procedures.

Acceptance Criteria

  • Installer creates embedded Python environment
  • GAIA package installs with all dependencies
  • Launch scripts work from any directory
  • PATH updated correctly in user environment
  • Desktop shortcuts created
  • Silent install mode works
  • Custom install path supported
  • Installation logs created
  • Error messages clear and actionable
  • Uninstaller removes all files
  • Upgrade preserves user data
  • Version checking prevents conflicts


Web UI Packaging System Technical Specification