/** * Settings Page * Application configuration */ import { useState } from 'react'; import { Sun, Moon, Monitor, RefreshCw, Terminal, ExternalLink, Key, Download, Copy, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Separator } from '@/components/ui/separator'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { toast } from 'sonner'; import { useSettingsStore } from '@/stores/settings'; import { useGatewayStore } from '@/stores/gateway'; import { useUpdateStore } from '@/stores/update'; import { ProvidersSettings } from '@/components/settings/ProvidersSettings'; import { UpdateSettings } from '@/components/settings/UpdateSettings'; type ControlUiInfo = { url: string; token: string; port: number; }; export function Settings() { const { theme, setTheme, gatewayAutoStart, setGatewayAutoStart, autoCheckUpdate, setAutoCheckUpdate, autoDownloadUpdate, setAutoDownloadUpdate, devModeUnlocked, setDevModeUnlocked, } = useSettingsStore(); const { status: gatewayStatus, restart: restartGateway } = useGatewayStore(); const currentVersion = useUpdateStore((state) => state.currentVersion); const [controlUiInfo, setControlUiInfo] = useState(null); // Open developer console const openDevConsole = async () => { try { const result = await window.electron.ipcRenderer.invoke('gateway:getControlUiUrl') as { success: boolean; url?: string; token?: string; port?: number; error?: string; }; if (result.success && result.url && result.token && typeof result.port === 'number') { setControlUiInfo({ url: result.url, token: result.token, port: result.port }); window.electron.openExternal(result.url); } else { console.error('Failed to get Dev Console URL:', result.error); } } catch (err) { console.error('Error opening Dev Console:', err); } }; const refreshControlUiInfo = async () => { try { const result = await window.electron.ipcRenderer.invoke('gateway:getControlUiUrl') as { success: boolean; url?: string; token?: string; port?: number; }; if (result.success && result.url && result.token && typeof result.port === 'number') { setControlUiInfo({ url: result.url, token: result.token, port: result.port }); } } catch { // Ignore refresh errors } }; const handleCopyGatewayToken = async () => { if (!controlUiInfo?.token) return; try { await navigator.clipboard.writeText(controlUiInfo.token); toast.success('Gateway token copied'); } catch (error) { toast.error(`Failed to copy token: ${String(error)}`); } }; return (

Settings

Configure your ClawX experience

{/* Appearance */} Appearance Customize the look and feel
{/* AI Providers */} AI Providers Configure your AI model providers and API keys {/* Gateway */} Gateway OpenClaw Gateway settings

Port: {gatewayStatus.port}

{gatewayStatus.state}

Start Gateway when ClawX launches

{/* Updates */} Updates Keep ClawX up to date

Check for updates on startup

Download updates in the background

{/* Advanced */} Advanced Power-user options

Show developer tools and shortcuts

{/* Developer */} {devModeUnlocked && ( Developer Advanced options for developers

Access the native OpenClaw management interface

Opens the Control UI with gateway token injected

Paste this into Control UI settings if prompted

)} {/* About */} About

ClawX - Graphical AI Assistant

Based on OpenClaw

Version {currentVersion}

); } export default Settings;