Extension Persistence in WAIIDE

Extension Persistence in WAIIDE

Calliope Integration: This component is integrated into the Calliope AI platform. Some features and configurations may differ from the upstream project.

This document explains how WAIIDE extensions persist across JupyterHub spawns in the WAIIDE environment.

Storage Architecture

WAIIDE uses a hybrid storage model:

/opt/calliope/                    # Container filesystem (ephemeral per spawn)
├── WAIIDE-server/                # Built-in WAIIDE installation
│   └── extensions/               # ✅ PERSISTS (baked into Docker image)
└── .WAIIDE-server/               # WAIIDE runtime data
    ├── extensions/               # ❌ EPHEMERAL (lost on respawn)
    └── data/                     # ❌ EPHEMERAL

/home/{username}/                 # EFS mount (NFS)
└── .WAIIDE-server/               # ✅ PERSISTS (user-installed extensions)
    └── extensions/               # User extensions would go here (if writable)

How Extensions Are Loaded

WAIIDE Server is started with:

--extensions-dir=/opt/calliope/.WAIIDE-server/extensions
--builtin-extensions-dir=/opt/calliope/WAIIDE-server/extensions

This means:

  • Extensions in /opt/calliope/WAIIDE-server/extensions/ are ALWAYS available (built-in)
  • Extensions in /opt/calliope/.WAIIDE-server/extensions/ are available BUT don’t persist
  • User home /home/user/.WAIIDE-server/extensions/ is NOT currently scanned

Extension Persistence Strategies

✅ Strategy 1: Bake into Docker Image (Recommended)

Extensions built into the Docker image at /opt/calliope/WAIIDE-server/extensions/ persist across all spawns.

Implementation:

  1. Add extension source to repository (e.g., calliope-amplifier-extension/)
  2. Add build step to Dockerfile:
    # Build Amplifier extension
    RUN if [ -f "/workspace/scripts/build-amplifier-extension.sh" ]; then \
            ./scripts/build-amplifier-extension.sh; \
        fi
  3. Build script copies to /workspace/WAIIDE/extensions/calliope-amplifier
  4. Extension is included in WAIIDE build output

Pros:

  • Available to all users immediately
  • No per-user setup required
  • Survives container respawns
  • Part of infrastructure as WAIIDE

Cons:

  • Requires Docker rebuild to update
  • Cannot be disabled per-user (easily)
  • Build time increases

❌ Strategy 2: User Home Installation (Not Currently Supported)

Installing to /home/user/.WAIIDE-server/extensions/ would persist on EFS, but WAIIDE Server doesn’t scan this directory with current configuration.

Would require:

  • Changing WAIIDE Server launch parameters
  • OR symlinking from user home to /opt/calliope/.WAIIDE-server/extensions/

⚠️ Strategy 3: Runtime Installation (Temporary Only)

Installing at runtime to /opt/calliope/.WAIIDE-server/extensions/ works for current session but is lost on respawn.

Use case: Testing extensions during development (what we did!)

Current WAIIDE Extensions

Built-in Extensions (Persist)

Located in /opt/calliope/WAIIDE-server/extensions/:

  1. calliope-WAIIDE-agent - CalliopeAI Agent

    • Publisher: calliope-ai
    • Activation: onStartupFinished
  2. claude-WAIIDE-launcher - Claude WAIIDE terminal launcher

    • Publisher: calliope
    • Activation: onCommand:claude-WAIIDE.launch
  3. calliope-amplifier - Amplifier integration (NEW!)

    • Publisher: calliope-ai
    • Activation: onView:amplifier.agents, onCommand:amplifier.*

Extension Metadata Requirements

For extensions to load in WAIIDE Web:

{
  "name": "extension-name",
  "publisher": "calliope-ai",           // Must match existing publisher
  "browser": "./dist/extension.js",     // Web entry point (NOT "main")
  "activationEvents": [
    "onView:viewId",                    // Activate when view loads
    "onCommand:commandId"               // OR when command runs
  ]
}

Important:

  • Use "browser" not "main" for WAIIDE Web
  • Avoid "*" activation (may not work in web)
  • Use "calliope-ai" publisher to match existing extensions

Development Workflow

Testing New Extensions

  1. Build extension locally:

    cd calliope-amplifier-extension
    npm install
    npm run compile
  2. Install to current session:

    mkdir -p /opt/calliope/.WAIIDE-server/extensions/extension-name-version
    cp -r dist package.json src /opt/calliope/.WAIIDE-server/extensions/extension-name-version/
  3. Reload WAIIDE: Ctrl+Shift+P → “Reload Window”

  4. Test functionality

  5. If working, add to Docker build

Adding to Docker Build

  1. Add extension directory to repository root

  2. Create build script:

    # scripts/build-your-extension.sh
    #!/bin/bash
    cd your-extension
    npm install
    npm run compile
    cp -r dist package.json src /workspace/WAIIDE/extensions/your-extension/
  3. Update Dockerfile:

    COPY your-extension /workspace/your-extension
    
    RUN if [ -f "/workspace/scripts/build-your-extension.sh" ]; then \
            chmod +x scripts/build-your-extension.sh && \
            ./scripts/build-your-extension.sh; \
        fi
  4. Rebuild image:

    ./build.sh build

Troubleshooting

Extension Not Loading

Check extension directory:

ls -la /opt/calliope/WAIIDE-server/extensions/your-extension/

Check logs:

tail -100 /opt/calliope/.WAIIDE-server/data/logs/*/exthost*/remoteexthost.log | grep "your-extension"

Look for activation:

ExtensionService#_doActivateExtension publisher.extension-name

Extension Disappears After Respawn

❌ Extension was installed to /opt/calliope/.WAIIDE-server/extensions/ (ephemeral) ✅ Extension must be in /opt/calliope/WAIIDE-server/extensions/ (Docker image)

Wrong Publisher Name

Extensions must use publisher calliope-ai to match existing extensions:

"publisher": "calliope-ai"

Web vs Desktop APIs

Only use web-compatible WAIIDE APIs:

  • WAIIDE.window.createTerminal()
  • WAIIDE.commands.registerCommand()
  • WAIIDE.window.registerTreeDataProvider()
  • fs.readFile() (Node.js API)
  • child_process.spawn() (Node.js API)

Best Practices

  1. Always test locally first before adding to Docker build
  2. Use command-based activation (onCommand, onView) not *
  3. Set publisher to calliope-ai for consistency
  4. Use browser entry point not main
  5. Bundle with webpack for smaller size
  6. Document activation requirements clearly
  7. Include in source control with the WAIIDE repository

References