/** * Dynamic Model Loader - Frontend Logic * سیستم هوشمند بارگذاری مدل - منطق فرانتاند */ const dynamicLoader = { apiBase: window.location.origin, registeredModels: [], /** * مقداردهی اولیه */ async init() { console.log('🚀 Initializing Dynamic Model Loader...'); // Load registered models await this.refreshModelsList(); // Setup event listeners this.setupEventListeners(); console.log('✅ Dynamic Model Loader initialized'); }, setupEventListeners() { // Manual form submission const manualForm = document.getElementById('manual-form'); if (manualForm) { manualForm.addEventListener('submit', async (e) => { e.preventDefault(); await this.submitManualConfig(); }); } }, /** * نمایش حالتهای مختلف */ showPasteMode() { this.closeAllModes(); document.getElementById('paste-mode').style.display = 'block'; document.getElementById('paste-input').focus(); }, showManualMode() { this.closeAllModes(); document.getElementById('manual-mode').style.display = 'block'; document.getElementById('manual-model-id').focus(); }, showAutoMode() { this.closeAllModes(); document.getElementById('auto-mode').style.display = 'block'; document.getElementById('auto-url').focus(); }, closeAllModes() { document.getElementById('paste-mode').style.display = 'none'; document.getElementById('manual-mode').style.display = 'none'; document.getElementById('auto-mode').style.display = 'none'; }, closeTestPanel() { document.getElementById('test-panel').style.display = 'none'; }, /** * پردازش کپی/پیست */ async processPastedConfig() { const configText = document.getElementById('paste-input').value.trim(); const autoDetect = document.getElementById('auto-detect-paste').checked; if (!configText) { this.showError('Please paste a configuration'); return; } this.showInfo('Processing pasted configuration...'); try { const response = await fetch(`${this.apiBase}/api/dynamic-models/paste-config`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ config_text: configText, auto_detect: autoDetect }) }); const data = await response.json(); if (data.success) { this.showSuccess(`Model "${data.data.model_id}" registered successfully!`); await this.refreshModelsList(); this.closeAllModes(); document.getElementById('paste-input').value = ''; } else { this.showError(data.error || 'Failed to process configuration'); } } catch (error) { this.showError(`Error: ${error.message}`); console.error('Paste config error:', error); } }, async testPastedConfig() { const configText = document.getElementById('paste-input').value.trim(); if (!configText) { this.showError('Please paste a configuration'); return; } this.showInfo('Testing configuration...'); try { // Parse the config let parsedConfig; try { parsedConfig = JSON.parse(configText); } catch { this.showError('Invalid JSON. Please provide valid JSON configuration for testing.'); return; } const response = await fetch(`${this.apiBase}/api/dynamic-models/test-connection`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(parsedConfig) }); const data = await response.json(); if (data.success && data.test_result.success) { this.showSuccess(`✅ Connection successful! (${Math.round(data.test_result.response_time_ms)}ms)`); } else { this.showError(`❌ Connection failed: ${data.test_result.error || 'Unknown error'}`); } } catch (error) { this.showError(`Test failed: ${error.message}`); console.error('Test error:', error); } }, /** * ارسال فرم دستی */ async submitManualConfig() { const config = { model_id: document.getElementById('manual-model-id').value.trim(), model_name: document.getElementById('manual-model-name').value.trim(), base_url: document.getElementById('manual-base-url').value.trim(), api_key: document.getElementById('manual-api-key').value.trim() || null, api_type: document.getElementById('manual-api-type').value === 'auto' ? null : document.getElementById('manual-api-type').value, endpoints: document.getElementById('manual-endpoint').value.trim() || null }; const testFirst = document.getElementById('test-before-register').checked; if (testFirst) { this.showInfo('Testing connection first...'); try { const testResponse = await fetch(`${this.apiBase}/api/dynamic-models/test-connection`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); const testData = await testResponse.json(); if (!testData.success || !testData.test_result.success) { const proceed = confirm( `Connection test failed: ${testData.test_result.error}\n\nDo you want to register anyway?` ); if (!proceed) return; } } catch (error) { const proceed = confirm( `Test failed: ${error.message}\n\nDo you want to register anyway?` ); if (!proceed) return; } } this.showInfo('Registering model...'); try { const response = await fetch(`${this.apiBase}/api/dynamic-models/register`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); const data = await response.json(); if (data.success) { this.showSuccess(`Model "${config.model_id}" registered successfully!`); await this.refreshModelsList(); this.closeAllModes(); document.getElementById('manual-form').reset(); } else { this.showError(data.message || 'Registration failed'); } } catch (error) { this.showError(`Error: ${error.message}`); console.error('Registration error:', error); } }, async testManualConfig() { const config = { model_id: document.getElementById('manual-model-id').value.trim(), model_name: document.getElementById('manual-model-name').value.trim(), base_url: document.getElementById('manual-base-url').value.trim(), api_key: document.getElementById('manual-api-key').value.trim() || null, api_type: document.getElementById('manual-api-type').value === 'auto' ? null : document.getElementById('manual-api-type').value }; if (!config.base_url) { this.showError('Please enter a base URL'); return; } this.showInfo('Testing connection...'); try { const response = await fetch(`${this.apiBase}/api/dynamic-models/test-connection`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); const data = await response.json(); if (data.success && data.test_result.success) { this.showSuccess( `✅ Connection successful!\n` + `API Type: ${data.test_result.api_type}\n` + `Response Time: ${Math.round(data.test_result.response_time_ms)}ms\n` + `Capabilities: ${data.test_result.detected_capabilities.join(', ')}` ); } else { this.showError( `❌ Connection failed:\n${data.test_result.error || 'Unknown error'}` ); } } catch (error) { this.showError(`Test failed: ${error.message}`); console.error('Test error:', error); } }, /** * تنظیم خودکار از URL */ async autoConfigureFromURL() { const url = document.getElementById('auto-url').value.trim(); if (!url) { this.showError('Please enter a URL'); return; } this.showInfo('Auto-configuring model...'); try { const response = await fetch(`${this.apiBase}/api/dynamic-models/auto-configure`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url }) }); const data = await response.json(); if (data.success) { this.showSuccess( `✅ Model auto-configured and registered!\n` + `Model ID: ${data.config.model_id}\n` + `API Type: ${data.config.api_type}\n` + `Endpoints discovered: ${Object.keys(data.config.endpoints?.endpoints || {}).length}` ); await this.refreshModelsList(); this.closeAllModes(); document.getElementById('auto-url').value = ''; } else { this.showError(data.error || 'Auto-configuration failed'); } } catch (error) { this.showError(`Error: ${error.message}`); console.error('Auto-configure error:', error); } }, /** * بازخوانی لیست مدلها */ async refreshModelsList() { const container = document.getElementById('models-list'); try { const response = await fetch(`${this.apiBase}/api/dynamic-models/models`); const data = await response.json(); if (data.success) { this.registeredModels = data.models; this.renderModelsList(data.models); } else { container.innerHTML = '
Failed to load models
'; } } catch (error) { console.error('Failed to load models:', error); container.innerHTML = 'Error loading models
'; } }, renderModelsList(models) { const container = document.getElementById('models-list'); if (models.length === 0) { container.innerHTML = `No models registered yet
Click one of the quick action buttons above to register your first model
Running test...
'; try { const response = await fetch( `${this.apiBase}/api/dynamic-models/models/${modelId}/use`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ endpoint, payload }) } ); const data = await response.json(); if (data.success) { this.showSuccess(`Test completed in ${Math.round(data.data.response_time_ms)}ms`); resultDiv.innerHTML = `${JSON.stringify(data.data.data, null, 2)}
`;
} else {
this.showError('Test failed');
resultDiv.innerHTML = `