chore: rename key runOnStartup from hooks useLocalApiServer

This commit is contained in:
Faisal Amir 2025-08-20 22:37:45 +07:00
parent cfa68c5500
commit 39df7b22b9
4 changed files with 98 additions and 31 deletions

View File

@ -24,7 +24,7 @@ describe('useLocalApiServer', () => {
vi.clearAllMocks() vi.clearAllMocks()
// Reset store state to defaults // Reset store state to defaults
const store = useLocalApiServer.getState() const store = useLocalApiServer.getState()
store.setRunOnStartup(true) store.setEnableOnStartup(true)
store.setServerHost('127.0.0.1') store.setServerHost('127.0.0.1')
store.setServerPort(1337) store.setServerPort(1337)
store.setApiPrefix('/v1') store.setApiPrefix('/v1')
@ -37,7 +37,7 @@ describe('useLocalApiServer', () => {
it('should initialize with default values', () => { it('should initialize with default values', () => {
const { result } = renderHook(() => useLocalApiServer()) const { result } = renderHook(() => useLocalApiServer())
expect(result.current.runOnStartup).toBe(true) expect(result.current.enableOnStartup).toBe(true)
expect(result.current.serverHost).toBe('127.0.0.1') expect(result.current.serverHost).toBe('127.0.0.1')
expect(result.current.serverPort).toBe(1337) expect(result.current.serverPort).toBe(1337)
expect(result.current.apiPrefix).toBe('/v1') expect(result.current.apiPrefix).toBe('/v1')
@ -47,21 +47,21 @@ describe('useLocalApiServer', () => {
expect(result.current.apiKey).toBe('') expect(result.current.apiKey).toBe('')
}) })
describe('runOnStartup', () => { describe('enableOnStartup', () => {
it('should set run on startup', () => { it('should set run on startup', () => {
const { result } = renderHook(() => useLocalApiServer()) const { result } = renderHook(() => useLocalApiServer())
act(() => { act(() => {
result.current.setRunOnStartup(false) result.current.setEnableOnStartup(false)
}) })
expect(result.current.runOnStartup).toBe(false) expect(result.current.enableOnStartup).toBe(false)
act(() => { act(() => {
result.current.setRunOnStartup(true) result.current.setEnableOnStartup(true)
}) })
expect(result.current.runOnStartup).toBe(true) expect(result.current.enableOnStartup).toBe(true)
}) })
}) })
@ -323,7 +323,7 @@ describe('useLocalApiServer', () => {
const { result: result2 } = renderHook(() => useLocalApiServer()) const { result: result2 } = renderHook(() => useLocalApiServer())
act(() => { act(() => {
result1.current.setRunOnStartup(false) result1.current.setEnableOnStartup(false)
result1.current.setServerHost('0.0.0.0') result1.current.setServerHost('0.0.0.0')
result1.current.setServerPort(8080) result1.current.setServerPort(8080)
result1.current.setApiPrefix('/api') result1.current.setApiPrefix('/api')
@ -333,7 +333,7 @@ describe('useLocalApiServer', () => {
result1.current.addTrustedHost('example.com') result1.current.addTrustedHost('example.com')
}) })
expect(result2.current.runOnStartup).toBe(false) expect(result2.current.enableOnStartup).toBe(false)
expect(result2.current.serverHost).toBe('0.0.0.0') expect(result2.current.serverHost).toBe('0.0.0.0')
expect(result2.current.serverPort).toBe(8080) expect(result2.current.serverPort).toBe(8080)
expect(result2.current.apiPrefix).toBe('/api') expect(result2.current.apiPrefix).toBe('/api')

View File

@ -4,8 +4,8 @@ import { localStorageKey } from '@/constants/localStorage'
type LocalApiServerState = { type LocalApiServerState = {
// Run local API server once app opens // Run local API server once app opens
runOnStartup: boolean enableOnStartup: boolean
setRunOnStartup: (value: boolean) => void setEnableOnStartup: (value: boolean) => void
// Server host option (127.0.0.1 or 0.0.0.0) // Server host option (127.0.0.1 or 0.0.0.0)
serverHost: '127.0.0.1' | '0.0.0.0' serverHost: '127.0.0.1' | '0.0.0.0'
setServerHost: (value: '127.0.0.1' | '0.0.0.0') => void setServerHost: (value: '127.0.0.1' | '0.0.0.0') => void
@ -33,8 +33,8 @@ type LocalApiServerState = {
export const useLocalApiServer = create<LocalApiServerState>()( export const useLocalApiServer = create<LocalApiServerState>()(
persist( persist(
(set) => ({ (set) => ({
runOnStartup: false, enableOnStartup: false,
setRunOnStartup: (value) => set({ runOnStartup: value }), setEnableOnStartup: (value) => set({ enableOnStartup: value }),
serverHost: '127.0.0.1', serverHost: '127.0.0.1',
setServerHost: (value) => set({ serverHost: value }), setServerHost: (value) => set({ serverHost: value }),
serverPort: 1337, serverPort: 1337,

View File

@ -36,7 +36,7 @@ export function DataProvider() {
// Local API Server hooks // Local API Server hooks
const { const {
runOnStartup, enableOnStartup,
serverHost, serverHost,
serverPort, serverPort,
apiPrefix, apiPrefix,
@ -146,7 +146,7 @@ export function DataProvider() {
// Auto-start Local API Server on app startup if enabled // Auto-start Local API Server on app startup if enabled
useEffect(() => { useEffect(() => {
if (runOnStartup) { if (enableOnStartup) {
// Validate API key before starting // Validate API key before starting
if (!apiKey || apiKey.toString().trim().length === 0) { if (!apiKey || apiKey.toString().trim().length === 0) {
console.warn('Cannot start Local API Server: API key is required') console.warn('Cannot start Local API Server: API key is required')

View File

@ -13,6 +13,9 @@ import { TrustedHostsInput } from '@/containers/TrustedHostsInput'
import { useLocalApiServer } from '@/hooks/useLocalApiServer' import { useLocalApiServer } from '@/hooks/useLocalApiServer'
import { WebviewWindow } from '@tauri-apps/api/webviewWindow' import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
import { useAppState } from '@/hooks/useAppState' import { useAppState } from '@/hooks/useAppState'
import { useModelProvider } from '@/hooks/useModelProvider'
import { startModel } from '@/services/models'
import { localStorageKey } from '@/constants/localStorage'
import { windowKey } from '@/constants/windows' import { windowKey } from '@/constants/windows'
import { IconLogs } from '@tabler/icons-react' import { IconLogs } from '@tabler/icons-react'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
@ -32,8 +35,8 @@ function LocalAPIServer() {
setCorsEnabled, setCorsEnabled,
verboseLogs, verboseLogs,
setVerboseLogs, setVerboseLogs,
runOnStartup, enableOnStartup,
setRunOnStartup, setEnableOnStartup,
serverHost, serverHost,
serverPort, serverPort,
apiPrefix, apiPrefix,
@ -42,6 +45,7 @@ function LocalAPIServer() {
} = useLocalApiServer() } = useLocalApiServer()
const { serverStatus, setServerStatus } = useAppState() const { serverStatus, setServerStatus } = useAppState()
const { selectedModel, selectedProvider, getProviderByName } = useModelProvider()
const [showApiKeyError, setShowApiKeyError] = useState(false) const [showApiKeyError, setShowApiKeyError] = useState(false)
const [isApiKeyEmpty, setIsApiKeyEmpty] = useState( const [isApiKeyEmpty, setIsApiKeyEmpty] = useState(
!apiKey || apiKey.toString().trim().length === 0 !apiKey || apiKey.toString().trim().length === 0
@ -62,6 +66,54 @@ function LocalAPIServer() {
setIsApiKeyEmpty(!isValid) setIsApiKeyEmpty(!isValid)
} }
const getLastUsedModel = (): { provider: string; model: string } | null => {
try {
const stored = localStorage.getItem(localStorageKey.lastUsedModel)
return stored ? JSON.parse(stored) : null
} catch (error) {
console.debug('Failed to get last used model from localStorage:', error)
return null
}
}
// Helper function to determine which model to start
const getModelToStart = () => {
// Use last used model if available
const lastUsedModel = getLastUsedModel()
if (lastUsedModel) {
const provider = getProviderByName(lastUsedModel.provider)
if (
provider &&
provider.models.some((m) => m.id === lastUsedModel.model)
) {
return { model: lastUsedModel.model, provider }
}
}
// Use selected model if available
if (selectedModel && selectedProvider) {
const provider = getProviderByName(selectedProvider)
if (provider) {
return { model: selectedModel.id, provider }
}
}
// Use first model from llamacpp provider
const llamacppProvider = getProviderByName('llamacpp')
if (
llamacppProvider &&
llamacppProvider.models &&
llamacppProvider.models.length > 0
) {
return {
model: llamacppProvider.models[0].id,
provider: llamacppProvider,
}
}
return null
}
const toggleAPIServer = async () => { const toggleAPIServer = async () => {
// Validate API key before starting server // Validate API key before starting server
if (serverStatus === 'stopped') { if (serverStatus === 'stopped') {
@ -70,19 +122,33 @@ function LocalAPIServer() {
return return
} }
setShowApiKeyError(false) setShowApiKeyError(false)
}
setServerStatus('pending') const modelToStart = getModelToStart()
if (serverStatus === 'stopped') { // Only start server if we have a model to load
window.core?.api if (!modelToStart) {
?.startServer({ console.warn(
host: serverHost, 'Cannot start Local API Server: No model available to load'
port: serverPort, )
prefix: apiPrefix, return
apiKey, }
trustedHosts,
isCorsEnabled: corsEnabled, setServerStatus('pending')
isVerboseEnabled: verboseLogs,
// Start the model first
startModel(modelToStart.provider, modelToStart.model)
.then(() => {
console.log(`Model ${modelToStart.model} started successfully`)
// Then start the server
return window.core?.api?.startServer({
host: serverHost,
port: serverPort,
prefix: apiPrefix,
apiKey,
trustedHosts,
isCorsEnabled: corsEnabled,
isVerboseEnabled: verboseLogs,
})
}) })
.then(() => { .then(() => {
setServerStatus('running') setServerStatus('running')
@ -92,6 +158,7 @@ function LocalAPIServer() {
setServerStatus('stopped') setServerStatus('stopped')
}) })
} else { } else {
setServerStatus('pending')
window.core?.api window.core?.api
?.stopServer() ?.stopServer()
.then(() => { .then(() => {
@ -208,13 +275,13 @@ function LocalAPIServer() {
description={t('settings:localApiServer.runOnStartupDesc')} description={t('settings:localApiServer.runOnStartupDesc')}
actions={ actions={
<Switch <Switch
checked={runOnStartup} checked={enableOnStartup}
onCheckedChange={(checked) => { onCheckedChange={(checked) => {
if (!apiKey || apiKey.toString().trim().length === 0) { if (!apiKey || apiKey.toString().trim().length === 0) {
setShowApiKeyError(true) setShowApiKeyError(true)
return return
} }
setRunOnStartup(checked) setEnableOnStartup(checked)
}} }}
/> />
} }