feat(ui): Phase 8 UI/UX optimization and system documentation update

## Sidebar Enhancement
- Change tabs to icon + small label layout for better space utilization
- Add Teams tab with team collaboration entry point

## Settings Page Improvements
- Connect theme toggle to gatewayStore.saveQuickConfig for persistence
- Remove OpenFang backend download section, simplify UI
- Add time range filter to UsageStats (7d/30d/all)
- Add stat cards with icons (sessions, messages, input/output tokens)
- Add token usage overview bar chart
- Add 8 ZCLAW system skill definitions with categories

## Bug Fixes
- Fix ChannelList duplicate content with deduplication logic
- Integrate CreateTriggerModal in TriggersPanel
- Add independent SecurityStatusPanel with 12 default enabled layers
- Change workflow view to use SchedulerPanel as unified entry

## New Components
- CreateTriggerModal: Event trigger creation modal
- HandApprovalModal: Hand approval workflow dialog
- HandParamsForm: Enhanced Hand parameter form
- SecurityLayersPanel: 16-layer security status display

## Architecture
- Add TOML config parsing support (toml-utils.ts, config-parser.ts)
- Add request timeout and retry mechanism (request-helper.ts)
- Add secure token storage (secure-storage.ts, secure_storage.rs)

## Tests
- Add unit tests for config-parser, toml-utils, request-helper
- Add team-client and teamStore tests

## Documentation
- Update SYSTEM_ANALYSIS.md with Phase 8 completion
- UI completion: 100% (30/30 components)
- API coverage: 93% (63/68 endpoints)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-15 14:12:11 +08:00
parent bf79c06d4a
commit 3e81bd3e50
30 changed files with 8875 additions and 284 deletions

View File

@@ -0,0 +1,104 @@
/**
* Test script to verify TOML parsing with actual config files
*/
import TOML from 'smol-toml';
// Use inline TOML strings for testing
const MAIN_CONFIG_TOML = `
[server]
host = "127.0.0.1"
port = 4200
websocket_port = 4200
websocket_path = "/ws"
[agent.defaults]
workspace = "~/.openfang/workspace"
default_model = "gpt-4"
[llm]
default_provider = "openai"
default_model = "gpt-4"
`;
const CHINESE_PROVIDERS_TOML = `
[[llm.providers]]
name = "zhipu"
display_name = "Zhipu GLM"
api_key = "\${ZHIPU_API_KEY}"
base_url = "https://open.bigmodel.cn/api/paas/v4"
[[llm.providers.models]]
id = "glm-4-plus"
alias = "GLM-4-Plus"
context_window = 128000
[[llm.providers]]
name = "qwen"
display_name = "Qwen"
api_key = "\${QWEN_API_KEY}"
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"
[[llm.providers.models]]
id = "qwen-max"
alias = "Qwen-Max"
`;
console.log('=== Testing TOML Parsing ===\n');
// Test 1: Parse main config
try {
console.log('\n--- Test 1: Main config.toml ---');
const mainConfig = TOML.parse(MAIN_CONFIG_TOML);
console.log('Parsed successfully!');
console.log('Server config:', JSON.stringify(mainConfig.server, null, 2));
console.log('Agent defaults:', JSON.stringify(mainConfig.agent?.defaults, null, 2));
console.log('LLM config:', JSON.stringify(mainConfig.llm, null, 2));
// Check required fields
if (!mainConfig.server?.host) throw new Error('Missing server.host');
if (!mainConfig.server?.port) throw new Error('Missing server.port');
if (!mainConfig.agent?.defaults?.workspace) throw new Error('Missing agent.defaults.workspace');
if (!mainConfig.agent?.defaults?.default_model) throw new Error('Missing agent.defaults.default_model');
if (!mainConfig.llm?.default_provider) throw new Error('Missing llm.default_provider');
if (!mainConfig.llm?.default_model) throw new Error('Missing llm.default_model');
console.log('All required fields present!');
} catch (error) {
console.error('Failed to parse main config:', error.message);
process.exit(1);
}
// Test 2: Parse chinese-providers.toml
try {
console.log('\n--- Test 2: chinese-providers.toml ---');
const chineseProviders = TOML.parse(CHINESE_PROVIDERS_TOML);
console.log('Parsed successfully!');
console.log('Number of providers:', chineseProviders.llm?.providers?.length || 0);
// List providers
if (chineseProviders.llm?.providers) {
console.log('\nProviders found:');
chineseProviders.llm.providers.forEach((provider, index) => {
console.log(` ${index + 1}. ${provider.name} (${provider.display_name || 'N/A'})`);
if (provider.models) {
console.log(` Models: ${provider.models.length}`);
}
});
}
// Check for environment variable references
const envVarPattern = /\$\{([^}]+)\}/g;
const envVars = CHINESE_PROVIDERS_TOML.match(envVarPattern);
if (envVars) {
console.log('\nEnvironment variables referenced:');
const uniqueVars = [...new Set(envVars)];
uniqueVars.forEach(v => console.log(` - ${v}`));
}
} catch (error) {
console.error('Failed to parse chinese-providers:', error.message);
process.exit(1);
}
console.log('\n=== All TOML parsing tests passed! ===\n');