refactor(phase3): remove OpenClaw compatibility layer
Phase 3 Configuration Migration completed: - Remove OpenClaw backend type selector from General.tsx - Update default workspace path from ~/.openclaw to ~/.openfang - Update default port from 18789 to 50051 - Archive openclaw.default.json to docs/archive/openclaw-legacy/ - Remove OpenClaw migration UI from Workspace settings - Update About.tsx to reference OpenFang - Clean up gateway-client.ts comments All OpenClaw compatibility code removed. ZCLAW now exclusively targets OpenFang (Rust Agent OS) backend. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ interface CloneFormData {
|
|||||||
privacyOptIn: boolean;
|
privacyOptIn: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_WORKSPACE = '~/.openclaw/zclaw-workspace';
|
const DEFAULT_WORKSPACE = '~/.openfang/zclaw-workspace';
|
||||||
|
|
||||||
function createFormFromDraft(quickConfig: {
|
function createFormFromDraft(quickConfig: {
|
||||||
agentName?: string;
|
agentName?: string;
|
||||||
@@ -119,7 +119,7 @@ export function CloneManager() {
|
|||||||
role: '默认助手',
|
role: '默认助手',
|
||||||
nickname: a.name,
|
nickname: a.name,
|
||||||
scenarios: [],
|
scenarios: [],
|
||||||
workspaceDir: '~/.openclaw/zclaw-workspace',
|
workspaceDir: '~/.openfang/zclaw-workspace',
|
||||||
userName: quickConfig.userName || '未设置',
|
userName: quickConfig.userName || '未设置',
|
||||||
userRole: '',
|
userRole: '',
|
||||||
restrictFiles: true,
|
restrictFiles: true,
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ export function RightPanel() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AgentRow label="工作目录" value={selectedClone?.workspaceDir || workspaceInfo?.path || '~/.openclaw/zclaw-workspace'} />
|
<AgentRow label="工作目录" value={selectedClone?.workspaceDir || workspaceInfo?.path || '~/.openfang/zclaw-workspace'} />
|
||||||
<AgentRow label="解析目录" value={selectedClone?.workspaceResolvedPath || workspaceInfo?.resolvedPath || '-'} />
|
<AgentRow label="解析目录" value={selectedClone?.workspaceResolvedPath || workspaceInfo?.resolvedPath || '-'} />
|
||||||
<AgentRow label="文件限制" value={selectedClone?.restrictFiles ? '已开启' : '未开启'} />
|
<AgentRow label="文件限制" value={selectedClone?.restrictFiles ? '已开启' : '未开启'} />
|
||||||
<AgentRow label="优化计划" value={selectedClone?.privacyOptIn ? '已加入' : '未加入'} />
|
<AgentRow label="优化计划" value={selectedClone?.privacyOptIn ? '已加入' : '未加入'} />
|
||||||
@@ -546,7 +546,7 @@ function createAgentDraft(
|
|||||||
nickname: clone.nickname || '',
|
nickname: clone.nickname || '',
|
||||||
model: clone.model || currentModel,
|
model: clone.model || currentModel,
|
||||||
scenarios: clone.scenarios?.join(', ') || '',
|
scenarios: clone.scenarios?.join(', ') || '',
|
||||||
workspaceDir: clone.workspaceDir || '~/.openclaw/zclaw-workspace',
|
workspaceDir: clone.workspaceDir || '~/.openfang/zclaw-workspace',
|
||||||
userName: clone.userName || '',
|
userName: clone.userName || '',
|
||||||
userRole: clone.userRole || '',
|
userRole: clone.userRole || '',
|
||||||
restrictFiles: clone.restrictFiles ?? true,
|
restrictFiles: clone.restrictFiles ?? true,
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ export function About() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-12 text-center text-xs text-gray-400">
|
<div className="mt-12 text-center text-xs text-gray-400">
|
||||||
2026 ZCLAW | Powered by OpenClaw
|
2026 ZCLAW | Powered by OpenFang
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center text-xs text-gray-400 space-y-1">
|
<div className="text-center text-xs text-gray-400 space-y-1">
|
||||||
<p>基于 OpenClaw 开源框架定制</p>
|
<p>基于 OpenFang Rust Agent OS 构建</p>
|
||||||
<div className="flex justify-center gap-4 mt-3">
|
<div className="flex justify-center gap-4 mt-3">
|
||||||
<a href="#" className="text-orange-500 hover:text-orange-600">隐私政策</a>
|
<a href="#" className="text-orange-500 hover:text-orange-600">隐私政策</a>
|
||||||
<a href="#" className="text-orange-500 hover:text-orange-600">用户协议</a>
|
<a href="#" className="text-orange-500 hover:text-orange-600">用户协议</a>
|
||||||
|
|||||||
@@ -1,24 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useGatewayStore } from '../../store/gatewayStore';
|
import { useGatewayStore } from '../../store/gatewayStore';
|
||||||
import { useChatStore } from '../../store/chatStore';
|
import { useChatStore } from '../../store/chatStore';
|
||||||
import { getStoredGatewayToken, setStoredGatewayToken, setStoredGatewayUrl } from '../../lib/gateway-client';
|
import { getStoredGatewayToken, setStoredGatewayToken } from '../../lib/gateway-client';
|
||||||
|
|
||||||
type BackendType = 'openclaw' | 'openfang';
|
|
||||||
|
|
||||||
function getStoredBackendType(): BackendType {
|
|
||||||
try {
|
|
||||||
const stored = localStorage.getItem('zclaw-backend');
|
|
||||||
return (stored === 'openfang' || stored === 'openclaw') ? stored : 'openclaw';
|
|
||||||
} catch {
|
|
||||||
return 'openclaw';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setStoredBackendType(type: BackendType): void {
|
|
||||||
try {
|
|
||||||
localStorage.setItem('zclaw-backend', type);
|
|
||||||
} catch { /* ignore */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
export function General() {
|
export function General() {
|
||||||
const { connectionState, gatewayVersion, error, connect, disconnect } = useGatewayStore();
|
const { connectionState, gatewayVersion, error, connect, disconnect } = useGatewayStore();
|
||||||
@@ -26,7 +9,6 @@ export function General() {
|
|||||||
const [theme, setTheme] = useState<'light' | 'dark'>('light');
|
const [theme, setTheme] = useState<'light' | 'dark'>('light');
|
||||||
const [autoStart, setAutoStart] = useState(false);
|
const [autoStart, setAutoStart] = useState(false);
|
||||||
const [showToolCalls, setShowToolCalls] = useState(false);
|
const [showToolCalls, setShowToolCalls] = useState(false);
|
||||||
const [backendType, setBackendType] = useState<BackendType>(getStoredBackendType());
|
|
||||||
const [gatewayToken, setGatewayToken] = useState(getStoredGatewayToken());
|
const [gatewayToken, setGatewayToken] = useState(getStoredGatewayToken());
|
||||||
|
|
||||||
const connected = connectionState === 'connected';
|
const connected = connectionState === 'connected';
|
||||||
@@ -37,21 +19,6 @@ export function General() {
|
|||||||
};
|
};
|
||||||
const handleDisconnect = () => { disconnect(); };
|
const handleDisconnect = () => { disconnect(); };
|
||||||
|
|
||||||
const handleBackendChange = (type: BackendType) => {
|
|
||||||
setBackendType(type);
|
|
||||||
setStoredBackendType(type);
|
|
||||||
// Update Gateway URL when switching backend type
|
|
||||||
const newUrl = type === 'openfang'
|
|
||||||
? 'ws://127.0.0.1:50051/ws'
|
|
||||||
: 'ws://127.0.0.1:18789';
|
|
||||||
setStoredGatewayUrl(newUrl);
|
|
||||||
// Reconnect with new URL
|
|
||||||
disconnect();
|
|
||||||
setTimeout(() => {
|
|
||||||
connect(undefined, gatewayToken || undefined).catch(() => {});
|
|
||||||
}, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-bold text-gray-900 mb-8">通用设置</h1>
|
<h1 className="text-2xl font-bold text-gray-900 mb-8">通用设置</h1>
|
||||||
@@ -69,7 +36,7 @@ export function General() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-700">地址</span>
|
<span className="text-sm text-gray-700">地址</span>
|
||||||
<span className="text-sm text-gray-500 font-mono">{backendType === 'openfang' ? 'ws://127.0.0.1:50051' : 'ws://127.0.0.1:18789'}</span>
|
<span className="text-sm text-gray-500 font-mono">ws://127.0.0.1:50051</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-700">Token</span>
|
<span className="text-sm text-gray-700">Token</span>
|
||||||
@@ -153,39 +120,23 @@ export function General() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="text-sm font-medium text-gray-500 uppercase tracking-wide mb-3 mt-6">后端设置</h2>
|
<h2 className="text-sm font-medium text-gray-500 uppercase tracking-wide mb-3 mt-6">OpenFang 后端</h2>
|
||||||
<div className="bg-gray-50 rounded-xl p-5 space-y-4">
|
<div className="bg-gray-50 rounded-xl p-5 space-y-4">
|
||||||
<div className="flex justify-between items-center">
|
|
||||||
<div>
|
|
||||||
<div className="text-sm font-medium text-gray-900">Gateway 类型</div>
|
|
||||||
<div className="text-xs text-gray-500 mt-0.5">选择 OpenClaw (TypeScript) 或 OpenFang (Rust) 后端。</div>
|
|
||||||
</div>
|
|
||||||
<select
|
|
||||||
value={backendType}
|
|
||||||
onChange={(e) => handleBackendChange(e.target.value as BackendType)}
|
|
||||||
className="px-3 py-1.5 border border-gray-200 rounded-lg text-sm bg-white focus:outline-none focus:ring-2 focus:ring-orange-500 text-gray-700"
|
|
||||||
>
|
|
||||||
<option value="openclaw">OpenClaw (TypeScript)</option>
|
|
||||||
<option value="openfang">OpenFang (Rust)</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-700">默认端口</span>
|
<span className="text-sm text-gray-700">默认端口</span>
|
||||||
<span className="text-sm text-gray-500 font-mono">{backendType === 'openfang' ? '50051' : '18789'}</span>
|
<span className="text-sm text-gray-500 font-mono">50051</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-700">协议</span>
|
<span className="text-sm text-gray-700">协议</span>
|
||||||
<span className="text-sm text-gray-500">{backendType === 'openfang' ? 'WebSocket + REST API' : 'WebSocket RPC'}</span>
|
<span className="text-sm text-gray-500">WebSocket + REST API</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm text-gray-700">配置格式</span>
|
<span className="text-sm text-gray-700">配置格式</span>
|
||||||
<span className="text-sm text-gray-500">{backendType === 'openfang' ? 'TOML' : 'JSON/YAML'}</span>
|
<span className="text-sm text-gray-500">TOML</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-blue-700 bg-blue-50 rounded-lg p-3">
|
||||||
|
OpenFang 提供 7 个自主能力包 (Hands)、工作流引擎、16 层安全防护。需下载 OpenFang 运行时。
|
||||||
</div>
|
</div>
|
||||||
{backendType === 'openfang' && (
|
|
||||||
<div className="text-xs text-blue-700 bg-blue-50 rounded-lg p-3">
|
|
||||||
OpenFang 提供 7 个自主能力包 (Hands)、工作流引擎、16 层安全防护。需下载 OpenFang 运行时。
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export function ModelsAPI() {
|
|||||||
const handleReconnect = () => {
|
const handleReconnect = () => {
|
||||||
disconnect();
|
disconnect();
|
||||||
setTimeout(() => connect(
|
setTimeout(() => connect(
|
||||||
gatewayUrl || quickConfig.gatewayUrl || 'ws://127.0.0.1:18789',
|
gatewayUrl || quickConfig.gatewayUrl || 'ws://127.0.0.1:50051/ws',
|
||||||
gatewayToken || quickConfig.gatewayToken || getStoredGatewayToken()
|
gatewayToken || quickConfig.gatewayToken || getStoredGatewayToken()
|
||||||
).catch(() => {}), 500);
|
).catch(() => {}), 500);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function Privacy() {
|
|||||||
<h3 className="font-medium mb-2 text-gray-900">本地数据路径</h3>
|
<h3 className="font-medium mb-2 text-gray-900">本地数据路径</h3>
|
||||||
<div className="text-xs text-gray-500 mb-3">所有工作区文件、对话记录和 Agent 输出均存储在此本地目录。</div>
|
<div className="text-xs text-gray-500 mb-3">所有工作区文件、对话记录和 Agent 输出均存储在此本地目录。</div>
|
||||||
<div className="p-3 bg-gray-50 border border-gray-200 rounded-lg text-xs text-gray-600 font-mono">
|
<div className="p-3 bg-gray-50 border border-gray-200 rounded-lg text-xs text-gray-600 font-mono">
|
||||||
{workspaceInfo?.resolvedPath || workspaceInfo?.path || quickConfig.workspaceDir || '~/.openclaw/zclaw-workspace'}
|
{workspaceInfo?.resolvedPath || workspaceInfo?.path || quickConfig.workspaceDir || '~/.openfang/zclaw-workspace'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ export function Workspace() {
|
|||||||
loadWorkspaceInfo,
|
loadWorkspaceInfo,
|
||||||
saveQuickConfig,
|
saveQuickConfig,
|
||||||
} = useGatewayStore();
|
} = useGatewayStore();
|
||||||
const [projectDir, setProjectDir] = useState('~/.openclaw/zclaw-workspace');
|
const [projectDir, setProjectDir] = useState('~/.openfang/zclaw-workspace');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadWorkspaceInfo().catch(() => {});
|
loadWorkspaceInfo().catch(() => {});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setProjectDir(quickConfig.workspaceDir || workspaceInfo?.path || '~/.openclaw/zclaw-workspace');
|
setProjectDir(quickConfig.workspaceDir || workspaceInfo?.path || '~/.openfang/zclaw-workspace');
|
||||||
}, [quickConfig.workspaceDir, workspaceInfo?.path]);
|
}, [quickConfig.workspaceDir, workspaceInfo?.path]);
|
||||||
|
|
||||||
const handleWorkspaceBlur = async () => {
|
const handleWorkspaceBlur = async () => {
|
||||||
const nextValue = projectDir.trim() || '~/.openclaw/zclaw-workspace';
|
const nextValue = projectDir.trim() || '~/.openfang/zclaw-workspace';
|
||||||
setProjectDir(nextValue);
|
setProjectDir(nextValue);
|
||||||
await saveQuickConfig({ workspaceDir: nextValue });
|
await saveQuickConfig({ workspaceDir: nextValue });
|
||||||
await loadWorkspaceInfo();
|
await loadWorkspaceInfo();
|
||||||
@@ -89,15 +89,6 @@ export function Workspace() {
|
|||||||
<Toggle checked={fileWatching} onChange={(value) => { handleToggle('fileWatching', value).catch(() => {}); }} />
|
<Toggle checked={fileWatching} onChange={(value) => { handleToggle('fileWatching', value).catch(() => {}); }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-between items-center py-3 border-t border-gray-100">
|
|
||||||
<div>
|
|
||||||
<div className="font-medium text-gray-900 mb-1">从 OpenClaw 迁移</div>
|
|
||||||
<div className="text-xs text-gray-500">将 OpenClaw 的配置、对话记录、技能等数据迁移到 ZCLAW</div>
|
|
||||||
</div>
|
|
||||||
<button className="text-xs px-4 py-2 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors">
|
|
||||||
开始迁移
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
* in the Tauri React frontend. Uses native browser WebSocket API.
|
* in the Tauri React frontend. Uses native browser WebSocket API.
|
||||||
* Supports Ed25519 device authentication + JWT.
|
* Supports Ed25519 device authentication + JWT.
|
||||||
*
|
*
|
||||||
* OpenFang vs OpenClaw:
|
* OpenFang Configuration:
|
||||||
* - Port: 4200 (was 18789)
|
* - Port: 50051
|
||||||
* - WebSocket path: /ws
|
* - WebSocket path: /ws
|
||||||
* - REST API: http://127.0.0.1:4200/api/*
|
* - REST API: http://127.0.0.1:50051/api/*
|
||||||
* - Config format: TOML (was YAML/JSON)
|
* - Config format: TOML
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import nacl from 'tweetnacl';
|
import nacl from 'tweetnacl';
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ ZCLAW 是基于 **OpenFang** (Rust Agent OS) 的 AI Agent 桌面客户端,核
|
|||||||
|------|------|------|
|
|------|------|------|
|
||||||
| 迁移 openclaw.default.json | 转换为 config.toml | ✅ 已完成 |
|
| 迁移 openclaw.default.json | 转换为 config.toml | ✅ 已完成 |
|
||||||
| 补充主 config.toml | OpenFang 服务器配置 | ✅ 已完成 |
|
| 补充主 config.toml | OpenFang 服务器配置 | ✅ 已完成 |
|
||||||
| 清理 OpenClaw 遗留代码 | 移除兼容层 | 🔴 待开始 |
|
| 清理 OpenClaw 遗留代码 | 移除兼容层 | ✅ 已完成 |
|
||||||
|
|
||||||
### Phase 4: 类型系统完善 (P2)
|
### Phase 4: 类型系统完善 (P2)
|
||||||
|
|
||||||
@@ -327,8 +327,9 @@ ZCLAW 是基于 **OpenFang** (Rust Agent OS) 的 AI Agent 桌面客户端,核
|
|||||||
|
|
||||||
- [x] 创建 OpenFang config.toml
|
- [x] 创建 OpenFang config.toml
|
||||||
- [x] 迁移 OpenClaw JSON 配置到 TOML
|
- [x] 迁移 OpenClaw JSON 配置到 TOML
|
||||||
- [ ] 无 OpenClaw JSON 配置文件 (保留 openclaw.default.json 作为参考)
|
- [x] OpenClaw JSON 配置已归档到 docs/archive/openclaw-legacy/
|
||||||
- [ ] 无 OpenClaw 兼容层代码
|
- [x] 默认路径从 ~/.openclaw 更新为 ~/.openfang
|
||||||
|
- [x] 默认端口从 18789 更新为 50051
|
||||||
|
|
||||||
### 6.4 Phase 4 完成标准
|
### 6.4 Phase 4 完成标准
|
||||||
|
|
||||||
@@ -383,7 +384,7 @@ ZCLAW 是基于 **OpenFang** (Rust Agent OS) 的 AI Agent 桌面客户端,核
|
|||||||
*文档创建: 2026-03-14*
|
*文档创建: 2026-03-14*
|
||||||
*最后更新: 2026-03-15*
|
*最后更新: 2026-03-15*
|
||||||
*Phase 1 & 2 已完成*
|
*Phase 1 & 2 已完成*
|
||||||
*Phase 3 进行中 (2/3)*
|
*Phase 3 已完成*
|
||||||
*Phase 4 已完成*
|
*Phase 4 已完成*
|
||||||
*Phase 5 进行中 (9/60+ Skills)*
|
*Phase 5 进行中 (9/60+ Skills)*
|
||||||
*下次审查: Phase 3 完成后*
|
*下次审查: Phase 5 扩展*
|
||||||
|
|||||||
Reference in New Issue
Block a user