{"repo": "c-hri-sw-u/rotfix", "files": {"model-configuration.js": {"bbf70b9e566ec0d17b793e082461325bbb9af5b9": {"t": 1785746009.6426818, "n": 31395, "h": "29a94b6f5c4a8cbd", "c": "// Model Configuration Management\n// Based on Swift code ServiceProvider and APITestService implementation\n\n// Service provider configuration (based on Swift ServiceProvider enum)\nconst ServiceProviders = {\n openAI: {\n name: 'OpenAI',\n value: 'openAI',\n defaultApiUrl: 'https://api.openai.com/v1',\n suggestedModels: ['gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano', 'gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo'],\n modelCharacteristics: {\n 'gpt-4.1': { maxTokens: 32768, temperature: 0.3, hasImageCapability: true, contextWindow: 1000000, pricing: '$2.00/1M input, $8.00/1M output' },\n 'gpt-4.1-mini': { maxTokens: 16384, temperature: 0.3, hasImageCapability: true, contextWindow: 1000000, pricing: '$0.40/1M input, $1.60/1M output' },\n 'gpt-4.1-nano': { maxTokens: 8192, temperature: 0.3, hasImageCapability: false, contextWindow: 500000, pricing: '$0.10/1M input, $0.40/1M output' },\n 'gpt-4o': { maxTokens: 4000, temperature: 0.3, hasImageCapability: false, speciality: 'Advanced reasoning and complex problem solving' },\n 'gpt-4o-mini': { maxTokens: 2000, temperature: 0.3, hasImageCapability: true },\n 'gpt-4-turbo': { maxTokens: 4000, temperature: 0.3, hasImageCapability: true }\n }\n },\n // claude: {\n // name: 'Claude',\n // value: 'claude',\n // defaultApiUrl: 'https://api.anthropic.com/v1',\n // suggestedModels: ['claude-opus-4-20250514', 'claude-sonnet-4-20250514', 'claude-3-7-sonnet-latest', 'claude-3-5-haiku-latest', 'claude-3-5-sonnet-latest', 'claude-3-5-sonnet-20240620', 'claude-3-haiku-20240307'],\n // modelCharacteristics: {\n // 'claude-opus-4-20250514': { maxTokens: 4000, temperature: 0.3, hasImageCapability: true, contextWindow: 200000, speciality: 'Highest capability with advanced agentic features' },\n // 'claude-sonnet-4-20250514': { maxTokens: 3000, temperature: 0.3, hasImageCapability: true, contextWindow: 200000, speciality: 'Balanced capability and speed with code execution' },\n // 'claude-3-7-sonnet-latest': { maxTokens: 3000, temperature: 0.3, hasImageCapability: true, contextWindow: 200000, speciality: 'Hybrid reasoning modes and Claude Code beta' },\n // 'claude-3-5-haiku-latest': { maxTokens: 3000, temperature: 0.3, hasImageCapability: true, contextWindow: 200000, speciality: 'Enhanced coding and Artifacts feature' },\n // 'claude-3-5-sonnet-latest': { maxTokens: 3000, temperature: 0.3, hasImageCapability: true, contextWindow: 200000, speciality: 'Enhanced coding and Artifacts feature' },\n // 'claude-3-5-sonnet-20240620': { maxTokens: 3000, temperature: 0.3, hasImageCapability: true, contextWindow: 200000, speciality: 'Enhanced coding and Artifacts feature' },\n // 'claude-3-haiku-20240307': { maxTokens: 2000, temperature: 0.3, hasImageCapability: true, contextWindow: 200000, speciality: 'Speed optimized' }\n // }\n // },\n gemini: {\n name: 'Gemini',\n value: 'gemini',\n defaultApiUrl: 'https://generativelanguage.googleapis.com/v1beta/models',\n suggestedModels: ['gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.5-flash-lite-preview-06-17', 'gemini-2.0-flash', 'gemini-2.0-flash-lite'],\n modelCharacteristics: {\n 'gemini-2.5-pro': { maxTokens: 8000, temperature: 0.3, hasImageCapability: true, contextWindow: 1000000, speciality: 'Multimodal with advanced coding capabilities' },\n 'gemini-2.5-flash': { maxTokens: 2000, temperature: 0.3, hasImageCapability: true, contextWindow: 1000000, speciality: 'Fast inference with multimodal support' },\n 'gemini-2.5-flash-lite-preview-06-17': { maxTokens: 4000, temperature: 0.3, hasImageCapability: true, contextWindow: 128000 },\n 'gemini-2.0-flash': { maxTokens: 1000, temperature: 0.3, hasImageCapability: true, contextWindow: 128000 },\n 'gemini-2.0-flash-lite': { maxTokens: 1000, temperature: 0.3, hasImageCapability: true, contextWindow: 128000 }\n }\n },\n deepSeek: {\n name: 'DeepSeek',\n value: 'deepSeek',\n defaultApiUrl: 'https://api.deepseek.com/v1',\n suggestedModels: ['deepseek-reasoner', 'deepseek-chat'],\n modelCharacteristics: {\n 'deepseek-reasoner': { maxTokens: 4000, temperature: 0.3, hasImageCapability: false, contextWindow: 128000, speciality: 'Specialized for coding tasks' },\n 'deepseek-chat': { maxTokens: 1000, temperature: 0.3, hasImageCapability: false, contextWindow: 128000 }\n }\n },\n xAI: {\n name: 'xAI',\n value: 'xai',\n defaultApiUrl: 'https://api.x.ai/v1',\n suggestedModels: ['grok-3', 'grok-2', 'grok-1.5'],\n modelCharacteristics: {\n 'grok-3': { maxTokens: 4000, temperature: 0.3, hasImageCapability: true, speciality: 'Real-time information access and witty personality' },\n 'grok-2': { maxTokens: 3000, temperature: 0.3, hasImageCapability: true, speciality: 'Improved reasoning and image understanding' },\n 'grok-1.5': { maxTokens: 2000, temperature: 0.3, hasImageCapability: false, speciality: 'Fast inference with humor' }\n }\n },\n meta: {\n name: 'Meta',\n value: 'meta',\n defaultApiUrl: 'https://api.llama-api.com/v1',\n suggestedModels: ['llama-4', 'llama-3.3-70b', 'llama-3.2-90b', 'llama-3.1-405b'],\n modelCharacteristics: {\n 'llama-4': { maxTokens: 8000, temperature: 0.3, hasImageCapability: true, speciality: 'Latest generation with improved reasoning' },\n 'llama-3.3-70b': { maxTokens: 4000, temperature: 0.3, hasImageCapability: false, contextWindow: 128000, speciality: 'Optimized 70B parameter model' },\n 'llama-3.2-90b': { maxTokens: 4000, temperature: 0.3, hasImageCapability: true, contextWindow: 128000 },\n 'llama-3.1-405b': { maxTokens: 8000, temperature: 0.3, hasImageCapability: false, contextWindow: 128000, speciality: 'Largest open-source model' }\n }\n },\n qwen: {\n name: 'Qwen',\n value: 'qwen',\n defaultApiUrl: 'https://dashscope.aliyuncs.com/api/v1',\n suggestedModels: ['qwen-3', 'qwen-2.5-72b', 'qwen-2.5-32b', 'qwen-2.5-14b'],\n modelCharacteristics: {\n 'qwen-3': { maxTokens: 8000, temperature: 0.3, hasImageCapability: true, speciality: 'Latest generation with multimodal capabilities' },\n 'qwen-2.5-72b': { maxTokens: 4000, temperature: 0.3, hasImageCapability: true, contextWindow: 128000 },\n 'qwen-2.5-32b': { maxTokens: 3000, temperature: 0.3, hasImageCapability: false, contextWindow: 32000 },\n 'qwen-2.5-14b': { maxTokens: 2000, temperature: 0.3, hasImageCapability: false, contextWindow: 32000 }\n }\n },\n mistral: {\n name: 'Mistral',\n value: 'mistral',\n defaultApiUrl: 'https://api.mistral.ai/v1',\n suggestedModels: ['mistral-large-2', 'mixtral-8x22b', 'mistral-medium', 'mistral-small'],\n modelCharacteristics: {\n 'mistral-large-2': { maxTokens: 4000, temperature: 0.3, hasImageCapability: false, contextWindow: 128000, speciality: 'Latest flagship model' },\n 'mixtral-8x22b': { maxTokens: 4000, temperature: 0.3, hasImageCapability: false, contextWindow: 64000, speciality: 'Mixture of Experts architecture' },\n 'mistral-medium': { maxTokens: 3000, temperature: 0.3, hasImageCapability: false, contextWindow: 32000 },\n 'mistral-small': { maxTokens: 2000, temperature: 0.3, hasImageCapability: false, contextWindow: 32000 }\n }\n },\n};\n\n// Current configuration state\nlet currentConfig = {\n provider: null,\n model: null,\n apiUrl: '',\n apiKey: '',\n maxTokens: 2000,\n temperature: 0.3,\n multiRounds: 5,\n multiRoundsEnabled: false\n};\n\n// Initialize model configuration\nfunction initializeModelConfiguration() {\n console.log('[ModelConfig] ๐ Initializing model configuration interface');\n \n // Get DOM elements\n const providerSelect = document.querySelector('.config-grid .config-item:nth-child(1) .config-select');\n const modelSelect = document.querySelector('.config-grid .config-item:nth-child(2) .config-select');\n const apiUrlInput = document.getElementById('api-url');\n const apiKeyInput = document.getElementById('api-key');\n const maxTokensInput = document.querySelector('.config-grid .config-item:nth-child(5) .config-input');\n const temperatureInput = document.querySelector('.config-grid .config-item:nth-child(6) .config-input');\n const multiRoundsInput = document.getElementById('multi-rounds');\n const multiRoundsToggle = document.getElementById('multi-rounds-toggle');\n const saveTestButton = document.querySelector('.model-config-header .btn-small');\n \n // Populate Provider selector\n populateProviderSelect(providerSelect);\n \n // Bind event listeners\n providerSelect.addEventListener('change', handleProviderChange);\n modelSelect.addEventListener('change', handleModelChange);\n apiUrlInput.addEventListener('input', handleApiUrlChange);\n apiKeyInput.addEventListener('input', handleApiKeyChange);\n maxTokensInput.addEventListener('input', handleMaxTokensChange);\n temperatureInput.addEventListener('input', handleTemperatureChange);\n multiRoundsInput.addEventListener('input', handleMultiRoundsChange);\n \n // Add input filter for multi-rounds to only allow numbers\n multiRoundsInput.addEventListener('keypress', function(event) {\n // Only allow numbers, backspace, delete, arrow keys\n if (!/[0-9]/.test(event.key) && \n !['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab'].includes(event.key)) {\n event.preventDefault();\n }\n });\n \n saveTestButton.addEventListener('click', handleSaveAndTest);\n \n console.log('[ModelConfig] โ
Model configuration initialization complete');\n}\n\n// Populate Provider selector\nfunction populateProviderSelect(selectElement) {\n console.log('[ModelConfig] ๐ Populating Provider selector');\n \n // Clear existing options\n selectElement.innerHTML = '';\n \n // Add all provider options\n Object.values(ServiceProviders).forEach(provider => {\n const option = document.createElement('option');\n option.value = provider.value;\n option.textContent = provider.name;\n selectElement.appendChild(option);\n });\n}\n\n// Populate Model selector\nfunction populateModelSelect(selectElement, providerValue) {\n console.log('[ModelConfig] ๐ Populating Model selector, Provider:', providerValue);\n \n // Clear existing options\n selectElement.innerHTML = '';\n \n if (providerValue && ServiceProviders[providerValue]) {\n const provider = ServiceProviders[providerValue];\n provider.suggestedModels.forEach(model => {\n const option = document.createElement('option');\n option.value = model;\n option.textContent = model;\n selectElement.appendChild(option);\n });\n }\n}\n\n// Handle Provider change\nfunction handleProviderChange(event) {\n const providerValue = event.target.value;\n console.log('[ModelConfig] ๐ Provider selection changed:', providerValue);\n \n currentConfig.provider = providerValue;\n \n // Update Model selector\n const modelSelect = document.querySelector('.config-grid .config-item:nth-child(2) .config-select');\n populateModelSelect(modelSelect, providerValue);\n \n // Auto-fill API URL\n if (providerValue && ServiceProviders[providerValue]) {\n const provider = ServiceProviders[providerValue];\n const apiUrlInput = document.getElementById('api-url');\n apiUrlInput.value = provider.defaultApiUrl;\n currentConfig.apiUrl = provider.defaultApiUrl;\n console.log('[ModelConfig] ๐ Auto-filled API URL:', provider.defaultApiUrl);\n }\n \n // Reset Model selection and image capability\n currentConfig.model = null;\n modelSelect.value = '';\n const imageCapabilityInput = document.getElementById('image-capability');\n if (imageCapabilityInput) {\n imageCapabilityInput.value = 'false';\n }\n \n // Auto-save configuration\n // ่ชๅจไฟๅญ้
็ฝฎ\n saveConfiguration();\n}\n\n// Handle Model change\nfunction handleModelChange(event) {\n const modelValue = event.target.value;\n console.log('[ModelConfig] ๐ Model selection changed:', modelValue);\n \n currentConfig.model = modelValue;\n \n // Auto-set recommended maxTokens and temperature\n if (currentConfig.provider && modelValue) {\n const provider = ServiceProviders[currentConfig.provider];\n const characteristics = provider.modelCharacteristics[modelValue];\n \n if (characteristics) {\n const maxTokensInput = document.querySelector('.config-grid .config-item:nth-child(5) .config-input');\n const temperatureInput = document.querySelector('.config-grid .config-item:nth-child(6) .config-input');\n const imageCapabilityInput = document.getElementById('image-capability');\n \n maxTokensInput.value = characteristics.maxTokens;\n temperatureInput.value = characteristics.temperature;\n imageCapabilityInput.value = characteristics.hasImageCapability.toString();\n \n currentConfig.maxTokens = characteristics.maxTokens;\n currentConfig.temperature = characteristics.temperature;\n \n console.log('[ModelConfig] โ๏ธ Auto-set parameters - MaxTokens:', characteristics.maxTokens, 'Temperature:', characteristics.temperature, 'Image Capability:', characteristics.hasImageCapability);\n }\n } else {\n // Reset image capability when no model selected\n const imageCapabilityInput = document.getElementById('image-capability');\n if (imageCapabilityInput) {\n imageCapabilityInput.value = 'false';\n }\n }\n \n // Auto-save configuration\n // ่ชๅจไฟๅญ้
็ฝฎ\n saveConfiguration();\n}\n\n// Handle API URL change\nfunction handleApiUrlChange(event) {\n currentConfig.apiUrl = event.target.value;\n console.log('[ModelConfig] ๐ API URL updated:', currentConfig.apiUrl);\n \n // Auto-save configuration\n // ่ชๅจไฟๅญ้
็ฝฎ\n saveConfiguration();\n}\n\n// Handle API Key change\nfunction handleApiKeyChange(event) {\n currentConfig.apiKey = event.target.value;\n const maskedKey = currentConfig.apiKey.length > 6 ? \n currentConfig.apiKey.substring(0, 6) + '...' : currentConfig.apiKey;\n console.log('[ModelConfig] ๐ API Key updated (first 6 chars):', maskedKey);\n \n // Auto-save configuration\n // ่ชๅจไฟๅญ้
็ฝฎ\n saveConfiguration();\n}\n\n// Handle Max Tokens change\nfunction handleMaxTokensChange(event) {\n currentConfig.maxTokens = parseInt(event.target.value) || 1000;\n console.log('[ModelConfig] ๐ข Max Tokens updated:', currentConfig.maxTokens);\n \n // Auto-save configuration\n // ่ชๅจไฟๅญ้
็ฝฎ\n saveConfiguration();\n}\n\n// Handle Temperature change\nfunction handleTemperatureChange(event) {\n currentConfig.temperature = parseFloat(event.target.value) || 0.3;\n console.log('[ModelConfig] ๐ก๏ธ Temperature updated:', currentConfig.temperature);\n \n // Auto-save configuration\n // ่ชๅจไฟๅญ้
็ฝฎ\n saveConfiguration();\n}\n\n// Handle Multi-Rounds change\nfunction handleMultiRoundsChange(event) {\n // Only handle changes if multi-rounds is enabled\n if (!currentConfig.multiRoundsEnabled) {\n return;\n }\n \n let value = parseInt(event.target.value);\n \n // Validate range (2-30)\n if (isNaN(value) || value < 2) {\n value = 2;\n event.target.value = value;\n } else if (value > 30) {\n value = 30;\n event.target.value = value;\n } else {\n // Valid number, update the input to clean format\n event.target.value = value;\n }\n \n currentConfig.multiRounds = value;\n console.log('[ModelConfig] ๐ Multi-Rounds updated:', currentConfig.multiRounds);\n \n // Update short history management max rounds\n if (currentConfig.multiRoundsEnabled && typeof window.ShortHistory !== 'undefined') {\n window.ShortHistory.updateMaxRounds(value);\n }\n \n // Auto-save configuration\n // ่ชๅจไฟๅญ้
็ฝฎ\n saveConfiguration();\n}\n\n// Handle Multi-Rounds toggle\nfunction toggleMultiRounds(enabled) {\n currentConfig.multiRoundsEnabled = enabled;\n \n const multiRoundsInput = document.getElementById('multi-rounds');\n if (enabled) {\n multiRoundsInput.disabled = false;\n multiRoundsInput.value = currentConfig.multiRounds || 5;\n console.log('[ModelConfig] โ
Multi-Rounds enabled:', currentConfig.multiRounds);\n \n // Enable short history management\n if (typeof window.ShortHistory !== 'undefined') {\n window.ShortHistory.enableMultiRound(currentConfig.multiRounds || 5);\n }\n } else {\n multiRoundsInput.disabled = true;\n multiRoundsInput.value = '--';\n console.log('[ModelConfig] โ Multi-Rounds disabled');\n \n // Disable short history management\n if (typeof window.ShortHistory !== 'undefined') {\n window.ShortHistory.disableMultiRound();\n }\n }\n \n // Auto-save configuration\n // ่ชๅจไฟๅญ้
็ฝฎ\n saveConfiguration();\n}\n\n// Make toggleMultiRounds globally accessible\nwindow.toggleMultiRounds = toggleMultiRounds;\n\n// Handle Save & Test button click\nasync function handleSaveAndTest() {\n console.log('[ModelConfig] ๐ Starting save and test configuration');\n console.log('[ModelConfig] ๐ Current configuration:', currentConfig);\n \n // Validate configuration completeness\n if (!validateConfiguration()) {\n return;\n }\n \n // Save configuration\n saveConfiguration();\n \n // Execute API test\n await testApiConfiguration();\n}\n\n// Validate configuration completeness\nfunction validateConfiguration() {\n console.log('[ModelConfig] ๐ Validating configuration completeness');\n \n if (!currentConfig.provider) {\n console.error('[ModelConfig] โ Provider not selected');\n alert('Please select Provider');\n return false;\n }\n \n if (!currentConfig.model) {\n console.error('[ModelConfig] โ Model not selected');\n alert('Please select Model');\n return false;\n }\n \n if (!currentConfig.apiUrl) {\n console.error('[ModelConfig] โ API URL is empty');\n alert('Please fill in API URL');\n return false;\n }\n \n if (!currentConfig.apiKey) {\n console.error('[ModelConfig] โ API Key is empty');\n alert('Please fill in API Key');\n return false;\n }\n \n console.log('[ModelConfig] โ
Configuration validation passed');\n return true;\n}\n\n// Save configuration to localStorage\nfunction saveConfiguration() {\n console.log('[ModelConfig] ๐พ Saving configuration to localStorage');\n \n try {\n localStorage.setItem('modelConfiguration', JSON.stringify(currentConfig));\n console.log('[ModelConfig] โ
Configuration saved successfully');\n } catch (error) {\n console.error('[ModelConfig] โ Configuration save failed:', error);\n }\n}\n\n// Load configuration from localStorage\nfunction loadConfiguration() {\n console.log('[ModelConfig] ๐ Loading configuration from localStorage');\n \n try {\n const savedConfig = localStorage.getItem('modelConfiguration');\n if (savedConfig) {\n const parsedConfig = JSON.parse(savedConfig);\n // Merge configuration, keeping defaults\n currentConfig = { ...currentConfig, ...parsedConfig };\n \n // Update UI\n updateUIFromConfig();\n \n console.log('[ModelConfig] โ
Configuration loaded successfully:', currentConfig);\n }\n } catch (error) {\n console.error('[ModelConfig] โ Configuration load failed:', error);\n }\n}\n\n// Update UI based on configuration\nfunction updateUIFromConfig() {\n console.log('[ModelConfig] ๐จ Updating UI based on configuration');\n \n // Update Provider selector\n const providerSelect = document.querySelector('.config-grid .config-item:nth-child(1) .config-select');\n if (providerSelect && currentConfig.provider) {\n providerSelect.value = currentConfig.provider;\n \n // Trigger Model selector update\n const modelSelect = document.querySelector('.config-grid .config-item:nth-child(2) .config-select');\n populateModelSelect(modelSelect, currentConfig.provider);\n \n if (currentConfig.model) {\n modelSelect.value = currentConfig.model;\n }\n }\n \n // Update other input fields\n const apiUrlInput = document.getElementById('api-url');\n const apiKeyInput = document.getElementById('api-key');\n const maxTokensInput = document.querySelector('.config-grid .config-item:nth-child(5) .config-input');\n const temperatureInput = document.querySelector('.config-grid .config-item:nth-child(6) .config-input');\n const multiRoundsInput = document.getElementById('multi-rounds');\n const multiRoundsToggle = document.getElementById('multi-rounds-toggle');\n \n if (apiUrlInput) apiUrlInput.value = currentConfig.apiUrl || '';\n if (apiKeyInput) apiKeyInput.value = currentConfig.apiKey || '';\n if (maxTokensInput) maxTokensInput.value = currentConfig.maxTokens || 1000;\n if (temperatureInput) temperatureInput.value = currentConfig.temperature || 0.3;\n \n // Update multi-rounds toggle and input\n if (multiRoundsToggle) {\n multiRoundsToggle.checked = currentConfig.multiRoundsEnabled || false;\n }\n if (multiRoundsInput) {\n if (currentConfig.multiRoundsEnabled) {\n multiRoundsInput.disabled = false;\n multiRoundsInput.value = currentConfig.multiRounds || 5;\n \n // Enable short history management if enabled\n if (typeof window.ShortHistory !== 'undefined') {\n window.ShortHistory.enableMultiRound(currentConfig.multiRounds || 5);\n }\n } else {\n multiRoundsInput.disabled = true;\n multiRoundsInput.value = '--';\n \n // Disable short history management if disabled\n if (typeof window.ShortHistory !== 'undefined') {\n window.ShortHistory.disableMultiRound();\n }\n }\n }\n}\n\n// API test functionality (based on Swift APITestService)\nasync function testApiConfiguration() {\n console.log('[ModelConfig] ๐งช Starting API test');\n console.log('[ModelConfig] ๐งช Test parameters:');\n console.log(' - Provider:', currentConfig.provider);\n console.log(' - Model:', currentConfig.model);\n console.log(' - API URL:', currentConfig.apiUrl);\n console.log(' - API Key (first 6 chars):', currentConfig.apiKey.substring(0, 6) + '...');\n \n try {\n const startTime = Date.now();\n \n let testResult = false;\n \n // Route to corresponding test function based on provider\n switch (currentConfig.provider) {\n case 'openAI':\n testResult = await testOpenAIAPI();\n break;\n case 'claude':\n testResult = await testClaudeAPI();\n break;\n case 'gemini':\n testResult = await testGeminiAPI();\n break;\n case 'deepSeek':\n testResult = await testDeepSeekAPI();\n break;\n\n default:\n console.error('[ModelConfig] โ Unsupported Provider:', currentConfig.provider);\n return;\n }\n \n const endTime = Date.now();\n const duration = (endTime - startTime) / 1000;\n \n console.log('[ModelConfig] ๐งช API test complete');\n console.log(' - Duration:', duration.toFixed(2) + ' seconds');\n console.log(' - Result:', testResult ? 'โ
Success' : 'โ Failed');\n \n // Display test result\n if (testResult) {\n alert('API test successful!');\n } else {\n alert('API test failed, please check configuration and network connection. See console for details.');\n }\n \n } catch (error) {\n console.error('[ModelConfig] โ API test exception:', error);\n alert('API test exception: ' + error.message);\n }\n}\n\n// OpenAI API test\nasync function testOpenAIAPI() {\n console.log('[ModelConfig] ๐ Starting OpenAI API test');\n \n const fullUrl = `${currentConfig.apiUrl}/chat/completions`;\n console.log('[ModelConfig] ๐ Complete request URL:', fullUrl);\n \n const requestBody = {\n model: currentConfig.model,\n messages: [\n { role: \"user\", content: \"Hi\" }\n ],\n max_tokens: 1 // Minimum token consumption\n };\n \n console.log('[ModelConfig] ๐ Request body:', JSON.stringify(requestBody, null, 2));\n \n try {\n const response = await fetch(fullUrl, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${currentConfig.apiKey}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(requestBody)\n });\n \n console.log('[ModelConfig] ๐ HTTP status code:', response.status);\n console.log('[ModelConfig] ๐ Response headers:', Object.fromEntries(response.headers.entries()));\n \n const responseText = await response.text();\n console.log('[ModelConfig] ๐ Response body:', responseText);\n \n return response.ok;\n \n } catch (error) {\n console.error('[ModelConfig] โ OpenAI test error:', error);\n return false;\n }\n}\n\n// Claude API test\nasync function testClaudeAPI() {\n console.log('[ModelConfig] ๐ฃ Starting Claude API test');\n \n // Due to CORS limitations with Claude API, we'll perform configuration validation instead\n console.log('[ModelConfig] ๐ฃ Note: Claude API testing is limited by CORS policy in browsers');\n console.log('[ModelConfig] ๐ฃ Performing configuration validation instead of live API test');\n \n // Validate API key format (Claude API keys start with 'sk-ant-')\n if (!currentConfig.apiKey.startsWith('sk-ant-')) {\n console.error('[ModelConfig] โ Invalid Claude API key format - should start with \"sk-ant-\"');\n return false;\n }\n \n // Validate API URL\n if (!currentConfig.apiUrl.includes('anthropic.com')) {\n console.error('[ModelConfig] โ Invalid Claude API URL - should contain \"anthropic.com\"');\n return false;\n }\n \n // Validate model exists in our configuration\n const provider = ServiceProviders[currentConfig.provider];\n if (!provider.suggestedModels.includes(currentConfig.model)) {\n console.error('[ModelConfig] โ Invalid model selection for Claude');\n return false;\n }\n \n // Validate other parameters\n if (currentConfig.maxTokens < 1 || currentConfig.maxTokens > 4096) {\n console.error('[ModelConfig] โ Invalid max tokens - should be between 1 and 4096');\n return false;\n }\n \n if (currentConfig.temperature < 0 || currentConfig.temperature > 1) {\n console.error('[ModelConfig] โ Invalid temperature - should be between 0 and 1');\n return false;\n }\n \n console.log('[ModelConfig] ๐ฃ โ
Configuration validation passed');\n console.log('[ModelConfig] ๐ฃ โ
API key format is valid');\n console.log('[ModelConfig] ๐ฃ โ
API URL is valid');\n console.log('[ModelConfig] ๐ฃ โ
Model selection is valid');\n console.log('[ModelConfig] ๐ฃ โ
Parameters are within valid ranges');\n console.log('[ModelConfig] ๐ฃ Note: For actual API connectivity testing, use a server-side implementation');\n \n return true;\n}\n\n// Gemini API test\nasync function testGeminiAPI() {\n console.log('[ModelConfig] ๐ข Starting Gemini API test');\n \n const fullUrl = `${currentConfig.apiUrl}/${currentConfig.model}:generateContent?key=${currentConfig.apiKey}`;\n console.log('[ModelConfig] ๐ข Complete request URL:', fullUrl);\n \n const requestBody = {\n contents: [\n {\n parts: [\n { text: \"Hi\" }\n ]\n }\n ],\n generationConfig: {\n maxOutputTokens: 1\n }\n };\n \n console.log('[ModelConfig] ๐ข Request body:', JSON.stringify(requestBody, null, 2));\n \n try {\n const response = await fetch(fullUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(requestBody)\n });\n \n console.log('[ModelConfig] ๐ข HTTP status code:', response.status);\n console.log('[ModelConfig] ๐ข Response headers:', Object.fromEntries(response.headers.entries()));\n \n const responseText = await response.text();\n console.log('[ModelConfig] ๐ข Response body:', responseText);\n \n return response.ok;\n \n } catch (error) {\n console.error('[ModelConfig] โ Gemini test error:', error);\n return false;\n }\n}\n\n// DeepSeek API test\nasync function testDeepSeekAPI() {\n console.log('[ModelConfig] ๐ต Starting DeepSeek API test');\n \n const fullUrl = `${currentConfig.apiUrl}/chat/completions`;\n console.log('[ModelConfig] ๐ต Complete request URL:', fullUrl);\n \n // DeepSeek model name conversion\n const transformedModel = currentConfig.model.toLowerCase().replace(/\\s+/g, '-');\n console.log('[ModelConfig] ๐ต Model name conversion:', currentConfig.model, '->', transformedModel);\n \n const requestBody = {\n model: transformedModel,\n messages: [\n { role: \"user\", content: \"Hi\" }\n ],\n max_tokens: 1\n };\n \n console.log('[ModelConfig] ๐ต Request body:', JSON.stringify(requestBody, null, 2));\n \n try {\n const response = await fetch(fullUrl, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${currentConfig.apiKey}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(requestBody)\n });\n \n console.log('[ModelConfig] ๐ต HTTP status code:', response.status);\n console.log('[ModelConfig] ๐ต Response headers:', Object.fromEntries(response.headers.entries()));\n \n const responseText = await response.text();\n console.log('[ModelConfig] ๐ต Response body:', responseText);\n \n return response.ok;\n \n } catch (error) {\n console.error('[ModelConfig] โ DeepSeek test error:', error);\n return false;\n }\n}\n\n\n\n// Initialize when page loads\ndocument.addEventListener('DOMContentLoaded', function() {\n console.log('[ModelConfig] ๐ฑ Page loaded, starting initialization');\n \n // Delay initialization to ensure all elements are loaded\n setTimeout(() => {\n initializeModelConfiguration();\n loadConfiguration();\n }, 100);\n});\n\n// Export configuration object for other modules to use\nwindow.ModelConfiguration = {\n getCurrentConfig: () => currentConfig,\n getServiceProviders: () => ServiceProviders,\n testAPI: testApiConfiguration,\n saveConfig: saveConfiguration,\n loadConfig: loadConfiguration,\n toggleMultiRounds: toggleMultiRounds\n};\n"}}}}