import { useEffect, useState } from 'react'; export interface HumanPreferences { language: 'system' | 'zh-CN' | 'en'; font: 'system' | 'serif' | 'accessible'; readingSize: number; appearance: 'lake-night' | 'mist-light' | 'deep-night'; } export const DEFAULT_HUMAN_PREFERENCES: HumanPreferences = { language: 'system', font: 'system', readingSize: 17, appearance: 'lake-night', }; const STORAGE_KEY = 'hololake.human-preferences.v1'; export function loadHumanPreferences(): HumanPreferences { try { const stored = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); const appearance = stored.appearance === 'eternal-lake' ? 'lake-night' : stored.appearance; return { ...DEFAULT_HUMAN_PREFERENCES, ...stored, appearance: appearance || DEFAULT_HUMAN_PREFERENCES.appearance }; } catch { return DEFAULT_HUMAN_PREFERENCES; } } interface Props { open: boolean; preferences: HumanPreferences; onClose: () => void; onChange: (preferences: HumanPreferences) => void; onManageServer: () => void; onAgentChanged?: () => void; } export function HumanSettings({ open, preferences, onClose, onChange, onManageServer, onAgentChanged }: Props) { const [draft, setDraft] = useState(preferences); const [modelBaseUrl, setModelBaseUrl] = useState('https://api.openai.com/v1'); const [modelName, setModelName] = useState('gpt-4o'); const [modelKey, setModelKey] = useState(''); const [modelConfigured, setModelConfigured] = useState(false); const [modelOperational, setModelOperational] = useState(false); const [modelBusy, setModelBusy] = useState(false); const [modelMessage, setModelMessage] = useState(''); useEffect(() => { if (!open) return; setDraft(preferences); const agent = (window as any).hololake?.agent; if (!agent?.getConfig) return; agent.getConfig().then((config: any) => { setModelBaseUrl(config.baseUrl || 'https://api.openai.com/v1'); setModelName(config.model || 'gpt-4o'); setModelConfigured(Boolean(config.configured)); setModelOperational(Boolean(config.operational)); setModelMessage(config.operational ? '模型服务已验证可用' : config.configured ? '密钥已保存,尚未通过连通验证' : '尚未配置模型服务'); }).catch(() => setModelMessage('无法读取模型配置')); }, [open, preferences]); async function saveAndVerifyModel() { const agent = (window as any).hololake?.agent; if (!agent?.saveConfig || !agent?.testConfig) { setModelMessage('模型配置只在 HoloLake 桌面 App 中提供'); return; } setModelBusy(true); setModelMessage('正在保存并验证模型服务…'); try { await agent.saveConfig({ baseUrl: modelBaseUrl, model: modelName, apiKey: modelKey || undefined }); setModelKey(''); setModelConfigured(true); await agent.testConfig(); setModelOperational(true); setModelMessage('模型服务已验证可用'); onAgentChanged?.(); } catch (error) { setModelOperational(false); setModelMessage(error instanceof Error ? error.message : String(error)); onAgentChanged?.(); } finally { setModelBusy(false); } } if (!open) return null; function save() { localStorage.setItem(STORAGE_KEY, JSON.stringify(draft)); onChange(draft); onClose(); } return (
安装包不包含知识库、服务器令牌、模型密钥或个人设置。服务器仓库只显示当前账号有权访问的内容。