UNPKG

advanced-live-server-installer

Version:

Auto-installer for Advanced Live Server VS Code Extension

1,049 lines (951 loc) 45.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AISettingsPanel = void 0; const vscode = __importStar(require("vscode")); const ai_config_1 = require("../config/ai-config"); class AISettingsPanel { constructor(context) { this.context = context; this.configManager = new ai_config_1.AIConfigManager(context); // Debug: Log config path on construction console.log('[AISettingsPanel] Config path:', this.configManager.configPath); } show() { if (this.panel) { this.panel.reveal(); return; } this.panel = vscode.window.createWebviewPanel('aiSettings', 'AI Settings - Advanced Live Server', vscode.ViewColumn.One, { enableScripts: true, retainContextWhenHidden: true, }); this.panel.webview.html = this.getWebviewContent(); this.panel.webview.onDidReceiveMessage((message) => this.handleMessage(message)); this.panel.onDidDispose(() => { this.panel = undefined; }); } getWebviewContent() { const config = this.configManager.getConfig(); const providers = [ { value: 'openai', label: 'OpenAI', description: 'GPT-3.5, GPT-4, and other OpenAI models' }, { value: 'ollama', label: 'Ollama', description: 'Local AI models (requires Ollama installation)' }, { value: 'openrouter', label: 'OpenRouter', description: 'Access to multiple AI models through one API' }, { value: 'anthropic', label: 'Anthropic', description: 'Claude models for advanced reasoning' }, { value: 'gemini', label: 'Google Gemini', description: 'Google\'s latest AI models' }, { value: 'cohere', label: 'Cohere', description: 'Command and other Cohere models' }, { value: 'mistral', label: 'Mistral AI', description: 'Mistral 7B and other models' }, { value: 'perplexity', label: 'Perplexity', description: 'Perplexity AI models' }, { value: 'together', label: 'Together AI', description: 'Open source models and fine-tuning' }, { value: 'huggingface', label: 'Hugging Face', description: 'Thousands of open source models' }, { value: 'groq', label: 'Groq', description: 'Ultra-fast inference API' }, { value: 'deepseek', label: 'DeepSeek', description: 'DeepSeek models for coding and reasoning' }, { value: 'fireworks', label: 'Fireworks AI', description: 'Fast and cost-effective AI models' }, { value: 'nomic', label: 'Nomic', description: 'Embeddings and text generation' }, { value: 'custom', label: 'Custom', description: 'Custom API endpoint' }, { value: 'local', label: 'Local', description: 'Basic local analysis (no API key required)' }, ]; const models = this.getModelsForProvider(config.modelConfig.provider); return ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>AI Settings</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: var(--vscode-foreground); background: var(--vscode-editor-background); padding: 20px; } .container { max-width: 800px; margin: 0 auto; } .header { margin-bottom: 30px; text-align: center; } .header h1 { font-size: 2rem; margin-bottom: 10px; color: var(--vscode-textLink-foreground); } .header p { color: var(--vscode-descriptionForeground); } .section { background: var(--vscode-input-background); border: 1px solid var(--vscode-input-border); border-radius: 8px; padding: 20px; margin-bottom: 20px; } .section h2 { font-size: 1.3rem; margin-bottom: 15px; color: var(--vscode-textLink-foreground); } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 5px; font-weight: 600; color: var(--vscode-foreground); } .form-group input, .form-group select, .form-group textarea { width: 100%; padding: 8px 12px; border: 1px solid var(--vscode-input-border); border-radius: 4px; background: var(--vscode-input-background); color: var(--vscode-input-foreground); font-size: 14px; } .form-group select option { background: var(--vscode-dropdown-background); color: var(--vscode-dropdown-foreground); } .form-group input:focus, .form-group select:focus, .form-group textarea:focus { outline: none; border-color: var(--vscode-focusBorder); } .form-group textarea { resize: vertical; min-height: 80px; } .checkbox-group { display: flex; align-items: center; gap: 10px; margin-bottom: 15px; } .checkbox-group input[type="checkbox"] { width: auto; } .provider-option { border: 1px solid var(--vscode-input-border); border-radius: 6px; padding: 15px; margin-bottom: 10px; cursor: pointer; transition: all 0.2s ease; } .provider-option:hover { border-color: var(--vscode-focusBorder); background: var(--vscode-list-hoverBackground); } .provider-option.selected { border-color: var(--vscode-textLink-foreground); background: var(--vscode-list-activeSelectionBackground); } .provider-option input[type="radio"] { margin-right: 10px; } .provider-name { font-weight: 600; margin-bottom: 5px; } .provider-description { font-size: 0.9rem; color: var(--vscode-descriptionForeground); } .button-group { display: flex; gap: 10px; justify-content: flex-end; margin-top: 30px; } .btn { padding: 10px 20px; border: none; border-radius: 4px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; } .btn-primary { background: var(--vscode-button-background); color: var(--vscode-button-foreground); } .btn-primary:hover { background: var(--vscode-button-hoverBackground); } .btn-secondary { background: var(--vscode-button-secondaryBackground); color: var(--vscode-button-secondaryForeground); } .btn-secondary:hover { background: var(--vscode-button-secondaryHoverBackground); } .status { padding: 10px; border-radius: 4px; margin-bottom: 20px; display: none; } .status.success { background: var(--vscode-notificationsInfoBackground); color: var(--vscode-notificationsInfoForeground); border: 1px solid var(--vscode-notificationsInfoBorder); } .status.error { background: var(--vscode-notificationsErrorBackground); color: var(--vscode-notificationsErrorForeground); border: 1px solid var(--vscode-notificationsErrorBorder); } .help-text { font-size: 0.9rem; color: var(--vscode-descriptionForeground); margin-top: 5px; } .api-key-field { position: relative; } .api-key-field input { padding-right: 40px; } .toggle-password { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--vscode-descriptionForeground); cursor: pointer; font-size: 12px; } .model-info { background: var(--vscode-textBlockQuote-background); border-left: 3px solid var(--vscode-textBlockQuote-border); padding: 10px; margin-top: 10px; font-size: 0.9rem; } </style> </head> <body> <div class="container"> <div class="header"> <h1>🤖 AI Settings</h1> <p>Configure AI providers for code analysis, error explanation, and more</p> </div> <div id="status" class="status"></div> <form id="aiSettingsForm"> <div class="section"> <h2>General Settings</h2> <div class="checkbox-group"> <input type="checkbox" id="enabled" ${config.enabled ? 'checked' : ''}> <label for="enabled">Enable AI Features</label> </div> <div class="form-group"> <label for="mode">AI Mode</label> <select id="mode"> <option value="local" ${config.mode === 'local' ? 'selected' : ''}>Local Only</option> <option value="cloud" ${config.mode === 'cloud' ? 'selected' : ''}>Cloud Only</option> <option value="hybrid" ${config.mode === 'hybrid' ? 'selected' : ''}>Hybrid (Local + Cloud)</option> </select> <div class="help-text">Choose how AI features should work</div> </div> </div> <div class="section"> <h2>AI Provider</h2> <div class="help-text">Select your preferred AI provider and configure its settings</div> <div id="providerOptions"> ${providers.map(provider => ` <div class="provider-option ${config.modelConfig.provider === provider.value ? 'selected' : ''}"> <input type="radio" name="provider" value="${provider.value}" id="provider_${provider.value}" ${config.modelConfig.provider === provider.value ? 'checked' : ''}> <label for="provider_${provider.value}"> <div class="provider-name">${provider.label}</div> <div class="provider-description">${provider.description}</div> </label> </div> `).join('')} </div> </div> <div class="section"> <h2>Provider Configuration</h2> <div class="form-group"> <label for="model">Model</label> <div style="display: flex; gap: 10px; align-items: center;"> <select id="model" style="flex: 1;"> ${models.map(model => ` <option value="${model.value}" ${config.modelConfig.model === model.value ? 'selected' : ''}>${model.label}</option> `).join('')} <option value="custom" ${!models.find(m => m.value === config.modelConfig.model) ? 'selected' : ''}>Custom Model</option> </select> <button type="button" class="btn btn-secondary" onclick="refreshOllamaModels()" id="refreshModelsBtn" style="display: none;">🔄 Refresh</button> </div> <div class="help-text">Select a model or choose "Custom Model" to enter your own</div> </div> <div class="form-group" id="customModelGroup" style="display: none;"> <label for="customModel">Custom Model Name</label> <input type="text" id="customModel" value="${config.modelConfig.model}" placeholder="Enter your model name (e.g., gpt-4, claude-3-opus, gemini-pro)"> <div class="help-text">Enter the exact model name from your provider</div> </div> <div class="form-group" id="apiKeyGroup" style="display: ${this.shouldShowApiKey(config.modelConfig.provider) ? 'block' : 'none'};"> <label for="apiKey">API Key</label> <div class="api-key-field"> <input type="password" id="apiKey" value="${config.modelConfig.apiKey || ''}" placeholder="Enter your API key"> <button type="button" class="toggle-password" onclick="togglePassword()">👁️</button> </div> <div class="help-text">Your API key for the selected provider</div> </div> <div class="form-group" id="baseUrlGroup" style="display: ${this.shouldShowBaseUrl(config.modelConfig.provider) ? 'block' : 'none'};"> <label for="baseUrl">Base URL</label> <input type="url" id="baseUrl" value="${config.modelConfig.baseUrl || ''}" placeholder="Enter the base URL"> <div class="help-text">Base URL for the API (leave empty for default)</div> </div> <div class="form-group"> <label for="temperature">Temperature</label> <input type="range" id="temperature" min="0" max="2" step="0.1" value="${config.modelConfig.temperature || 0.7}"> <span id="temperatureValue">${config.modelConfig.temperature || 0.7}</span> <div class="help-text">Controls randomness in responses (0 = focused, 2 = creative)</div> </div> <div class="form-group"> <label for="maxTokens">Max Tokens</label> <input type="number" id="maxTokens" min="100" max="4000" value="${config.modelConfig.maxTokens || 1000}"> <div class="help-text">Maximum number of tokens in the response</div> </div> <div class="form-group"> <label for="timeout">Timeout (ms)</label> <input type="number" id="timeout" min="5000" max="120000" step="1000" value="${config.modelConfig.timeout || 30000}"> <div class="help-text">Request timeout in milliseconds</div> </div> </div> <div class="section"> <h2>Feature Settings</h2> <div class="help-text">Enable or disable specific AI features</div> <div class="checkbox-group"> <input type="checkbox" id="errorExplanation" ${config.errorExplanation ? 'checked' : ''}> <label for="errorExplanation">Error Explanation</label> </div> <div class="checkbox-group"> <input type="checkbox" id="accessibilityAnalysis" ${config.accessibilityAnalysis ? 'checked' : ''}> <label for="accessibilityAnalysis">Accessibility Analysis</label> </div> <div class="checkbox-group"> <input type="checkbox" id="codeImprovements" ${config.codeImprovements ? 'checked' : ''}> <label for="codeImprovements">Code Improvements</label> </div> <div class="checkbox-group"> <input type="checkbox" id="performanceAnalysis" ${config.performanceAnalysis ? 'checked' : ''}> <label for="performanceAnalysis">Performance Analysis</label> </div> <div class="checkbox-group"> <input type="checkbox" id="seoOptimization" ${config.seoOptimization ? 'checked' : ''}> <label for="seoOptimization">SEO Optimization</label> </div> <div class="checkbox-group"> <input type="checkbox" id="securityScan" ${config.securityScan ? 'checked' : ''}> <label for="securityScan">Security Scan</label> </div> </div> <div class="button-group"> <button type="button" class="btn btn-secondary" onclick="testConnection()">Test Connection</button> <button type="button" class="btn btn-secondary" onclick="resetToDefaults()">Reset to Defaults</button> <button type="submit" class="btn btn-primary">Save Settings</button> </div> </form> </div> <script> const vscode = acquireVsCodeApi(); // Provider change handler document.querySelectorAll('input[name="provider"]').forEach(radio => { radio.addEventListener('change', function() { updateProviderOptions(); updateModelOptions(this.value); updateFieldVisibility(this.value); updateCustomModelVisibility(); }); }); // Model change handler document.getElementById('model').addEventListener('change', function() { updateCustomModelVisibility(); }); // Temperature slider const temperatureSlider = document.getElementById('temperature'); const temperatureValue = document.getElementById('temperatureValue'); temperatureSlider.addEventListener('input', function() { temperatureValue.textContent = this.value; }); // Form submission document.getElementById('aiSettingsForm').addEventListener('submit', function(e) { e.preventDefault(); saveSettings(); }); function updateProviderOptions() { document.querySelectorAll('.provider-option').forEach(option => { option.classList.remove('selected'); }); const selectedRadio = document.querySelector('input[name="provider"]:checked'); if (selectedRadio) { selectedRadio.closest('.provider-option').classList.add('selected'); } } function updateModelOptions(provider) { const modelSelect = document.getElementById('model'); const models = getModelsForProvider(provider); modelSelect.innerHTML = models.map(model => \`<option value="\${model.value}">\${model.label}</option>\` ).join(''); } function updateFieldVisibility(provider) { const apiKeyGroup = document.getElementById('apiKeyGroup'); const baseUrlGroup = document.getElementById('baseUrlGroup'); const refreshBtn = document.getElementById('refreshModelsBtn'); const needsApiKey = ['openai', 'anthropic', 'gemini', 'cohere', 'mistral', 'perplexity', 'together', 'huggingface', 'openrouter', 'groq', 'deepseek', 'fireworks', 'nomic', 'custom'].includes(provider); const needsBaseUrl = ['ollama', 'local', 'custom'].includes(provider); const isOllama = provider === 'ollama'; apiKeyGroup.style.display = needsApiKey ? 'block' : 'none'; baseUrlGroup.style.display = needsBaseUrl ? 'block' : 'none'; refreshBtn.style.display = isOllama ? 'block' : 'none'; } function updateCustomModelVisibility() { const modelSelect = document.getElementById('model'); const customModelGroup = document.getElementById('customModelGroup'); if (modelSelect.value === 'custom') { customModelGroup.style.display = 'block'; } else { customModelGroup.style.display = 'none'; } } function getModelsForProvider(provider) { const modelMap = { openai: [ { value: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo' }, { value: 'gpt-3.5-turbo-16k', label: 'GPT-3.5 Turbo 16K' }, { value: 'gpt-4', label: 'GPT-4' }, { value: 'gpt-4-turbo', label: 'GPT-4 Turbo' }, { value: 'gpt-4o', label: 'GPT-4o' } ], ollama: [ { value: 'llama2', label: 'Llama 2' }, { value: 'llama2:13b', label: 'Llama 2 13B' }, { value: 'llama2:70b', label: 'Llama 2 70B' }, { value: 'codellama', label: 'Code Llama' }, { value: 'mistral', label: 'Mistral' }, { value: 'gemma', label: 'Gemma' }, { value: 'phi', label: 'Phi' } ], openrouter: [ { value: 'openai/gpt-3.5-turbo', label: 'OpenAI GPT-3.5 Turbo' }, { value: 'openai/gpt-4', label: 'OpenAI GPT-4' }, { value: 'anthropic/claude-3-opus', label: 'Anthropic Claude 3 Opus' }, { value: 'anthropic/claude-3-sonnet', label: 'Anthropic Claude 3 Sonnet' }, { value: 'google/gemini-pro', label: 'Google Gemini Pro' }, { value: 'meta-llama/llama-2-70b-chat', label: 'Meta Llama 2 70B' }, { value: 'mistralai/mistral-7b-instruct', label: 'Mistral 7B Instruct' } ], anthropic: [ { value: 'claude-3-opus-20240229', label: 'Claude 3 Opus' }, { value: 'claude-3-sonnet-20240229', label: 'Claude 3 Sonnet' }, { value: 'claude-3-haiku-20240307', label: 'Claude 3 Haiku' }, { value: 'claude-2.1', label: 'Claude 2.1' }, { value: 'claude-2.0', label: 'Claude 2.0' } ], gemini: [ { value: 'gemini-pro', label: 'Gemini Pro' }, { value: 'gemini-pro-vision', label: 'Gemini Pro Vision' } ], cohere: [ { value: 'command', label: 'Command' }, { value: 'command-light', label: 'Command Light' }, { value: 'command-nightly', label: 'Command Nightly' } ], mistral: [ { value: 'mistral-tiny', label: 'Mistral Tiny' }, { value: 'mistral-small', label: 'Mistral Small' }, { value: 'mistral-medium', label: 'Mistral Medium' }, { value: 'mistral-large', label: 'Mistral Large' } ], perplexity: [ { value: 'llama-2-70b-chat', label: 'Llama 2 70B Chat' }, { value: 'codellama-34b-instruct', label: 'Code Llama 34B Instruct' }, { value: 'mixtral-8x7b-instruct', label: 'Mixtral 8x7B Instruct' }, { value: 'mistral-7b-instruct', label: 'Mistral 7B Instruct' } ], together: [ { value: 'togethercomputer/llama-2-70b-chat', label: 'Llama 2 70B Chat' }, { value: 'togethercomputer/llama-2-13b-chat', label: 'Llama 2 13B Chat' }, { value: 'togethercomputer/falcon-40b-chat', label: 'Falcon 40B Chat' }, { value: 'togethercomputer/falcon-7b-chat', label: 'Falcon 7B Chat' } ], huggingface: [ { value: 'gpt2', label: 'GPT-2' }, { value: 'microsoft/DialoGPT-medium', label: 'DialoGPT Medium' }, { value: 'EleutherAI/gpt-neo-125M', label: 'GPT-Neo 125M' } ], groq: [ { value: 'llama2-70b-4096', label: 'Llama 2 70B' }, { value: 'mixtral-8x7b-32768', label: 'Mixtral 8x7B' }, { value: 'gemma-7b-it', label: 'Gemma 7B' } ], deepseek: [ { value: 'deepseek-chat', label: 'DeepSeek Chat' }, { value: 'deepseek-coder', label: 'DeepSeek Coder' } ], fireworks: [ { value: 'accounts/fireworks/models/llama-v2-7b-chat', label: 'Llama v2 7B Chat' }, { value: 'accounts/fireworks/models/llama-v2-13b-chat', label: 'Llama v2 13B Chat' }, { value: 'accounts/fireworks/models/llama-v2-70b-chat', label: 'Llama v2 70B Chat' } ], nomic: [ { value: 'nomic-embed-text-v1', label: 'Nomic Embed Text v1' }, { value: 'nomic-embed-text-v1.5', label: 'Nomic Embed Text v1.5' } ], custom: [ { value: 'custom', label: 'Custom Model' } ], local: [ { value: 'local', label: 'Local Analysis' } ] }; return modelMap[provider] || [{ value: 'default', label: 'Default' }]; } function togglePassword() { const apiKeyInput = document.getElementById('apiKey'); const toggleButton = document.querySelector('.toggle-password'); if (apiKeyInput.type === 'password') { apiKeyInput.type = 'text'; toggleButton.textContent = '🙈'; } else { apiKeyInput.type = 'password'; toggleButton.textContent = '👁️'; } } function saveSettings() { // Show immediate feedback showStatus('Saving settings...', 'success'); // Get the actual model name let modelName = document.getElementById('model').value; if (modelName === 'custom') { modelName = document.getElementById('customModel').value; } const formData = { enabled: document.getElementById('enabled').checked, mode: document.getElementById('mode').value, provider: document.querySelector('input[name="provider"]:checked').value, model: modelName, apiKey: document.getElementById('apiKey').value, baseUrl: document.getElementById('baseUrl').value, temperature: parseFloat(document.getElementById('temperature').value), maxTokens: parseInt(document.getElementById('maxTokens').value), timeout: parseInt(document.getElementById('timeout').value), errorExplanation: document.getElementById('errorExplanation').checked, accessibilityAnalysis: document.getElementById('accessibilityAnalysis').checked, codeImprovements: document.getElementById('codeImprovements').checked, performanceAnalysis: document.getElementById('performanceAnalysis').checked, seoOptimization: document.getElementById('seoOptimization').checked, securityScan: document.getElementById('securityScan').checked }; vscode.postMessage({ command: 'saveSettings', data: formData }); } function testConnection() { // Show immediate feedback showStatus('Testing connection...', 'success'); const provider = document.querySelector('input[name="provider"]:checked').value; const apiKey = document.getElementById('apiKey').value; const baseUrl = document.getElementById('baseUrl').value; const model = document.getElementById('model').value; vscode.postMessage({ command: 'testConnection', data: { provider, apiKey, baseUrl, model } }); } function resetToDefaults() { if (confirm('Are you sure you want to reset all settings to defaults?')) { // Show immediate feedback showStatus('Resetting to defaults...', 'success'); vscode.postMessage({ command: 'resetToDefaults' }); } } function showStatus(message, type = 'success') { const status = document.getElementById('status'); status.textContent = message; status.className = \`status \${type}\`; status.style.display = 'block'; setTimeout(() => { status.style.display = 'none'; }, 5000); } // Listen for messages from the extension window.addEventListener('message', event => { const message = event.data; switch (message.command) { case 'showStatus': showStatus(message.message, message.type); break; } }); async function refreshOllamaModels() { showStatus('Fetching Ollama models...', 'success'); const baseUrl = document.getElementById('baseUrl').value || 'http://localhost:11434'; try { const response = await fetch(\`\${baseUrl}/api/tags\`); if (!response.ok) { throw new Error(\`HTTP \${response.status}: \${response.statusText}\`); } const data = await response.json(); const models = data.models || []; if (models.length === 0) { showStatus('No models found in Ollama. Make sure Ollama is running and you have models installed.', 'error'); return; } // Update the model select with detected models const modelSelect = document.getElementById('model'); const currentValue = modelSelect.value; // Clear existing options except "Custom Model" const customOption = modelSelect.querySelector('option[value="custom"]'); modelSelect.innerHTML = ''; // Add detected models models.forEach(model => { const option = document.createElement('option'); option.value = model.name; option.textContent = \`\${model.name} (\${(model.size / 1024 / 1024 / 1024).toFixed(1)}GB)\`; modelSelect.appendChild(option); }); // Add back the custom option if (customOption) { modelSelect.appendChild(customOption); } // Try to restore the previous selection if (currentValue && currentValue !== 'custom') { const option = modelSelect.querySelector(\`option[value="\${currentValue}"]\`); if (option) { option.selected = true; } } showStatus(\`Found \${models.length} Ollama models!\`, 'success'); } catch (error) { console.error('Failed to fetch Ollama models:', error); showStatus(\`Failed to fetch Ollama models: \${error.message}\`, 'error'); } } // Initialize updateFieldVisibility('${config.modelConfig.provider}'); updateCustomModelVisibility(); </script> </body> </html> `; } shouldShowApiKey(provider) { return ['openai', 'anthropic', 'gemini', 'cohere', 'mistral', 'perplexity', 'together', 'huggingface', 'openrouter', 'groq', 'deepseek', 'fireworks', 'nomic', 'custom'].includes(provider); } shouldShowBaseUrl(provider) { return ['ollama', 'local', 'custom'].includes(provider); } getModelsForProvider(provider) { const modelMap = { openai: [ { value: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo' }, { value: 'gpt-3.5-turbo-16k', label: 'GPT-3.5 Turbo 16K' }, { value: 'gpt-4', label: 'GPT-4' }, { value: 'gpt-4-turbo', label: 'GPT-4 Turbo' }, { value: 'gpt-4o', label: 'GPT-4o' } ], ollama: [ { value: 'llama2', label: 'Llama 2' }, { value: 'llama2:13b', label: 'Llama 2 13B' }, { value: 'llama2:70b', label: 'Llama 2 70B' }, { value: 'codellama', label: 'Code Llama' }, { value: 'mistral', label: 'Mistral' }, { value: 'gemma', label: 'Gemma' }, { value: 'phi', label: 'Phi' } ], openrouter: [ { value: 'openai/gpt-3.5-turbo', label: 'OpenAI GPT-3.5 Turbo' }, { value: 'openai/gpt-4', label: 'OpenAI GPT-4' }, { value: 'anthropic/claude-3-opus', label: 'Anthropic Claude 3 Opus' }, { value: 'anthropic/claude-3-sonnet', label: 'Anthropic Claude 3 Sonnet' }, { value: 'google/gemini-pro', label: 'Google Gemini Pro' }, { value: 'meta-llama/llama-2-70b-chat', label: 'Meta Llama 2 70B' }, { value: 'mistralai/mistral-7b-instruct', label: 'Mistral 7B Instruct' } ], anthropic: [ { value: 'claude-3-opus-20240229', label: 'Claude 3 Opus' }, { value: 'claude-3-sonnet-20240229', label: 'Claude 3 Sonnet' }, { value: 'claude-3-haiku-20240307', label: 'Claude 3 Haiku' }, { value: 'claude-2.1', label: 'Claude 2.1' }, { value: 'claude-2.0', label: 'Claude 2.0' } ], gemini: [ { value: 'gemini-pro', label: 'Gemini Pro' }, { value: 'gemini-pro-vision', label: 'Gemini Pro Vision' } ], cohere: [ { value: 'command', label: 'Command' }, { value: 'command-light', label: 'Command Light' }, { value: 'command-nightly', label: 'Command Nightly' } ], mistral: [ { value: 'mistral-tiny', label: 'Mistral Tiny' }, { value: 'mistral-small', label: 'Mistral Small' }, { value: 'mistral-medium', label: 'Mistral Medium' }, { value: 'mistral-large', label: 'Mistral Large' } ], perplexity: [ { value: 'llama-2-70b-chat', label: 'Llama 2 70B Chat' }, { value: 'codellama-34b-instruct', label: 'Code Llama 34B Instruct' }, { value: 'mixtral-8x7b-instruct', label: 'Mixtral 8x7B Instruct' }, { value: 'mistral-7b-instruct', label: 'Mistral 7B Instruct' } ], together: [ { value: 'togethercomputer/llama-2-70b-chat', label: 'Llama 2 70B Chat' }, { value: 'togethercomputer/llama-2-13b-chat', label: 'Llama 2 13B Chat' }, { value: 'togethercomputer/falcon-40b-chat', label: 'Falcon 40B Chat' }, { value: 'togethercomputer/falcon-7b-chat', label: 'Falcon 7B Chat' } ], huggingface: [ { value: 'gpt2', label: 'GPT-2' }, { value: 'microsoft/DialoGPT-medium', label: 'DialoGPT Medium' }, { value: 'EleutherAI/gpt-neo-125M', label: 'GPT-Neo 125M' } ], groq: [ { value: 'llama2-70b-4096', label: 'Llama 2 70B' }, { value: 'mixtral-8x7b-32768', label: 'Mixtral 8x7B' }, { value: 'gemma-7b-it', label: 'Gemma 7B' } ], deepseek: [ { value: 'deepseek-chat', label: 'DeepSeek Chat' }, { value: 'deepseek-coder', label: 'DeepSeek Coder' } ], fireworks: [ { value: 'accounts/fireworks/models/llama-v2-7b-chat', label: 'Llama v2 7B Chat' }, { value: 'accounts/fireworks/models/llama-v2-13b-chat', label: 'Llama v2 13B Chat' }, { value: 'accounts/fireworks/models/llama-v2-70b-chat', label: 'Llama v2 70B Chat' } ], nomic: [ { value: 'nomic-embed-text-v1', label: 'Nomic Embed Text v1' }, { value: 'nomic-embed-text-v1.5', label: 'Nomic Embed Text v1.5' } ], custom: [ { value: 'custom', label: 'Custom Model' } ], local: [ { value: 'local', label: 'Local Analysis' } ] }; return modelMap[provider] || [{ value: 'default', label: 'Default' }]; } async handleMessage(message) { console.log('[AISettingsPanel] Received message:', message); switch (message.command) { case 'saveSettings': console.log('[AISettingsPanel] Handling saveSettings'); await this.saveSettings(message.data); break; case 'testConnection': console.log('[AISettingsPanel] Handling testConnection'); await this.testConnection(message.data); break; case 'resetToDefaults': console.log('[AISettingsPanel] Handling resetToDefaults'); await this.resetToDefaults(); break; default: console.log('[AISettingsPanel] Unknown command:', message.command); } } async saveSettings(data) { try { console.log('[AISettingsPanel] saveSettings called with:', data); this.configManager.updateConfig({ enabled: data.enabled, mode: data.mode, errorExplanation: data.errorExplanation, accessibilityAnalysis: data.accessibilityAnalysis, codeImprovements: data.codeImprovements, performanceAnalysis: data.performanceAnalysis, seoOptimization: data.seoOptimization, securityScan: data.securityScan, }); this.configManager.updateModelConfig({ provider: data.provider, model: data.model, apiKey: data.apiKey, baseUrl: data.baseUrl, temperature: data.temperature, maxTokens: data.maxTokens, timeout: data.timeout, }); // Debug: Log after saving console.log('[AISettingsPanel] Settings saved.'); this.showStatus('Settings saved successfully!', 'success'); // Refresh the panel to show updated values if (this.panel) { this.panel.webview.html = this.getWebviewContent(); } } catch (error) { console.error('[AISettingsPanel] Failed to save settings:', error); this.showStatus(`Failed to save settings: ${error}`, 'error'); } } async testConnection(data) { try { // Create a temporary config for testing const testConfig = { provider: data.provider, model: data.model, apiKey: data.apiKey, baseUrl: data.baseUrl, temperature: 0.7, maxTokens: 100, timeout: 10000, }; // Test the connection based on provider let success = false; let error = ''; switch (data.provider) { case 'openai': success = await this.testOpenAIConnection(testConfig); break; case 'ollama': success = await this.testOllamaConnection(testConfig); break; case 'openrouter': success = await this.testOpenRouterConnection(testConfig); break; case 'local': success = true; // Local always works break; default: error = 'Provider not implemented for testing'; } if (success) { this.showStatus('Connection test successful!', 'success'); } else { this.showStatus(`Connection test failed: ${error}`, 'error'); } } catch (error) { this.showStatus(`Connection test failed: ${error}`, 'error'); } } async testOpenAIConnection(config) { try { const response = await fetch(`${config.baseUrl || 'https://api.openai.com/v1'}/models`, { method: 'GET', headers: { 'Authorization': `Bearer ${config.apiKey}`, }, }); return response.ok; } catch { return false; } } async testOllamaConnection(config) { try { const response = await fetch(`${config.baseUrl || 'http://localhost:11434'}/api/tags`, { method: 'GET', }); return response.ok; } catch { return false; } } async testOpenRouterConnection(config) { try { const response = await fetch(`${config.baseUrl || 'https://openrouter.ai/api/v1'}/models`, { method: 'GET', headers: { 'Authorization': `Bearer ${config.apiKey}`, }, }); return response.ok; } catch { return false; } } async resetToDefaults() { try { this.configManager.updateConfig({ enabled: false, mode: 'local', errorExplanation: true, accessibilityAnalysis: true, codeImprovements: true, performanceAnalysis: false, seoOptimization: false, securityScan: false, }); this.configManager.updateModelConfig({ provider: 'openai', model: 'gpt-3.5-turbo', temperature: 0.7, maxTokens: 1000, timeout: 30000, }); this.showStatus('Settings reset to defaults!', 'success'); // Reload the panel if (this.panel) { this.panel.webview.html = this.getWebviewContent(); } } catch (error) { this.showStatus(`Failed to reset settings: ${error}`, 'error'); } } showStatus(message, type) { if (this.panel) { this.panel.webview.postMessage({ command: 'showStatus', message, type }); } } } exports.AISettingsPanel = AISettingsPanel; //# sourceMappingURL=ai-settings-panel.js.map