refactor: 统一项目名称从OpenFang到ZCLAW
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
重构所有代码和文档中的项目名称,将OpenFang统一更新为ZCLAW。包括: - 配置文件中的项目名称 - 代码注释和文档引用 - 环境变量和路径 - 类型定义和接口名称 - 测试用例和模拟数据 同时优化部分代码结构,移除未使用的模块,并更新相关依赖项。
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* VikingPanel - OpenViking Semantic Memory UI
|
||||
* VikingPanel - ZCLAW Semantic Memory UI
|
||||
*
|
||||
* Provides interface for semantic search and knowledge base management.
|
||||
* OpenViking is an optional sidecar for semantic memory operations.
|
||||
* Uses native Rust SqliteStorage with TF-IDF semantic search.
|
||||
*/
|
||||
import { useState, useEffect } from 'react';
|
||||
import {
|
||||
@@ -11,16 +11,13 @@ import {
|
||||
AlertCircle,
|
||||
CheckCircle,
|
||||
FileText,
|
||||
Server,
|
||||
Play,
|
||||
Square,
|
||||
Database,
|
||||
} from 'lucide-react';
|
||||
import {
|
||||
getVikingStatus,
|
||||
findVikingResources,
|
||||
getVikingServerStatus,
|
||||
startVikingServer,
|
||||
stopVikingServer,
|
||||
listVikingResources,
|
||||
readVikingResource,
|
||||
} from '../lib/viking-client';
|
||||
import type { VikingStatus, VikingFindResult } from '../lib/viking-client';
|
||||
|
||||
@@ -30,17 +27,28 @@ export function VikingPanel() {
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [searchResults, setSearchResults] = useState<VikingFindResult[]>([]);
|
||||
const [isSearching, setIsSearching] = useState(false);
|
||||
const [serverRunning, setServerRunning] = useState(false);
|
||||
const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
|
||||
const [memoryCount, setMemoryCount] = useState<number | null>(null);
|
||||
const [expandedUri, setExpandedUri] = useState<string | null>(null);
|
||||
const [expandedContent, setExpandedContent] = useState<string | null>(null);
|
||||
const [isLoadingL2, setIsLoadingL2] = useState(false);
|
||||
|
||||
const loadStatus = async () => {
|
||||
setIsLoading(true);
|
||||
setMessage(null);
|
||||
try {
|
||||
const vikingStatus = await getVikingStatus();
|
||||
setStatus(vikingStatus);
|
||||
|
||||
const serverStatus = await getVikingServerStatus();
|
||||
setServerRunning(serverStatus.running);
|
||||
if (vikingStatus.available) {
|
||||
// Load memory count
|
||||
try {
|
||||
const resources = await listVikingResources('/');
|
||||
setMemoryCount(resources.length);
|
||||
} catch {
|
||||
setMemoryCount(null);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load Viking status:', error);
|
||||
setStatus({ available: false, error: String(error) });
|
||||
@@ -74,22 +82,22 @@ export function VikingPanel() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleServerToggle = async () => {
|
||||
const handleExpandL2 = async (uri: string) => {
|
||||
if (expandedUri === uri) {
|
||||
setExpandedUri(null);
|
||||
setExpandedContent(null);
|
||||
return;
|
||||
}
|
||||
|
||||
setExpandedUri(uri);
|
||||
setIsLoadingL2(true);
|
||||
try {
|
||||
if (serverRunning) {
|
||||
await stopVikingServer();
|
||||
setServerRunning(false);
|
||||
setMessage({ type: 'success', text: '服务器已停止' });
|
||||
} else {
|
||||
await startVikingServer();
|
||||
setServerRunning(true);
|
||||
setMessage({ type: 'success', text: '服务器已启动' });
|
||||
}
|
||||
} catch (error) {
|
||||
setMessage({
|
||||
type: 'error',
|
||||
text: `操作失败: ${error instanceof Error ? error.message : '未知错误'}`,
|
||||
});
|
||||
const fullContent = await readVikingResource(uri, 'L2');
|
||||
setExpandedContent(fullContent);
|
||||
} catch {
|
||||
setExpandedContent(null);
|
||||
} finally {
|
||||
setIsLoadingL2(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -100,7 +108,7 @@ export function VikingPanel() {
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-gray-900 dark:text-white">语义记忆</h1>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
|
||||
OpenViking 语义搜索引擎
|
||||
ZCLAW 语义记忆搜索引擎
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2 items-center">
|
||||
@@ -125,10 +133,9 @@ export function VikingPanel() {
|
||||
<div className="flex items-start gap-2">
|
||||
<AlertCircle className="w-4 h-4 text-amber-500 mt-0.5" />
|
||||
<div className="text-xs text-amber-700 dark:text-amber-300">
|
||||
<p className="font-medium">OpenViking CLI 不可用</p>
|
||||
<p className="font-medium">语义记忆存储不可用</p>
|
||||
<p className="mt-1">
|
||||
请安装 OpenViking CLI 或设置{' '}
|
||||
<code className="bg-amber-100 dark:bg-amber-800 px-1 rounded">ZCLAW_VIKING_BIN</code> 环境变量。
|
||||
本地 SQLite 存储初始化失败。请检查数据目录权限后重启应用。
|
||||
</p>
|
||||
{status?.error && (
|
||||
<p className="mt-1 text-amber-600 dark:text-amber-400 font-mono text-xs">
|
||||
@@ -158,47 +165,37 @@ export function VikingPanel() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Server Control */}
|
||||
{/* Storage Info */}
|
||||
{status?.available && (
|
||||
<div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-4 mb-6 shadow-sm">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div
|
||||
className={`w-10 h-10 rounded-xl flex items-center justify-center ${
|
||||
serverRunning
|
||||
? 'bg-gradient-to-br from-green-500 to-emerald-500 text-white'
|
||||
: 'bg-gray-200 dark:bg-gray-700 text-gray-400'
|
||||
}`}
|
||||
>
|
||||
<Server className="w-4 h-4" />
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-blue-500 to-indigo-500 flex items-center justify-center">
|
||||
<Database className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-900 dark:text-white">
|
||||
本地存储
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-900 dark:text-white">
|
||||
Viking Server
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 dark:text-gray-400">
|
||||
{serverRunning ? '运行中' : '已停止'}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 dark:text-gray-400">
|
||||
{status.version || 'Native'} · {status.dataDir || '默认路径'}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleServerToggle}
|
||||
className={`px-4 py-2 rounded-lg flex items-center gap-2 text-sm transition-colors ${
|
||||
serverRunning
|
||||
? 'bg-red-100 text-red-600 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-400'
|
||||
: 'bg-green-100 text-green-600 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400'
|
||||
}`}
|
||||
>
|
||||
{serverRunning ? (
|
||||
<>
|
||||
<Square className="w-4 h-4" /> 停止
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Play className="w-4 h-4" /> 启动
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex gap-4 text-xs">
|
||||
<div className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300">
|
||||
<CheckCircle className="w-3.5 h-3.5 text-green-500" />
|
||||
<span>SQLite + FTS5</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300">
|
||||
<CheckCircle className="w-3.5 h-3.5 text-green-500" />
|
||||
<span>TF-IDF 语义评分</span>
|
||||
</div>
|
||||
{memoryCount !== null && (
|
||||
<div className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300">
|
||||
<CheckCircle className="w-3.5 h-3.5 text-green-500" />
|
||||
<span>{memoryCount} 条记忆</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -251,21 +248,43 @@ export function VikingPanel() {
|
||||
<span className="text-sm font-medium text-gray-900 dark:text-white truncate">
|
||||
{result.uri}
|
||||
</span>
|
||||
<span className="text-xs text-gray-400 bg-gray-100 dark:bg-gray-700 px-2 py-0.5 rounded">
|
||||
<span className={`text-xs px-2 py-0.5 rounded ${
|
||||
result.level === 'L1'
|
||||
? 'text-green-600 bg-green-100 dark:bg-green-900/30 dark:text-green-400'
|
||||
: 'text-gray-400 bg-gray-100 dark:bg-gray-700'
|
||||
}`}>
|
||||
{result.level}
|
||||
</span>
|
||||
<span className="text-xs text-blue-600 dark:text-blue-400">
|
||||
{Math.round(result.score * 100)}%
|
||||
</span>
|
||||
</div>
|
||||
{result.overview && (
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1 line-clamp-2">
|
||||
{result.overview}
|
||||
</p>
|
||||
)}
|
||||
<p className="text-xs text-gray-600 dark:text-gray-300 mt-2 line-clamp-3 font-mono">
|
||||
<p className="text-xs text-gray-600 dark:text-gray-300 mt-2 line-clamp-3">
|
||||
{result.content}
|
||||
</p>
|
||||
{result.level === 'L1' && (
|
||||
<button
|
||||
onClick={() => handleExpandL2(result.uri)}
|
||||
className="mt-1.5 text-xs text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300 transition-colors"
|
||||
>
|
||||
{expandedUri === result.uri ? '收起全文' : '展开全文'}
|
||||
</button>
|
||||
)}
|
||||
{expandedUri === result.uri && (
|
||||
<div className="mt-2 p-3 bg-gray-50 dark:bg-gray-900/50 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
{isLoadingL2 ? (
|
||||
<div className="flex items-center gap-2 text-xs text-gray-400">
|
||||
<RefreshCw className="w-3 h-3 animate-spin" /> 加载中...
|
||||
</div>
|
||||
) : expandedContent ? (
|
||||
<p className="text-xs text-gray-600 dark:text-gray-300 whitespace-pre-wrap font-mono">
|
||||
{expandedContent}
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-xs text-gray-400">加载失败</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -275,11 +294,11 @@ export function VikingPanel() {
|
||||
|
||||
{/* Info Section */}
|
||||
<div className="mt-6 p-4 bg-gray-50 dark:bg-gray-800/50 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<h3 className="text-sm font-medium text-gray-900 dark:text-white mb-2">关于 OpenViking</h3>
|
||||
<h3 className="text-sm font-medium text-gray-900 dark:text-white mb-2">关于语义记忆</h3>
|
||||
<ul className="text-xs text-gray-500 dark:text-gray-400 space-y-1">
|
||||
<li>• 语义搜索引擎,支持自然语言查询</li>
|
||||
<li>• 自动提取和索引知识资源</li>
|
||||
<li>• 支持多种文档格式和代码文件</li>
|
||||
<li>• 基于本地 SQLite + TF-IDF 的语义搜索引擎</li>
|
||||
<li>• 自动提取和索引对话中的知识资源</li>
|
||||
<li>• 支持自然语言查询知识库</li>
|
||||
<li>• 可作为本地知识库增强 AI 对话</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user