feat: Add global settings modal and simplify agent controls

Adds a settings system for global configuration with YOLO mode toggle and
model selection. Simplifies the agent control UI by removing redundant
status indicator and pause functionality.

## Settings System
- New SettingsModal with YOLO mode toggle and model selection
- Settings persisted in SQLite (registry.db) - shared across all projects
- Models fetched from API endpoint (/api/settings/models)
- Single source of truth for models in registry.py - easy to add new models
- Optimistic UI updates with rollback on error

## Agent Control Simplification
- Removed StatusIndicator ("STOPPED"/"RUNNING" label) - redundant
- Removed Pause/Resume buttons - just Start/Stop toggle now
- Start button shows flame icon with fiery gradient when YOLO mode enabled

## Code Review Fixes
- Added focus trap to SettingsModal for accessibility
- Fixed YOLO button color contrast (WCAG AA compliance)
- Added model validation to AgentStartRequest schema
- Added model to AgentStatus response
- Added aria-labels to all icon-only buttons
- Added role="radiogroup" to model selection
- Added loading indicator during settings save
- Added SQLite timeout (30s) and retry logic with exponential backoff
- Added thread-safe database engine initialization
- Added orphaned lock file cleanup on server startup

## Files Changed
- registry.py: Model config, Settings CRUD, SQLite improvements
- server/routers/settings.py: New settings API
- server/schemas.py: Settings schemas with validation
- server/services/process_manager.py: Model param, orphan cleanup
- ui/src/components/SettingsModal.tsx: New modal component
- ui/src/components/AgentControl.tsx: Simplified to Start/Stop only

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Auto
2026-01-07 12:29:07 +02:00
parent 122f03dc21
commit 45ba266f71
16 changed files with 825 additions and 173 deletions

View File

@@ -16,6 +16,9 @@ import type {
PathValidationResponse,
AssistantConversation,
AssistantConversationDetail,
Settings,
SettingsUpdate,
ModelsResponse,
} from './types'
const API_BASE = '/api'
@@ -267,3 +270,22 @@ export async function deleteAssistantConversation(
{ method: 'DELETE' }
)
}
// ============================================================================
// Settings API
// ============================================================================
export async function getAvailableModels(): Promise<ModelsResponse> {
return fetchJSON('/settings/models')
}
export async function getSettings(): Promise<Settings> {
return fetchJSON('/settings')
}
export async function updateSettings(settings: SettingsUpdate): Promise<Settings> {
return fetchJSON('/settings', {
method: 'PATCH',
body: JSON.stringify(settings),
})
}

View File

@@ -90,6 +90,7 @@ export interface AgentStatusResponse {
pid: number | null
started_at: string | null
yolo_mode: boolean
model: string | null // Model being used by running agent
}
export interface AgentActionResponse {
@@ -295,3 +296,27 @@ export type AssistantChatServerMessage =
| AssistantChatErrorMessage
| AssistantChatConversationCreatedMessage
| AssistantChatPongMessage
// ============================================================================
// Settings Types
// ============================================================================
export interface ModelInfo {
id: string
name: string
}
export interface ModelsResponse {
models: ModelInfo[]
default: string
}
export interface Settings {
yolo_mode: boolean
model: string
}
export interface SettingsUpdate {
yolo_mode?: boolean
model?: string
}