feat(web): persist new session agent and yolo preferences (#171)

This commit is contained in:
Him188
2026-02-10 15:40:45 +08:00
committed by GitHub
parent 2080ee8c7f
commit b11e6ed7eb
3 changed files with 98 additions and 2 deletions
+16 -2
View File
@@ -13,6 +13,12 @@ import { AgentSelector } from './AgentSelector'
import { DirectorySection } from './DirectorySection'
import { MachineSelector } from './MachineSelector'
import { ModelSelector } from './ModelSelector'
import {
loadPreferredAgent,
loadPreferredYoloMode,
savePreferredAgent,
savePreferredYoloMode,
} from './preferences'
import { SessionTypeSelector } from './SessionTypeSelector'
import { YoloToggle } from './YoloToggle'
@@ -34,9 +40,9 @@ export function NewSession(props: {
const [suppressSuggestions, setSuppressSuggestions] = useState(false)
const [isDirectoryFocused, setIsDirectoryFocused] = useState(false)
const [pathExistence, setPathExistence] = useState<Record<string, boolean>>({})
const [agent, setAgent] = useState<AgentType>('claude')
const [agent, setAgent] = useState<AgentType>(loadPreferredAgent)
const [model, setModel] = useState('auto')
const [yoloMode, setYoloMode] = useState(false)
const [yoloMode, setYoloMode] = useState(loadPreferredYoloMode)
const [sessionType, setSessionType] = useState<SessionType>('simple')
const [worktreeName, setWorktreeName] = useState('')
const [error, setError] = useState<string | null>(null)
@@ -52,6 +58,14 @@ export function NewSession(props: {
setModel('auto')
}, [agent])
useEffect(() => {
savePreferredAgent(agent)
}, [agent])
useEffect(() => {
savePreferredYoloMode(yoloMode)
}, [yoloMode])
useEffect(() => {
if (props.machines.length === 0) return
if (machineId && props.machines.find((m) => m.id === machineId)) return
@@ -0,0 +1,40 @@
import { beforeEach, describe, expect, it } from 'vitest'
import {
loadPreferredAgent,
loadPreferredYoloMode,
savePreferredAgent,
savePreferredYoloMode,
} from './preferences'
describe('NewSession preferences', () => {
beforeEach(() => {
localStorage.clear()
})
it('loads defaults when storage is empty', () => {
expect(loadPreferredAgent()).toBe('claude')
expect(loadPreferredYoloMode()).toBe(false)
})
it('loads saved values from storage', () => {
localStorage.setItem('hapi:newSession:agent', 'codex')
localStorage.setItem('hapi:newSession:yolo', 'true')
expect(loadPreferredAgent()).toBe('codex')
expect(loadPreferredYoloMode()).toBe(true)
})
it('falls back to default agent on invalid stored value', () => {
localStorage.setItem('hapi:newSession:agent', 'unknown-agent')
expect(loadPreferredAgent()).toBe('claude')
})
it('persists new values to storage', () => {
savePreferredAgent('gemini')
savePreferredYoloMode(true)
expect(localStorage.getItem('hapi:newSession:agent')).toBe('gemini')
expect(localStorage.getItem('hapi:newSession:yolo')).toBe('true')
})
})
@@ -0,0 +1,42 @@
import type { AgentType } from './types'
const AGENT_STORAGE_KEY = 'hapi:newSession:agent'
const YOLO_STORAGE_KEY = 'hapi:newSession:yolo'
const VALID_AGENTS: AgentType[] = ['claude', 'codex', 'gemini', 'opencode']
export function loadPreferredAgent(): AgentType {
try {
const stored = localStorage.getItem(AGENT_STORAGE_KEY)
if (stored && VALID_AGENTS.includes(stored as AgentType)) {
return stored as AgentType
}
} catch {
// Ignore storage errors
}
return 'claude'
}
export function savePreferredAgent(agent: AgentType): void {
try {
localStorage.setItem(AGENT_STORAGE_KEY, agent)
} catch {
// Ignore storage errors
}
}
export function loadPreferredYoloMode(): boolean {
try {
return localStorage.getItem(YOLO_STORAGE_KEY) === 'true'
} catch {
return false
}
}
export function savePreferredYoloMode(enabled: boolean): void {
try {
localStorage.setItem(YOLO_STORAGE_KEY, enabled ? 'true' : 'false')
} catch {
// Ignore storage errors
}
}