# 🎨 HTML/Frontend Extensions Architecture ## Overview This document defines the **client-side extension system** for Chat Switchboard. Extensions are HTML/JS/CSS modules that can hook into the application lifecycle, add UI elements, intercept messages, and extend functionality. --- ## 🔌 Extension Interface ### Extension Manifest Structure ```javascript { "id": "example-extension", "name": "Example Extension", "version": "1.0.0", "author": "Your Name", "description": "Does something cool", "type": "frontend", // or "hybrid" if it has backend components "permissions": ["ui", "messages", "storage"], "entrypoint": "extension.js", "styles": "extension.css", "hooks": { "onLoad": true, "onMessageSend": true, "onMessageReceive": true, "onModelSwitch": true }, "ui": { "toolbar": true, "sidebar": false, "settings": true } } ``` --- ## 📦 Extension API ### Core Extension Class ```javascript class ChatSwitchboardExtension { constructor(manifest) { this.manifest = manifest; this.enabled = true; } // Lifecycle hooks onLoad() {} onUnload() {} onEnable() {} onDisable() {} // Message hooks async onMessageSend(message, context) { // Modify message before sending // return modified message or null to cancel return message; } async onMessageReceive(message, context) { // Process received message // return modified message or original return message; } async onMessageDisplay(message, element) { // Modify message DOM before display return element; } // UI hooks onModelSwitch(oldModel, newModel) {} onChatSwitch(oldChatId, newChatId) {} onSettingsOpen() {} // Render hooks renderToolbarButton() { // Return HTML string or DOM element return null; } renderSidebarPanel() { return null; } renderSettingsPanel() { return null; } renderMessageAction(message) { // Add custom actions to message bubbles return null; } } ``` --- ## 🎯 Extension Categories ### 1. **UI Extensions** Add visual elements and interface enhancements. **Examples:** - Syntax highlighter themes - Message templates/snippets - Custom emoji pickers - Voice input buttons - Image/file attachments **Hooks:** `renderToolbarButton`, `renderSidebarPanel`, `renderMessageAction` --- ### 2. **Message Processors** Transform messages before/after sending. **Examples:** - Markdown preprocessor - Code formatter - Translation layer - Prompt templates - Token counter **Hooks:** `onMessageSend`, `onMessageReceive`, `onMessageDisplay` --- ### 3. **Model Extensions** Enhance model selection and routing. **Examples:** - Model performance stats - Cost calculator - Context window manager - Model recommendation engine - Fallback routing (if model fails, try another) **Hooks:** `onModelSwitch`, access to `State.settings.model` --- ### 4. **Storage Extensions** Extend data persistence capabilities. **Examples:** - Cloud sync (S3, Dropbox) - Export formats (PDF, DOCX) - Search indexing - Tagging system - Chat organization **Permissions:** `storage` --- ### 5. **Tool/Function Extensions** Enable LLM function calling (critical for your use case). **Examples:** - Web search tool - Calculator - Code execution sandbox - API caller - File system access **Hooks:** `onFunctionCall`, `registerFunction` --- ## 🛠️ Extension Manager ### Core API ```javascript // Global extension registry window.ExtensionManager = { extensions: new Map(), // Register an extension register(manifest, ExtensionClass) { const ext = new ExtensionClass(manifest); this.extensions.set(manifest.id, ext); ext.onLoad(); return ext; }, // Enable/disable enable(id) {}, disable(id) {}, unload(id) {}, // Hook execution async executeHook(hookName, ...args) { const results = []; for (const [id, ext] of this.extensions) { if (ext.enabled && ext[hookName]) { const result = await ext[hookName](...args); results.push({ id, result }); } } return results; }, // Get all extensions with specific capability getByPermission(permission) { return Array.from(this.extensions.values()) .filter(ext => ext.manifest.permissions.includes(permission)); } }; ``` --- ## 📂 Extension File Structure ``` extensions/ ├── example-extension/ │ ├── manifest.json │ ├── extension.js │ ├── extension.css (optional) │ ├── README.md │ └── assets/ │ └── icon.svg ``` ### Loading Extensions ```javascript async function loadExtension(path) { const manifest = await fetch(`${path}/manifest.json`).then(r => r.json()); // Load JS const module = await import(`${path}/${manifest.entrypoint}`); // Load CSS if present if (manifest.styles) { const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = `${path}/${manifest.styles}`; document.head.appendChild(link); } // Register ExtensionManager.register(manifest, module.default); } ``` --- ## 🔐 Security & Permissions ### Permission System ```javascript const PERMISSIONS = { ui: "Modify user interface", messages: "Read and modify messages", storage: "Access local storage", network: "Make network requests", settings: "Access user settings", clipboard: "Access clipboard", notifications: "Show notifications" }; ``` ### Sandboxing (Future) - Use iframes for untrusted extensions - Content Security Policy restrictions - API key scoping (extensions can't access main API key) --- ## 🎨 Example Extensions ### 1. Token Counter ```javascript class TokenCounterExtension extends ChatSwitchboardExtension { onLoad() { this.tokenCount = 0; } renderToolbarButton() { return ` `; } async onMessageSend(message, context) { // Rough estimation: 1 token ≈ 4 chars this.tokenCount = Math.ceil(message.content.length / 4); document.getElementById('tokenCount').textContent = this.tokenCount; return message; } } ``` ### 2. Code Formatter ```javascript class CodeFormatterExtension extends ChatSwitchboardExtension { async onMessageDisplay(message, element) { if (message.role === 'assistant') { // Find code blocks and apply Prism.js highlighting element.querySelectorAll('pre code').forEach(block => { Prism.highlightElement(block); }); } return element; } renderMessageAction(message) { if (message.content.includes('```')) { return ` `; } return null; } } ``` ### 3. Model Router (Smart Fallback) ```javascript class ModelRouterExtension extends ChatSwitchboardExtension { async onMessageSend(message, context) { // If message is long, use high-context model if (message.content.length > 5000) { const originalModel = State.settings.model; State.settings.model = 'claude-3-opus-20240229'; // High context // Restore after response context.onComplete = () => { State.settings.model = originalModel; }; } return message; } } ``` --- ## 🚀 Integration with App ### Modify `app.js` to support hooks: ```javascript async function sendMessage() { // ... existing code ... // Execute hook before sending const hookResults = await ExtensionManager.executeHook( 'onMessageSend', message, { chatId: State.currentChatId } ); // Check if any extension cancelled the send if (hookResults.some(r => r.result === null)) { return; } // Apply transformations for (const { result } of hookResults) { if (result && result !== message) { message = result; } } // ... continue with API call ... } ``` --- ## 📋 Extension Discovery ### Extension Store (Future) ```javascript { "extensions": [ { "id": "web-search", "name": "Web Search Tool", "description": "Adds web search capability via function calling", "author": "Chat Switchboard Team", "version": "1.0.0", "downloadUrl": "https://extensions.switchboard/web-search.zip", "verified": true, "rating": 4.8, "downloads": 1250 } ] } ``` --- ## 🎯 Next Steps 1. **Implement ExtensionManager** in `src/js/extensions.js` 2. **Add hook points** to existing code (app.js, ui.js, api.js) 3. **Create example extensions** to validate API 4. **Build extension settings UI** for enable/disable/configure 5. **Document extension development** with starter template --- ## 🤝 Extension Development Workflow ```bash # Create new extension mkdir extensions/my-extension cd extensions/my-extension # Generate manifest cat > manifest.json << EOF { "id": "my-extension", "name": "My Extension", "version": "1.0.0", "entrypoint": "extension.js", "permissions": ["messages"] } EOF # Create extension class cat > extension.js << EOF class MyExtension extends ChatSwitchboardExtension { onLoad() { console.log('My extension loaded!'); } } export default MyExtension; EOF # Test in dev mode # Extensions auto-load from /extensions/ directory ``` --- **This architecture makes Chat Switchboard infinitely extensible while keeping the core lean.**