refactor: 移除多余依赖,统一 MUI 为唯一 UI 库
- 移除 radix-ui、clsx、tailwind-merge、class-variance-authority、react-router-dom - 前后端全面适配 MUI 组件,清理残留 Tailwind 工具类引用 - 优化 Agent Loop 引擎、IPC 处理器、Provider Adapter 等后端模块 - 新增 Agent 网络工具通用设计文档 v2
This commit is contained in:
@@ -25,8 +25,8 @@ export function SettingsModal(): React.JSX.Element | null {
|
||||
if (!settingsOpen) return null;
|
||||
|
||||
return (
|
||||
<Dialog open onClose={closeSettings} maxWidth="md" fullWidth PaperProps={{ sx: { maxWidth: 640, height: '80vh', borderRadius: 3, display: 'flex', flexDirection: 'column' } }}>
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ px: 2.5, py: 1.5, borderBottom: 1, borderColor: 'divider' }}>
|
||||
<Dialog open onClose={closeSettings} maxWidth="md" fullWidth slotProps={{ paper: { sx: { maxWidth: 640, height: '80vh', borderRadius: 3, display: 'flex', flexDirection: 'column' } } }}>
|
||||
<Stack direction="row" sx={{ px: 2.5, py: 1.5, borderBottom: 1, borderColor: 'divider', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Typography variant="h6">设置</Typography>
|
||||
<IconButton size="small" onClick={closeSettings}><X size={14} /></IconButton>
|
||||
</Stack>
|
||||
@@ -60,8 +60,8 @@ export function SettingsModal(): React.JSX.Element | null {
|
||||
|
||||
function useConfig<T>(key: string, defaultValue: T): [T, (v: T) => void] {
|
||||
const [value, setValue] = useState<T>(defaultValue);
|
||||
useEffect(() => { if (window.metona?.config?.get) window.metona.config.get(key).then((v) => { if (v != null) setValue(v as T); }).catch(() => {}); }, [key]);
|
||||
const set = useCallback((v: T) => { setValue(v); window.metona?.config?.set(key, v).catch(() => {}); }, [key]);
|
||||
useEffect(() => { if (window.metona?.config?.get) window.metona.config.get(key).then((v) => { if (v != null) setValue(v as T); }).catch((err) => { console.error('[SettingsModal]', err); }); }, [key]);
|
||||
const set = useCallback((v: T) => { setValue(v); window.metona?.config?.set(key, v).catch((err) => { console.error('[SettingsModal]', err); }); }, [key]);
|
||||
return [value, set];
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ function WorkspaceSettings() {
|
||||
<Stack spacing={2}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>工作空间</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'text.secondary' }}>工作空间是 Metona 的组织核心,包含 SOUL.md、AGENTS.md、MEMORY.md、USERS.md 四个必需文件。</Typography>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
||||
<TextField size="small" value={workspacePath} onChange={(e) => setWorkspacePath(e.target.value)} placeholder="~/MetonaWorkspaces/default/" sx={{ flex: 1 }} />
|
||||
<Button variant="outlined" size="small" onClick={handleSelect}>选择文件夹</Button>
|
||||
</Stack>
|
||||
@@ -193,20 +193,20 @@ function AgentSettings() {
|
||||
|
||||
function ToolsSettings() {
|
||||
const [tools, setTools] = useState<Array<{ name: string; description: string; riskLevel: string; enabled: boolean }>>([]);
|
||||
useEffect(() => { if (window.metona?.tools?.list) window.metona.tools.list().then((l) => setTools((l as any[]).map((t) => ({ ...t, enabled: true })))).catch(() => {}); }, []);
|
||||
const handleToggle = (name: string, enabled: boolean) => { setTools((p) => p.map((t) => t.name === name ? { ...t, enabled } : t)); window.metona?.tools?.toggle(name, enabled).catch(() => {}); };
|
||||
useEffect(() => { if (window.metona?.tools?.list) window.metona.tools.list().then((l) => setTools((l as MetonaToolInfo[]).map((t) => ({ ...t, enabled: true })))).catch((err) => { console.error('[SettingsModal]', err); }); }, []);
|
||||
const handleToggle = (name: string, enabled: boolean) => { setTools((p) => p.map((t) => t.name === name ? { ...t, enabled } : t)); window.metona?.tools?.toggle(name, enabled).catch((err) => { console.error('[SettingsModal]', err); }); };
|
||||
const riskColors: Record<string, 'success' | 'info' | 'warning' | 'error'> = { safe: 'success', low: 'info', medium: 'warning', high: 'error' };
|
||||
|
||||
return (
|
||||
<Stack spacing={2}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>工具管理</Typography>
|
||||
{tools.length === 0 ? <Typography variant="caption" sx={{ textAlign: 'center', py: 4, color: 'text.secondary' }}>加载中...</Typography> : tools.map((t) => (
|
||||
<Stack key={t.name} direction="row" alignItems="center" justifyContent="space-between" sx={{ py: 1, px: 1.5, borderRadius: 1.5, bgcolor: 'secondary.main' }}>
|
||||
<Stack direction="row" spacing={1} alignItems="center" sx={{ minWidth: 0, flex: 1 }}>
|
||||
<Stack key={t.name} direction="row" sx={{ py: 1, px: 1.5, borderRadius: 1.5, bgcolor: 'secondary.main', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Stack direction="row" spacing={1} sx={{ minWidth: 0, flex: 1, alignItems: 'center' }}>
|
||||
<Typography variant="body2" sx={{ fontFamily: 'monospace', fontSize: 12 }}>{t.name}</Typography>
|
||||
<Typography variant="caption" sx={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{t.description.slice(0, 40)}</Typography>
|
||||
</Stack>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
||||
<Chip label={t.riskLevel.toUpperCase()} size="small" color={riskColors[t.riskLevel]} variant="outlined" sx={{ height: 18, fontSize: 9 }} />
|
||||
<Checkbox checked={t.enabled} onChange={(e) => handleToggle(t.name, e.target.checked)} size="small" />
|
||||
</Stack>
|
||||
@@ -222,17 +222,17 @@ function MCPSettings() {
|
||||
const [newName, setNewName] = useState('');
|
||||
const [newCommand, setNewCommand] = useState('');
|
||||
const [newArgs, setNewArgs] = useState('');
|
||||
const loadServers = () => { if (window.metona?.mcp?.listServers) window.metona.mcp.listServers().then((l) => setServers(l as any[])).catch(() => {}); };
|
||||
const loadServers = () => { if (window.metona?.mcp?.listServers) window.metona.mcp.listServers().then((l) => setServers(l as MetonaMCPServerStatus[])).catch((err) => { console.error('[SettingsModal]', err); }); };
|
||||
useEffect(() => { loadServers(); }, []);
|
||||
const handleAdd = async () => { if (!newName.trim() || !newCommand.trim()) return; await window.metona?.mcp?.addServer({ name: newName.trim(), transport: 'stdio', command: newCommand.trim(), args: newArgs.trim() ? newArgs.trim().split(/\s+/) : [] }); setNewName(''); setNewCommand(''); setNewArgs(''); setShowAdd(false); loadServers(); };
|
||||
const handleAdd = async () => { if (!newName.trim() || !newCommand.trim()) return; await window.metona?.mcp?.addServer({ name: newName.trim(), transport: 'stdio', command: newCommand.trim(), args: newArgs.trim() ? newArgs.trim().split(/\s+/) : [], enabled: true }); setNewName(''); setNewCommand(''); setNewArgs(''); setShowAdd(false); loadServers(); };
|
||||
const statusColors: Record<string, string> = { connected: 'success.main', connecting: 'warning.main', disconnected: 'text.secondary', error: 'error.main' };
|
||||
|
||||
return (
|
||||
<Stack spacing={2}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>MCP 服务</Typography>
|
||||
{servers.length === 0 ? <Typography variant="caption" sx={{ textAlign: 'center', py: 4, color: 'text.secondary' }}>暂无 MCP 服务</Typography> : servers.map((s) => (
|
||||
<Stack key={s.name} direction="row" alignItems="center" justifyContent="space-between" sx={{ py: 1, px: 1.5, borderRadius: 1.5, bgcolor: 'secondary.main' }}>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<Stack key={s.name} direction="row" sx={{ py: 1, px: 1.5, borderRadius: 1.5, bgcolor: 'secondary.main', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
||||
<Box sx={{ width: 8, height: 8, borderRadius: '50', bgcolor: statusColors[s.status] }} />
|
||||
<Typography variant="body2" sx={{ fontWeight: 500 }}>{s.name}</Typography>
|
||||
<Typography variant="caption" sx={{ color: statusColors[s.status] }}>{s.status}</Typography>
|
||||
|
||||
Reference in New Issue
Block a user