Implement comprehensive LLM provider system with global cost protection
- Add multi-provider LLM architecture supporting OpenRouter, OpenAI, Gemini, and custom providers - Implement global LLM on/off switch with default DISABLED state for cost protection - Add per-character LLM configuration with provider-specific models and settings - Create performance-optimized caching system for LLM enabled status checks - Add API key validation before enabling LLM providers to prevent broken configurations - Implement audit logging for all LLM enable/disable actions for cost accountability - Create comprehensive admin UI with prominent cost warnings and confirmation dialogs - Add visual indicators in character list for custom AI model configurations - Build character-specific LLM client system with global fallback mechanism - Add database schema support for per-character LLM settings - Implement graceful fallback responses when LLM is globally disabled - Create provider testing and validation system for reliable connections
This commit is contained in:
@@ -515,9 +515,19 @@
|
||||
<div class="character-item">
|
||||
<div>
|
||||
<div class="character-name">${char.name}</div>
|
||||
<div class="character-info">${char.total_messages || 0} messages • ${char.status || 'Unknown'}</div>
|
||||
<div class="character-info">${char.total_messages || 0} messages • ${char.is_active ? 'Active' : 'Disabled'}</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px; align-items: center;">
|
||||
<button onclick="editCharacter('${char.name}')"
|
||||
style="padding: 5px 10px; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; background: #667eea; color: white;">
|
||||
Edit
|
||||
</button>
|
||||
<button onclick="toggleCharacter('${char.name}', ${char.is_active || false})"
|
||||
style="padding: 5px 10px; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; ${char.is_active ? 'background: #ef4444; color: white;' : 'background: #10b981; color: white;'}">
|
||||
${char.is_active ? 'Disable' : 'Enable'}
|
||||
</button>
|
||||
<span class="status ${char.is_active ? 'online' : 'offline'}">${char.is_active ? 'Enabled' : 'Disabled'}</span>
|
||||
</div>
|
||||
<span class="status ${char.status?.toLowerCase() || 'offline'}">${char.status || 'Offline'}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
@@ -1160,6 +1170,49 @@
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// Character management functions
|
||||
async function toggleCharacter(characterName, isCurrentlyActive) {
|
||||
try {
|
||||
const newStatus = !isCurrentlyActive;
|
||||
await apiCall(`/api/characters/${characterName}/toggle`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ is_active: newStatus })
|
||||
});
|
||||
showMessage(`Character ${characterName} ${newStatus ? 'enabled' : 'disabled'} successfully!`, 'success');
|
||||
loadDashboardData(); // Refresh the display
|
||||
} catch (error) {
|
||||
showMessage(`Failed to toggle ${characterName}: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function editCharacter(characterName) {
|
||||
try {
|
||||
// Get character details
|
||||
const character = await apiCall(`/api/characters/${characterName}`);
|
||||
|
||||
// Create a simple edit form
|
||||
const newGoals = prompt(`Edit goals for ${characterName} (comma-separated):`,
|
||||
character.current_goals ? character.current_goals.join(', ') : '');
|
||||
|
||||
if (newGoals !== null) {
|
||||
const updatedCharacter = {
|
||||
...character,
|
||||
current_goals: newGoals.split(',').map(g => g.trim()).filter(g => g)
|
||||
};
|
||||
|
||||
await apiCall(`/api/characters/${characterName}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(updatedCharacter)
|
||||
});
|
||||
|
||||
showMessage(`Character ${characterName} updated successfully!`, 'success');
|
||||
loadDashboardData(); // Refresh the display
|
||||
}
|
||||
} catch (error) {
|
||||
showMessage(`Failed to edit ${characterName}: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-refresh dashboard
|
||||
setInterval(() => {
|
||||
const activeTab = document.querySelector('.tab-content.active');
|
||||
|
||||
Reference in New Issue
Block a user