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/extensionsThis 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:
- Add extension source to repository (e.g.,
calliope-amplifier-extension/) - Add build step to Dockerfile:
# Build Amplifier extension RUN if [ -f "/workspace/scripts/build-amplifier-extension.sh" ]; then \ ./scripts/build-amplifier-extension.sh; \ fi - Build script copies to
/workspace/WAIIDE/extensions/calliope-amplifier - 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/:
calliope-WAIIDE-agent - CalliopeAI Agent
- Publisher:
calliope-ai - Activation:
onStartupFinished
- Publisher:
claude-WAIIDE-launcher - Claude WAIIDE terminal launcher
- Publisher:
calliope - Activation:
onCommand:claude-WAIIDE.launch
- Publisher:
calliope-amplifier - Amplifier integration (NEW!)
- Publisher:
calliope-ai - Activation:
onView:amplifier.agents,onCommand:amplifier.*
- Publisher:
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
Build extension locally:
cd calliope-amplifier-extension npm install npm run compileInstall 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/Reload WAIIDE:
Ctrl+Shift+P→ “Reload Window”Test functionality
If working, add to Docker build
Adding to Docker Build
Add extension directory to repository root
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/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; \ fiRebuild 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-nameExtension 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
- Always test locally first before adding to Docker build
- Use command-based activation (
onCommand,onView) not* - Set publisher to
calliope-aifor consistency - Use
browserentry point notmain - Bundle with webpack for smaller size
- Document activation requirements clearly
- Include in source control with the WAIIDE repository