// Providers Page Module class ProvidersPage { constructor() { this.providers = []; this.init(); } async init() { await this.loadProviders(); this.setupEventListeners(); } async loadProviders() { try { const data = await window.api.get('/providers'); this.providers = data; this.renderProviders(); this.renderStats(); } catch (error) { console.error('Error loading providers:', error); window.authManager.showToast('Failed to load providers', 'error'); } } renderProviders() { const container = document.getElementById('providers-list'); if (!container) return; if (this.providers.length === 0) { container.innerHTML = '
No providers configured
'; return; } container.innerHTML = `
${this.providers.map(provider => this.renderProviderCard(provider)).join('')}
`; } renderProviderCard(provider) { const statusClass = provider.status === 'online' ? 'success' : 'warning'; const modelCount = provider.models ? provider.models.length : 0; // Credit balance display logic const isLowBalance = provider.credit_balance <= provider.low_credit_threshold && provider.id !== 'ollama'; const balanceColor = isLowBalance ? 'var(--red-light)' : 'var(--green-light)'; const escapedId = window.api.escapeHtml(provider.id); const escapedName = window.api.escapeHtml(provider.name); const escapedStatus = window.api.escapeHtml(provider.status); const billingMode = provider.billing_mode ? provider.billing_mode.toUpperCase() : 'PREPAID'; return `

${escapedName}

${escapedId}
${escapedStatus}
${modelCount} Models Available
Balance: ${escapedId === 'ollama' ? 'FREE' : window.api.formatCurrency(provider.credit_balance)} ${isLowBalance ? '' : ''}
Billing: ${window.api.escapeHtml(billingMode)}
Last used: ${provider.last_used ? window.api.formatTimeAgo(provider.last_used) : 'Never'}
${(provider.models || []).slice(0, 5).map(m => `${window.api.escapeHtml(m)}`).join('')} ${modelCount > 5 ? `+${modelCount - 5} more` : ''}
`; } renderStats() { const container = document.getElementById('provider-stats'); if (!container) return; const onlineCount = this.providers.filter(p => p.status === 'online').length; const totalModels = this.providers.reduce((sum, p) => sum + (p.models ? p.models.length : 0), 0); container.innerHTML = `
${this.providers.length}
Total Providers
${onlineCount}
Online Status
${totalModels}
Total Models
`; } async testProvider(id) { window.authManager.showToast(`Testing connection to ${id}...`, 'info'); try { await window.api.post(`/providers/${id}/test`, {}); window.authManager.showToast(`${id} connection successful!`, 'success'); this.loadProviders(); } catch (error) { window.authManager.showToast(`${id} test failed: ${error.message}`, 'error'); } } configureProvider(id) { const provider = this.providers.find(p => p.id === id); if (!provider) return; const modal = document.createElement('div'); modal.className = 'modal active'; const escapedId = window.api.escapeHtml(provider.id); const escapedName = window.api.escapeHtml(provider.name); const escapedBaseUrl = window.api.escapeHtml(provider.base_url); const escapedBalance = window.api.escapeHtml(provider.credit_balance); const escapedThreshold = window.api.escapeHtml(provider.low_credit_threshold); modal.innerHTML = ` `; document.body.appendChild(modal); modal.querySelector('#save-provider-config').onclick = async () => { const enabled = modal.querySelector('#provider-enabled').checked; const baseUrl = modal.querySelector('#provider-base-url').value; const apiKey = modal.querySelector('#provider-api-key').value; const balance = parseFloat(modal.querySelector('#provider-balance').value); const threshold = parseFloat(modal.querySelector('#provider-threshold').value); const billingMode = modal.querySelector('#provider-billing-mode').value; try { await window.api.put(`/providers/${id}`, { enabled, base_url: baseUrl || null, api_key: apiKey || null, credit_balance: isNaN(balance) ? null : balance, low_credit_threshold: isNaN(threshold) ? null : threshold, billing_mode: billingMode || null, }); window.authManager.showToast(`${provider.name} configuration saved`, 'success'); modal.remove(); this.loadProviders(); } catch (error) { window.authManager.showToast(error.message, 'error'); } }; } setupEventListeners() { const testAllBtn = document.getElementById('test-all-providers'); if (testAllBtn) { testAllBtn.onclick = () => { this.providers.forEach(p => this.testProvider(p.id)); }; } } } window.initProviders = async () => { window.providersPage = new ProvidersPage(); };