import { useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Label } from '@/components/ui/label'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Checkbox } from '@/components/ui/checkbox'; import { Input } from '@/components/ui/input'; import { Loader2, Volume2, Key } from 'lucide-react'; import type { ThemeMode, EditorType, SoundFile } from 'shared/types'; import { EXECUTOR_TYPES, EDITOR_TYPES, EXECUTOR_LABELS, EDITOR_LABELS, SOUND_FILES, SOUND_LABELS, } from 'shared/types'; import { useTheme } from '@/components/theme-provider'; import { useConfig } from '@/components/config-provider'; export function Settings() { const { config, updateConfig, saveConfig, loading } = useConfig(); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); const { setTheme } = useTheme(); const playSound = async (soundFile: SoundFile) => { const audio = new Audio(`/api/sounds/${soundFile}.wav`); try { await audio.play(); } catch (err) { console.error('Failed to play sound:', err); } }; const handleSave = async () => { if (!config) return; setSaving(true); setError(null); setSuccess(false); try { // Save the main configuration const success = await saveConfig(); if (success) { setSuccess(true); // Update theme provider to reflect the saved theme setTheme(config.theme); setTimeout(() => setSuccess(false), 3000); } else { setError('Failed to save configuration'); } } catch (err) { setError('Failed to save configuration'); console.error('Error saving config:', err); } finally { setSaving(false); } }; const resetDisclaimer = async () => { if (!config) return; updateConfig({ disclaimer_acknowledged: false }); }; const resetOnboarding = async () => { if (!config) return; updateConfig({ onboarding_acknowledged: false }); }; if (loading) { return (
Loading settings...
); } if (!config) { return (
Failed to load settings. {error}
); } return (

Settings

Configure your preferences and application settings.

{error && ( {error} )} {success && ( ✓ Settings saved successfully! )}
Appearance Customize how the application looks and feels.

Choose your preferred color scheme.

Task Execution Configure how tasks are executed and processed.

Choose the default executor for running tasks.

Editor Configure which editor to open when viewing task attempts.

Choose your preferred code editor for opening task attempts.

{config.editor.editor_type === 'custom' && (
updateConfig({ editor: { ...config.editor, custom_command: e.target.value || null, }, }) } />

Enter the command to run your custom editor. Use spaces for arguments (e.g., "code --wait").

)}
GitHub Integration Configure GitHub settings for creating pull requests from task attempts.
updateConfig({ github: { ...config.github, token: e.target.value || null, }, }) } />

GitHub Personal Access Token with 'repo' permissions. Required for creating pull requests.{' '} Create token here

updateConfig({ github: { ...config.github, default_pr_base: e.target.value || null, }, }) } />

Default base branch for pull requests. Defaults to 'main' if not specified.

Notifications Configure how you receive notifications about task completion.
updateConfig({ sound_alerts: checked }) } />

Play a sound when task attempts finish running.

{config.sound_alerts && (

Choose the sound to play when tasks complete. Click the volume button to preview.

)}
updateConfig({ push_notifications: checked }) } />

Show system notifications when task attempts finish running.

Safety & Disclaimers Manage safety warnings and acknowledgments.

{config.disclaimer_acknowledged ? 'You have acknowledged the safety disclaimer.' : 'The safety disclaimer has not been acknowledged.'}

Resetting the disclaimer will require you to acknowledge the safety warning again on next app start.

{config.onboarding_acknowledged ? 'You have completed the onboarding process.' : 'The onboarding process has not been completed.'}

Resetting the onboarding will show the setup screen again on next app start.

{/* Sticky save button */}
{/* Spacer to prevent content from being hidden behind sticky button */}
); }