[eric] settings-agent: one settingSelectAttrs helper kills the per-row JSON drift + extends select-and-send across the whole General tab (Interface+Agent Defaults+Advanced, 16 fields)

This commit is contained in:
ciregenz
2026-06-19 04:15:36 -07:00
parent 6e3ccd1824
commit de2fce4f62
4 changed files with 29 additions and 15 deletions
@@ -12,6 +12,7 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext';
import TrustedFilePatterns from '@/app/components/overlays/TrustedFilePatterns';
import SoftwareUpdateRow from './SoftwareUpdateRow';
import type { SettingsStyles } from '../settingsStyles';
import { settingSelectAttrs } from '../settingSelect';
const GeneralAdvanced: React.FC<{
form: AppSettings;
@@ -38,7 +39,7 @@ const GeneralAdvanced: React.FC<{
<>
<Typography sx={{ ...sectionSx, mt: 3 }}>Advanced</Typography>
<Box sx={inlineRowSx}>
<Box sx={inlineRowSx} {...settingSelectAttrs('dev_mode', 'Developer mode', 'Advanced', 'Show transport details, env vars, and technical metadata throughout the app.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Developer mode</Typography>
<Typography sx={descSx}>Show transport details, environment variables, raw configs, and other technical metadata throughout the app.</Typography>
@@ -53,7 +54,7 @@ const GeneralAdvanced: React.FC<{
/>
</Box>
<Box sx={inlineRowLastSx}>
<Box sx={inlineRowLastSx} {...settingSelectAttrs('allow_experimental_updates', 'Experimental updates', 'Advanced', 'Receive pre-release builds with new features earlier.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Experimental updates</Typography>
<Typography sx={descSx}>Receive pre-release builds with new features earlier. These versions may be less stable than normal releases.</Typography>
@@ -13,6 +13,7 @@ import { useAppDispatch } from '@/shared/hooks';
import { resetSystemPrompt, AppSettings, DEFAULT_SYSTEM_PROMPT } from '@/shared/state/settingsSlice';
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
import type { SettingsStyles } from '../settingsStyles';
import { settingSelectAttrs } from '../settingSelect';
type ModelOption = { value: string; label: string };
@@ -34,7 +35,7 @@ const GeneralAgentDefaults: React.FC<{
<>
<Typography sx={sectionSx}>Agent Defaults</Typography>
<Box sx={rowSx}>
<Box sx={rowSx} {...settingSelectAttrs('default_system_prompt', 'System prompt', 'Agent Defaults', 'Prepended to every agent session before mode-specific instructions.')}>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 0.5 }}>
<Typography sx={labelSx}>System prompt</Typography>
{form.default_system_prompt !== DEFAULT_SYSTEM_PROMPT && (
@@ -79,7 +80,7 @@ const GeneralAgentDefaults: React.FC<{
/>
</Box>
<Box sx={rowSx}>
<Box sx={rowSx} {...settingSelectAttrs('default_folder', 'Working directory', 'Agent Defaults', 'Default folder agents start in.')}>
<Typography sx={labelSx}>Working directory</Typography>
<Typography sx={{ ...descSx, mb: 1.5 }}>
Default folder agents start in. Modes can override per-mode.
@@ -118,7 +119,7 @@ const GeneralAgentDefaults: React.FC<{
</Box>
</Box>
<Box sx={inlineRowSx}>
<Box sx={inlineRowSx} {...settingSelectAttrs('default_model', 'Model', 'Agent Defaults', 'Default model for new sessions.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Model</Typography>
<Typography sx={descSx}>Default model for new sessions.</Typography>
@@ -199,7 +200,7 @@ const GeneralAgentDefaults: React.FC<{
</FormControl>
</Box>
<Box sx={inlineRowSx}>
<Box sx={inlineRowSx} {...settingSelectAttrs('default_mode', 'Mode', 'Agent Defaults', 'Default interaction mode for new sessions.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Mode</Typography>
<Typography sx={descSx}>Default interaction mode for new sessions.</Typography>
@@ -218,7 +219,7 @@ const GeneralAgentDefaults: React.FC<{
</FormControl>
</Box>
<Box sx={inlineRowSx}>
<Box sx={inlineRowSx} {...settingSelectAttrs('default_thinking_level', 'Thinking', 'Agent Defaults', 'Default thinking level for reasoning-capable models.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Thinking</Typography>
<Typography sx={descSx}>Default thinking level for reasoning-capable models.</Typography>
@@ -239,7 +240,7 @@ const GeneralAgentDefaults: React.FC<{
</FormControl>
</Box>
<Box sx={inlineRowLastSx}>
<Box sx={inlineRowLastSx} {...settingSelectAttrs('default_max_turns', 'Max turns', 'Agent Defaults', 'Auto-stop after this many turns. Empty = unlimited.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Max turns</Typography>
<Typography sx={descSx}>Auto-stop after this many turns. Empty = unlimited.</Typography>
@@ -13,6 +13,7 @@ import LanguageIcon from '@mui/icons-material/Language';
import { AppSettings } from '@/shared/state/settingsSlice';
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
import type { SettingsStyles } from '../settingsStyles';
import { settingSelectAttrs } from '../settingSelect';
const GeneralInterface: React.FC<{
form: AppSettings;
@@ -27,7 +28,7 @@ const GeneralInterface: React.FC<{
<>
<Typography sx={{ ...sectionSx, mt: 3 }}>Interface</Typography>
<Box sx={inlineRowSx} data-select-type="settings-option" data-select-id="theme" data-select-meta={JSON.stringify({ name: 'Theme', category: 'Interface', fieldName: 'theme', description: 'Application color scheme.' })}>
<Box sx={inlineRowSx} {...settingSelectAttrs('theme', 'Theme', 'Interface', 'Application color scheme.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Theme</Typography>
<Typography sx={descSx}>Application color scheme.</Typography>
@@ -64,7 +65,7 @@ const GeneralInterface: React.FC<{
</ToggleButtonGroup>
</Box>
<Box sx={rowSx} data-select-type="settings-option" data-select-id="zoom_sensitivity" data-select-meta={JSON.stringify({ name: 'Zoom sensitivity', category: 'Interface', fieldName: 'zoom_sensitivity', description: 'Scroll-to-zoom responsiveness.' })}>
<Box sx={rowSx} {...settingSelectAttrs('zoom_sensitivity', 'Zoom sensitivity', 'Interface', 'Scroll-to-zoom responsiveness.')}>
<Typography sx={labelSx}>Zoom sensitivity</Typography>
<Typography sx={{ ...descSx, mb: 1 }}>
Scroll-to-zoom responsiveness. Lower for trackpads, higher for mouse wheels.
@@ -91,7 +92,7 @@ const GeneralInterface: React.FC<{
</Box>
</Box>
<Box sx={inlineRowSx} data-select-type="settings-option" data-select-id="new_agent_shortcut" data-select-meta={JSON.stringify({ name: 'New agent shortcut', category: 'Interface', fieldName: 'new_agent_shortcut', description: 'Keyboard shortcut to create an agent.' })}>
<Box sx={inlineRowSx} {...settingSelectAttrs('new_agent_shortcut', 'New agent shortcut', 'Interface', 'Keyboard shortcut to create an agent.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>New agent shortcut</Typography>
<Typography sx={descSx}>Keyboard shortcut to create an agent.</Typography>
@@ -149,7 +150,7 @@ const GeneralInterface: React.FC<{
</Box>
</Box>
<Box sx={inlineRowSx} data-select-type="settings-option" data-select-id="auto_select_mode_on_new_agent" data-select-meta={JSON.stringify({ name: 'Auto-enable element selection', category: 'Interface', fieldName: 'auto_select_mode_on_new_agent', description: 'Enter element selection mode when creating a new agent.' })}>
<Box sx={inlineRowSx} {...settingSelectAttrs('auto_select_mode_on_new_agent', 'Auto-enable element selection', 'Interface', 'Enter element selection mode when creating a new agent.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Auto-enable element selection</Typography>
<Typography sx={descSx}>Automatically enter element selection mode when creating a new agent.</Typography>
@@ -164,7 +165,7 @@ const GeneralInterface: React.FC<{
/>
</Box>
<Box sx={inlineRowSx} data-select-type="settings-option" data-select-id="expand_new_chats_in_dashboard" data-select-meta={JSON.stringify({ name: 'Default agent spawn state in dashboard', category: 'Interface', fieldName: 'expand_new_chats_in_dashboard', description: 'New agents spawn expanded instead of collapsed.' })}>
<Box sx={inlineRowSx} {...settingSelectAttrs('expand_new_chats_in_dashboard', 'Default agent spawn state in dashboard', 'Interface', 'New agents spawn expanded instead of collapsed.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Default agent spawn state in dashboard</Typography>
<Typography sx={descSx}>When enabled, new agents spawn expanded instead of collapsed.</Typography>
@@ -179,7 +180,7 @@ const GeneralInterface: React.FC<{
/>
</Box>
<Box sx={inlineRowLastSx} data-select-type="settings-option" data-select-id="auto_reveal_sub_agents" data-select-meta={JSON.stringify({ name: 'Auto-reveal sub-agents on dashboard', category: 'Interface', fieldName: 'auto_reveal_sub_agents', description: 'Show sub-agent cards tethered to their parent on the dashboard.' })}>
<Box sx={inlineRowLastSx} {...settingSelectAttrs('auto_reveal_sub_agents', 'Auto-reveal sub-agents on dashboard', 'Interface', 'Show sub-agent cards tethered to their parent on the dashboard.')}>
<Box sx={{ mr: 3 }}>
<Typography sx={labelSx}>Auto-reveal sub-agents on dashboard</Typography>
<Typography sx={descSx}>Automatically show sub-agent cards (from CreateAgent / InvokeAgent) tethered to their parent on the dashboard.</Typography>
@@ -196,7 +197,7 @@ const GeneralInterface: React.FC<{
<Typography sx={{ ...sectionSx, mt: 3 }}>Browser</Typography>
<Box sx={rowLastSx} data-select-type="settings-option" data-select-id="browser_homepage" data-select-meta={JSON.stringify({ name: 'Default homepage', category: 'Browser', fieldName: 'browser_homepage', description: 'URL loaded when opening a new browser card.' })}>
<Box sx={rowLastSx} {...settingSelectAttrs('browser_homepage', 'Default homepage', 'Browser', 'URL loaded when opening a new browser card.')}>
<Typography sx={labelSx}>Default homepage</Typography>
<Typography sx={{ ...descSx, mb: 1.5 }}>
URL loaded when opening a new browser card on the dashboard.
@@ -0,0 +1,11 @@
// The data-select-* handle that makes a Settings row pointable by the chat
// element-selector. One source for it, spread onto a row's Box, so a row's label
// and its selection metadata can't drift apart (same args) and every section
// opts in the same way instead of copy-pasting the JSON.stringify.
export function settingSelectAttrs(field: string, name: string, category: string, description?: string) {
return {
'data-select-type': 'settings-option',
'data-select-id': field,
'data-select-meta': JSON.stringify({ name, category, fieldName: field, description }),
};
}