refactor(skills): add skill-adapter and refactor SkillMarket

- Add skill-adapter.ts to bridge configStore and UI skill formats
- Refactor SkillMarket to use new skill-adapter instead of skill-discovery
- Add health check state to connectionStore
- Update multiple components with improved typing
- Clean up test artifacts and add new test results
- Update README and add skill-market-mvp plan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-21 00:28:03 +08:00
parent 54ccc0a7b0
commit 48a430fc97
50 changed files with 1523 additions and 360 deletions

View File

@@ -1,12 +1,19 @@
import { useState, useEffect } from 'react';
import { useGatewayStore } from '../../store/gatewayStore';
import { useConnectionStore } from '../../store/connectionStore';
import { useConfigStore } from '../../store/configStore';
import { useChatStore } from '../../store/chatStore';
import { getStoredGatewayToken, setStoredGatewayToken } from '../../lib/gateway-client';
import { silentErrorHandler } from '../../lib/error-utils';
export function General() {
const { connectionState, gatewayVersion, error, connect, disconnect, quickConfig, saveQuickConfig } = useGatewayStore();
const { currentModel } = useChatStore();
const connectionState = useConnectionStore((s) => s.connectionState);
const gatewayVersion = useConnectionStore((s) => s.gatewayVersion);
const error = useConnectionStore((s) => s.error);
const connect = useConnectionStore((s) => s.connect);
const disconnect = useConnectionStore((s) => s.disconnect);
const quickConfig = useConfigStore((s) => s.quickConfig);
const saveQuickConfig = useConfigStore((s) => s.saveQuickConfig);
const currentModel = useChatStore((s) => s.currentModel);
const [theme, setTheme] = useState<'light' | 'dark'>(quickConfig.theme || 'light');
const [autoStart, setAutoStart] = useState(quickConfig.autoStart ?? false);
const [showToolCalls, setShowToolCalls] = useState(quickConfig.showToolCalls ?? false);

View File

@@ -1,6 +1,8 @@
import { useEffect } from 'react';
import { Radio, RefreshCw, MessageCircle, Settings2 } from 'lucide-react';
import { useGatewayStore } from '../../store/gatewayStore';
import { useConnectionStore } from '../../store/connectionStore';
import { useConfigStore } from '../../store/configStore';
import { useAgentStore } from '../../store/agentStore';
const CHANNEL_ICONS: Record<string, string> = {
feishu: '飞',
@@ -9,7 +11,10 @@ const CHANNEL_ICONS: Record<string, string> = {
};
export function IMChannels() {
const { channels, connectionState, loadChannels, loadPluginStatus } = useGatewayStore();
const channels = useConfigStore((s) => s.channels);
const loadChannels = useConfigStore((s) => s.loadChannels);
const connectionState = useConnectionStore((s) => s.connectionState);
const loadPluginStatus = useAgentStore((s) => s.loadPluginStatus);
const connected = connectionState === 'connected';
const loading = connectionState === 'connecting' || connectionState === 'reconnecting' || connectionState === 'handshaking';

View File

@@ -1,6 +1,7 @@
import { useState, useEffect } from 'react';
import { getStoredGatewayToken, getStoredGatewayUrl } from '../../lib/gateway-client';
import { useGatewayStore } from '../../store/gatewayStore';
import { useConnectionStore } from '../../store/connectionStore';
import { useConfigStore } from '../../store/configStore';
import { useChatStore } from '../../store/chatStore';
import { silentErrorHandler } from '../../lib/error-utils';
import { Plus, Pencil, Trash2, Star, Eye, EyeOff, AlertCircle, X } from 'lucide-react';
@@ -53,7 +54,11 @@ function saveCustomModels(models: CustomModel[]): void {
}
export function ModelsAPI() {
const { connectionState, connect, disconnect, quickConfig, loadModels } = useGatewayStore();
const connectionState = useConnectionStore((s) => s.connectionState);
const connect = useConnectionStore((s) => s.connect);
const disconnect = useConnectionStore((s) => s.disconnect);
const quickConfig = useConfigStore((s) => s.quickConfig);
const loadModels = useConfigStore((s) => s.loadModels);
const { currentModel, setCurrentModel } = useChatStore();
const [gatewayUrl, setGatewayUrl] = useState(getStoredGatewayUrl());
const [gatewayToken, setGatewayToken] = useState(quickConfig.gatewayToken || getStoredGatewayToken());

View File

@@ -1,5 +1,5 @@
import { useState } from 'react';
import { useGatewayStore } from '../../store/gatewayStore';
import { useSecurityStore } from '../../store/securityStore';
import {
Settings as SettingsIcon,
BarChart3,
@@ -15,6 +15,7 @@ import {
HelpCircle,
ClipboardList,
Clock,
Heart,
} from 'lucide-react';
import { silentErrorHandler } from '../../lib/error-utils';
import { General } from './General';
@@ -31,6 +32,7 @@ import { AuditLogsPanel } from '../AuditLogsPanel';
import { SecurityStatus } from '../SecurityStatus';
import { SecurityLayersPanel } from '../SecurityLayersPanel';
import { TaskList } from '../TaskList';
import { HeartbeatConfig } from '../HeartbeatConfig';
interface SettingsLayoutProps {
onBack: () => void;
@@ -49,6 +51,7 @@ type SettingsPage =
| 'security'
| 'audit'
| 'tasks'
| 'heartbeat'
| 'feedback'
| 'about';
@@ -65,13 +68,14 @@ const menuItems: { id: SettingsPage; label: string; icon: React.ReactNode }[] =
{ id: 'security', label: '安全状态', icon: <Shield className="w-4 h-4" /> },
{ id: 'audit', label: '审计日志', icon: <ClipboardList className="w-4 h-4" /> },
{ id: 'tasks', label: '定时任务', icon: <Clock className="w-4 h-4" /> },
{ id: 'heartbeat', label: '心跳配置', icon: <Heart className="w-4 h-4" /> },
{ id: 'feedback', label: '提交反馈', icon: <HelpCircle className="w-4 h-4" /> },
{ id: 'about', label: '关于', icon: <Info className="w-4 h-4" /> },
];
export function SettingsLayout({ onBack }: SettingsLayoutProps) {
const [activePage, setActivePage] = useState<SettingsPage>('general');
const { securityStatus } = useGatewayStore();
const securityStatus = useSecurityStore((s) => s.securityStatus);
const renderPage = () => {
switch (activePage) {
@@ -112,6 +116,11 @@ export function SettingsLayout({ onBack }: SettingsLayoutProps) {
</div>
</div>
);
case 'heartbeat': return (
<div className="max-w-3xl h-full">
<HeartbeatConfig />
</div>
);
case 'feedback': return <Feedback />;
case 'about': return <About />;
default: return <General />;

View File

@@ -1,5 +1,6 @@
import { useEffect, useState } from 'react';
import { useGatewayStore } from '../../store/gatewayStore';
import { useConnectionStore } from '../../store/connectionStore';
import { useConfigStore } from '../../store/configStore';
import { silentErrorHandler } from '../../lib/error-utils';
import { Wrench, Zap, FileCode, Globe, Mail, Database, Search, MessageSquare } from 'lucide-react';
@@ -64,7 +65,11 @@ const SYSTEM_SKILLS = [
];
export function Skills() {
const { connectionState, quickConfig, skillsCatalog, loadSkillsCatalog, saveQuickConfig } = useGatewayStore();
const connectionState = useConnectionStore((s) => s.connectionState);
const quickConfig = useConfigStore((s) => s.quickConfig);
const skillsCatalog = useConfigStore((s) => s.skillsCatalog);
const loadSkillsCatalog = useConfigStore((s) => s.loadSkillsCatalog);
const saveQuickConfig = useConfigStore((s) => s.saveQuickConfig);
const connected = connectionState === 'connected';
const [extraDir, setExtraDir] = useState('');
const [activeFilter, setActiveFilter] = useState<'all' | 'system' | 'builtin' | 'extra'>('all');