import React, { useState } from 'react'; import { useNavigate } from '@remix-run/react'; import Cookies from 'js-cookie'; import { toast } from 'react-toastify'; import { db, deleteById, getAll } from '~/lib/persistence'; import { logStore } from '~/lib/stores/logs'; import { classNames } from '~/utils/classNames'; // List of supported providers that can have API keys const API_KEY_PROVIDERS = [ 'Anthropic', 'OpenAI', 'Google', 'Groq', 'HuggingFace', 'OpenRouter', 'Deepseek', 'Mistral', 'OpenAILike', 'Together', 'xAI', 'Perplexity', 'Cohere', 'AzureOpenAI', ] as const; interface ApiKeys { [key: string]: string; } export default function DataTab() { const navigate = useNavigate(); const [isDeleting, setIsDeleting] = useState(false); const downloadAsJson = (data: any, filename: string) => { const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); }; const handleExportAllChats = async () => { if (!db) { const error = new Error('Database is not available'); logStore.logError('Failed to export chats - DB unavailable', error); toast.error('Database is not available'); return; } try { const allChats = await getAll(db); const exportData = { chats: allChats, exportDate: new Date().toISOString(), }; downloadAsJson(exportData, `all-chats-${new Date().toISOString()}.json`); logStore.logSystem('Chats exported successfully', { count: allChats.length }); toast.success('Chats exported successfully'); } catch (error) { logStore.logError('Failed to export chats', error); toast.error('Failed to export chats'); console.error(error); } }; const handleDeleteAllChats = async () => { const confirmDelete = window.confirm('Are you sure you want to delete all chats? This action cannot be undone.'); if (!confirmDelete) { return; } if (!db) { const error = new Error('Database is not available'); logStore.logError('Failed to delete chats - DB unavailable', error); toast.error('Database is not available'); return; } try { setIsDeleting(true); const allChats = await getAll(db); await Promise.all(allChats.map((chat) => deleteById(db!, chat.id))); logStore.logSystem('All chats deleted successfully', { count: allChats.length }); toast.success('All chats deleted successfully'); navigate('/', { replace: true }); } catch (error) { logStore.logError('Failed to delete chats', error); toast.error('Failed to delete chats'); console.error(error); } finally { setIsDeleting(false); } }; const handleExportSettings = () => { const settings = { providers: Cookies.get('providers'), isDebugEnabled: Cookies.get('isDebugEnabled'), isEventLogsEnabled: Cookies.get('isEventLogsEnabled'), isLocalModelsEnabled: Cookies.get('isLocalModelsEnabled'), promptId: Cookies.get('promptId'), isLatestBranch: Cookies.get('isLatestBranch'), commitHash: Cookies.get('commitHash'), eventLogs: Cookies.get('eventLogs'), selectedModel: Cookies.get('selectedModel'), selectedProvider: Cookies.get('selectedProvider'), githubUsername: Cookies.get('githubUsername'), githubToken: Cookies.get('githubToken'), bolt_theme: localStorage.getItem('bolt_theme'), }; downloadAsJson(settings, 'bolt-settings.json'); toast.success('Settings exported successfully'); }; const handleImportSettings = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) { return; } const reader = new FileReader(); reader.onload = (e) => { try { const settings = JSON.parse(e.target?.result as string); Object.entries(settings).forEach(([key, value]) => { if (key === 'bolt_theme') { if (value) { localStorage.setItem(key, value as string); } } else if (value) { Cookies.set(key, value as string); } }); toast.success('Settings imported successfully. Please refresh the page for changes to take effect.'); } catch (error) { toast.error('Failed to import settings. Make sure the file is a valid JSON file.'); console.error('Failed to import settings:', error); } }; reader.readAsText(file); event.target.value = ''; }; const handleExportApiKeyTemplate = () => { const template: ApiKeys = {}; API_KEY_PROVIDERS.forEach((provider) => { template[`${provider}_API_KEY`] = ''; }); template.OPENAI_LIKE_API_BASE_URL = ''; template.LMSTUDIO_API_BASE_URL = ''; template.OLLAMA_API_BASE_URL = ''; template.TOGETHER_API_BASE_URL = ''; downloadAsJson(template, 'api-keys-template.json'); toast.success('API keys template exported successfully'); }; const handleImportApiKeys = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) { return; } const reader = new FileReader(); reader.onload = (e) => { try { const apiKeys = JSON.parse(e.target?.result as string); let importedCount = 0; const consolidatedKeys: Record = {}; API_KEY_PROVIDERS.forEach((provider) => { const keyName = `${provider}_API_KEY`; if (apiKeys[keyName]) { consolidatedKeys[provider] = apiKeys[keyName]; importedCount++; } }); if (importedCount > 0) { // Store all API keys in a single cookie as JSON Cookies.set('apiKeys', JSON.stringify(consolidatedKeys)); // Also set individual cookies for backward compatibility Object.entries(consolidatedKeys).forEach(([provider, key]) => { Cookies.set(`${provider}_API_KEY`, key); }); toast.success(`Successfully imported ${importedCount} API keys/URLs. Refreshing page to apply changes...`); // Reload the page after a short delay to allow the toast to be seen setTimeout(() => { window.location.reload(); }, 1500); } else { toast.warn('No valid API keys found in the file'); } // Set base URLs if they exist ['OPENAI_LIKE_API_BASE_URL', 'LMSTUDIO_API_BASE_URL', 'OLLAMA_API_BASE_URL', 'TOGETHER_API_BASE_URL'].forEach( (baseUrl) => { if (apiKeys[baseUrl]) { Cookies.set(baseUrl, apiKeys[baseUrl]); } }, ); } catch (error) { toast.error('Failed to import API keys. Make sure the file is a valid JSON file.'); console.error('Failed to import API keys:', error); } }; reader.readAsText(file); event.target.value = ''; }; return (

Data Management

Chat History

Export or delete all your chat history.

Settings Backup

Export your settings to a JSON file or import settings from a previously exported file.

API Keys Management

Import API keys from a JSON file or download a template to fill in your keys.

); }