513 lines
16 KiB
Markdown
513 lines
16 KiB
Markdown
# ZCLAW 独立化架构重构计划
|
||
|
||
## Context
|
||
|
||
### 问题背景
|
||
1. **外部进程不稳定** - OpenFang 作为独立进程运行,启动失败、版本兼容问题频发
|
||
2. **代码分散** - ZCLAW 和 OpenFang 逻辑分离,维护困难
|
||
3. **分发复杂** - 用户安装需要额外配置 OpenFang 运行时
|
||
4. **技术债务** - 架构需要清理,希望借此机会彻底解决
|
||
|
||
### 目标
|
||
将 ZCLAW 从"基于 OpenFang 定制"转变为**完全独立的 AI Agent 桌面系统**:
|
||
- 代码所有权:所有代码在 ZCLAW 仓库
|
||
- 架构自主:完全自由设计
|
||
- 品牌独立:无 OpenFang/OpenClaw 痕迹
|
||
- 技术栈独立:选择最适合的技术
|
||
|
||
### 策略
|
||
**混合策略**:核心能力自研,通用能力借鉴设计,代码层面完全原创
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
### Crate 结构
|
||
|
||
```
|
||
ZCLAW/
|
||
├── crates/ # Rust Workspace
|
||
│ │
|
||
│ ├── zclaw-types/ # L1: 基础类型(无依赖)
|
||
│ │ ├── AgentId, SessionId, Message
|
||
│ │ ├── Capability, Tool, Event
|
||
│ │ ├── Config, Error
|
||
│ │ └── 共享 trait 定义
|
||
│ │
|
||
│ ├── zclaw-memory/ # L2: 存储层(依赖 types)
|
||
│ │ ├── KV Store(Agent 配置、状态)
|
||
│ │ ├── Session Manager(对话历史)
|
||
│ │ ├── Semantic Search(向量搜索)
|
||
│ │ └── SQLite 持久化
|
||
│ │
|
||
│ ├── zclaw-runtime/ # L3: 运行时(依赖 types, memory)
|
||
│ │ ├── LLM Drivers(Anthropic, OpenAI, Gemini, Local)
|
||
│ │ ├── Tool Runner(23 个内置工具)
|
||
│ │ ├── Agent Loop(消息循环、流式处理)
|
||
│ │ ├── Loop Guard(防循环)
|
||
│ │ └── Session Compactor(上下文压缩)
|
||
│ │
|
||
│ ├── zclaw-kernel/ # L4: 核心协调(依赖所有下层)
|
||
│ │ ├── Agent Registry(注册、生命周期)
|
||
│ │ ├── Scheduler(配额、调度)
|
||
│ │ ├── Capability Manager(权限)
|
||
│ │ ├── Event Bus(事件发布)
|
||
│ │ ├── Workflow Engine(工作流)
|
||
│ │ ├── Trigger Engine(触发器)
|
||
│ │ └── Supervisor(健康监控)
|
||
│ │
|
||
│ ├── zclaw-skills/ # 技能系统
|
||
│ │ ├── Skill Loader(TOML/SKILL.md 解析)
|
||
│ │ ├── Skill Runner(Python/WASM/PromptOnly)
|
||
│ │ └── Bundled Skills(内置技能)
|
||
│ │
|
||
│ ├── zclaw-hands/ # Hands 自主能力
|
||
│ │ ├── Browser Hand(整合现有 browser/)
|
||
│ │ ├── Collector Hand
|
||
│ │ ├── Researcher Hand
|
||
│ │ └── 其他 Hands
|
||
│ │
|
||
│ ├── zclaw-channels/ # 通道适配器
|
||
│ │ ├── Channel Trait
|
||
│ │ ├── Telegram/Discord/Slack 等
|
||
│ │ └── Bridge Manager
|
||
│ │
|
||
│ └── zclaw-protocols/ # 协议支持
|
||
│ ├── MCP Client/Server
|
||
│ └── A2A Protocol
|
||
│
|
||
├── desktop/
|
||
│ ├── src-tauri/ # Tauri 应用
|
||
│ │ ├── src/
|
||
│ │ │ ├── lib.rs # 主入口,Kernel 初始化
|
||
│ │ │ ├── commands/ # Tauri 命令封装
|
||
│ │ │ ├── intelligence/ # 已有智能层(保留)
|
||
│ │ │ ├── browser/ # 已有浏览器(保留,后续整合到 zclaw-hands)
|
||
│ │ │ └── state.rs # 应用状态
|
||
│ │ └── Cargo.toml # 依赖内部 crates
|
||
│ └── src/ # React 前端(保持不变)
|
||
│
|
||
└── Cargo.toml # Workspace 定义
|
||
```
|
||
|
||
### 依赖关系
|
||
|
||
```
|
||
zclaw-types (无依赖)
|
||
↑
|
||
zclaw-memory (→ types)
|
||
↑
|
||
zclaw-runtime (→ types, memory)
|
||
↑
|
||
zclaw-kernel (→ types, memory, runtime)
|
||
↑
|
||
desktop/src-tauri (→ kernel, skills, hands, channels, protocols)
|
||
```
|
||
|
||
---
|
||
|
||
## Core Modules
|
||
|
||
### zclaw-types
|
||
|
||
```rust
|
||
// 核心 ID 类型
|
||
pub struct AgentId(Uuid);
|
||
pub struct SessionId(Uuid);
|
||
pub struct ToolId(String);
|
||
|
||
// 消息类型
|
||
pub enum Message {
|
||
User { content: String },
|
||
Assistant { content: String, thinking: Option<String> },
|
||
ToolUse { tool: ToolId, input: Value },
|
||
ToolResult { tool: ToolId, output: Value, error: bool },
|
||
}
|
||
|
||
// Agent 配置
|
||
pub struct AgentConfig {
|
||
pub id: AgentId,
|
||
pub name: String,
|
||
pub model: ModelConfig,
|
||
pub system_prompt: String,
|
||
pub capabilities: Vec<Capability>,
|
||
pub tools: Vec<ToolId>,
|
||
}
|
||
|
||
// 能力定义
|
||
pub enum Capability {
|
||
ToolInvoke(String),
|
||
MemoryRead(String),
|
||
MemoryWrite(String),
|
||
NetConnect(String),
|
||
ShellExec(String),
|
||
AgentSpawn,
|
||
AgentMessage(String),
|
||
}
|
||
|
||
// 统一错误类型
|
||
pub enum ZclawError {
|
||
NotFound(String),
|
||
PermissionDenied(String),
|
||
LlmError(String),
|
||
ToolError(String),
|
||
StorageError(String),
|
||
}
|
||
```
|
||
|
||
### zclaw-memory
|
||
|
||
```rust
|
||
pub struct MemoryStore {
|
||
db: Arc<Mutex<Connection>>,
|
||
}
|
||
|
||
impl MemoryStore {
|
||
// Agent 配置持久化
|
||
pub async fn save_agent(&self, agent: &AgentConfig) -> Result<()>;
|
||
pub async fn load_agent(&self, id: &AgentId) -> Result<Option<AgentConfig>>;
|
||
pub async fn list_agents(&self) -> Result<Vec<AgentConfig>>;
|
||
|
||
// 会话管理
|
||
pub async fn create_session(&self, agent_id: &AgentId) -> Result<SessionId>;
|
||
pub async fn get_session(&self, id: &SessionId) -> Result<Option<Session>>;
|
||
pub async fn append_message(&self, session: &SessionId, msg: Message) -> Result<()>;
|
||
|
||
// KV 存储
|
||
pub async fn store(&self, agent: &AgentId, key: &str, value: &Value) -> Result<()>;
|
||
pub async fn recall(&self, agent: &AgentId, key: &str) -> Result<Option<Value>>;
|
||
|
||
// 语义搜索
|
||
pub async fn embed(&self, text: &str) -> Result<Vec<f32>>;
|
||
pub async fn search_similar(&self, query: &str, limit: usize) -> Result<Vec<MemoryEntry>>;
|
||
}
|
||
```
|
||
|
||
### zclaw-runtime
|
||
|
||
```rust
|
||
// LLM 驱动 trait
|
||
#[async_trait]
|
||
pub trait LlmDriver: Send + Sync {
|
||
async fn complete(&self, req: CompletionRequest) -> Result<CompletionResponse>;
|
||
async fn stream(&self, req: CompletionRequest) -> Result<mpsc::Receiver<StreamEvent>>;
|
||
}
|
||
|
||
// 内置驱动实现
|
||
pub struct AnthropicDriver { api_key: SecretString }
|
||
pub struct OpenAiDriver { api_key: SecretString, base_url: String }
|
||
pub struct GeminiDriver { api_key: SecretString }
|
||
pub struct LocalDriver { base_url: String } // Ollama/LMStudio
|
||
|
||
// Agent 循环
|
||
pub struct AgentLoop {
|
||
driver: Arc<dyn LlmDriver>,
|
||
tools: Vec<Tool>,
|
||
memory: Arc<MemoryStore>,
|
||
loop_guard: LoopGuard,
|
||
}
|
||
|
||
impl AgentLoop {
|
||
pub async fn run(&self, session: SessionId, input: String) -> Result<AgentLoopResult>;
|
||
pub async fn run_streaming(&self, session: SessionId, input: String)
|
||
-> Result<mpsc::Receiver<LoopEvent>>;
|
||
}
|
||
```
|
||
|
||
### zclaw-kernel
|
||
|
||
```rust
|
||
pub struct Kernel {
|
||
registry: AgentRegistry,
|
||
scheduler: Scheduler,
|
||
capabilities: CapabilityManager,
|
||
events: EventBus,
|
||
workflows: WorkflowEngine,
|
||
triggers: TriggerEngine,
|
||
supervisor: Supervisor,
|
||
memory: Arc<MemoryStore>,
|
||
}
|
||
|
||
impl Kernel {
|
||
pub async fn boot(config: KernelConfig) -> Result<Self>;
|
||
|
||
// Agent 生命周期
|
||
pub async fn spawn_agent(&self, config: AgentConfig) -> Result<AgentId>;
|
||
pub async fn kill_agent(&self, id: &AgentId) -> Result<()>;
|
||
pub async fn list_agents(&self) -> Result<Vec<AgentInfo>>;
|
||
|
||
// 消息处理
|
||
pub async fn send_message(&self, agent: &AgentId, msg: String)
|
||
-> Result<MessageResponse>;
|
||
pub async fn send_message_stream(&self, agent: &AgentId, msg: String)
|
||
-> Result<mpsc::Receiver<StreamEvent>>;
|
||
|
||
// 工作流
|
||
pub async fn run_workflow(&self, workflow_id: &str, input: Value) -> Result<Value>;
|
||
|
||
// 事件
|
||
pub fn subscribe(&self) -> broadcast::Receiver<Event>;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Tauri Integration
|
||
|
||
### 启动流程
|
||
|
||
```rust
|
||
// desktop/src-tauri/src/lib.rs
|
||
|
||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||
pub fn run() {
|
||
tauri::Builder::default()
|
||
.setup(|app| {
|
||
// 1. 初始化内核
|
||
let runtime = tokio::runtime::Runtime::new().unwrap();
|
||
let kernel = runtime.block_on(async {
|
||
Kernel::boot(KernelConfig::load().await?).await
|
||
}).expect("Kernel boot failed");
|
||
|
||
// 2. 存储到应用状态
|
||
app.manage(Arc::new(kernel));
|
||
app.manage(runtime);
|
||
|
||
Ok(())
|
||
})
|
||
.invoke_handler(tauri::generate_handler![
|
||
// Agent 命令
|
||
agent_spawn, agent_kill, agent_list, agent_chat, agent_chat_stream,
|
||
// 配置命令
|
||
config_get, config_update,
|
||
// 工作流命令
|
||
workflow_list, workflow_run,
|
||
// 技能命令
|
||
skill_list, skill_install,
|
||
// Hands 命令
|
||
hand_trigger, hand_status,
|
||
// 记忆命令
|
||
memory_store, memory_recall, memory_search,
|
||
// 智能层命令(保留)
|
||
heartbeat_start, heartbeat_stop, reflection_reflect, identity_get,
|
||
])
|
||
.run(tauri::generate_context!())
|
||
}
|
||
```
|
||
|
||
### 关键变化
|
||
|
||
| 之前 | 之后 |
|
||
|------|------|
|
||
| 外部 OpenFang 进程 | 内部 Kernel 单例 |
|
||
| WebSocket 连接 localhost:4200 | 直接 Tauri 命令调用 |
|
||
| 启动脚本管理进程 | Tauri 应用内自动初始化 |
|
||
| 两个代码仓库 | 单一 ZCLAW 仓库 |
|
||
|
||
---
|
||
|
||
## Migration Phases
|
||
|
||
### 阶段 0:准备(1 周)✅ 已完成
|
||
|
||
**目标**:workspace 编译通过
|
||
|
||
**任务**:
|
||
- [x] 创建 `crates/` 目录
|
||
- [x] 创建根 `Cargo.toml` workspace 配置
|
||
- [x] 创建各 crate 骨架(`zclaw-types`, `zclaw-memory`, `zclaw-runtime`, `zclaw-kernel`)
|
||
- [x] 更新 `desktop/src-tauri/Cargo.toml` 加入 workspace
|
||
- [x] 验证 `cargo build` 成功
|
||
|
||
### 阶段 1:基础设施(2-3 周)✅ 已完成
|
||
|
||
**目标**:可以存储和加载 Agent 配置
|
||
|
||
**任务**:
|
||
- [x] **zclaw-types**
|
||
- 定义 AgentId, SessionId, ToolId
|
||
- 定义 Message 枚举
|
||
- 定义 AgentConfig 结构
|
||
- 定义 Capability 枚举
|
||
- 定义 ZclawError
|
||
- [x] **zclaw-memory**
|
||
- SQLite schema 设计(agents, sessions, kv, embeddings)
|
||
- 实现 MemoryStore
|
||
- Agent 配置 CRUD
|
||
- Session 管理
|
||
- KV 存储
|
||
- 基础语义搜索(可选:延后到阶段 4)
|
||
|
||
### 阶段 2:核心运行时(3-4 周)✅ 已完成
|
||
|
||
**目标**:可以与 LLM 对话并调用工具
|
||
|
||
**任务**:
|
||
- [x] **zclaw-runtime**
|
||
- LlmDriver trait 定义
|
||
- AnthropicDriver 实现
|
||
- OpenAiDriver 实现(含 OpenAI-compatible providers)
|
||
- GeminiDriver 实现
|
||
- LocalDriver 实现(Ollama/LMStudio)
|
||
- Tool trait 和基础工具实现(file_read, file_write, shell_exec, web_fetch)
|
||
- AgentLoop 实现
|
||
- LoopGuard 实现(防循环)
|
||
- 流式响应支持
|
||
|
||
### 阶段 3:内核集成(2-3 周)✅ 已完成
|
||
|
||
**目标**:Tauri 应用可以创建 Agent 并对话
|
||
|
||
**任务**:
|
||
- [x] **zclaw-kernel**
|
||
- AgentRegistry 实现
|
||
- Scheduler 实现(基础版)
|
||
- CapabilityManager 实现
|
||
- EventBus 实现
|
||
- Kernel 主结构
|
||
- boot() 初始化流程
|
||
- [x] **desktop/src-tauri**
|
||
- lib.rs 集成 Kernel (kernel_commands 模块)
|
||
- Tauri 命令封装(kernel_init, agent_create, agent_chat 等)
|
||
- 保留外部 OpenFang 命令作为备选方案
|
||
- 前端适配(待实现)
|
||
|
||
### 阶段 4:扩展能力(4-6 周)✅ 已完成
|
||
|
||
**目标**:技能、Hands、通道功能正常
|
||
|
||
**任务**:
|
||
- [x] **zclaw-skills**
|
||
- Skill manifest 定义
|
||
- SKILL.md 解析器
|
||
- SkillRunner trait
|
||
- PromptOnly 技能执行
|
||
- Python 技能执行(subprocess 隔离)
|
||
- 内置技能移植
|
||
- [x] **zclaw-hands**
|
||
- Hand/Trigger trait 定义
|
||
- HandRegistry/TriggerRegistry 实现
|
||
- 整合现有 browser/ 模块(待完整移植)
|
||
- Collector Hand
|
||
- Researcher Hand
|
||
- 其他 Hands
|
||
- [x] **zclaw-channels**
|
||
- Channel trait 定义
|
||
- ChannelBridge 管理器
|
||
- Telegram 适配器(骨架)
|
||
- Discord 适配器(骨架)
|
||
- Slack 适配器(骨架)
|
||
- Console 适配器(测试用)
|
||
- [x] **zclaw-protocols**
|
||
- MCP Client 实现
|
||
- MCP Server 实现(待完善)
|
||
- A2A 协议支持(可选)
|
||
|
||
### 阶段 5:清理与优化(2-3 周)✅ 已完成
|
||
|
||
**目标**:无外部依赖,单安装包可运行
|
||
|
||
**任务**:
|
||
- [x] 移除 `resources/openfang-runtime/`
|
||
- [x] 移除 `start-all.ps1` 中的 OpenFang 启动逻辑
|
||
- [x] 更新 tauri.conf.json 移除外部运行时引用
|
||
- [x] 更新 CLAUDE.md 反映新架构
|
||
- [x] 修复 UTF-8 边界问题 (compactor.rs)
|
||
- [x] Rust 测试验证 (26/26 通过)
|
||
- [x] E2E 测试验证 (161/161 通过)
|
||
- [x] 性能优化 (Release LTO 配置)
|
||
- [x] 发布准备 (NSIS 安装包生成成功)
|
||
|
||
---
|
||
|
||
## Verification
|
||
|
||
### 阶段验收标准
|
||
|
||
| 阶段 | 验收命令/方法 |
|
||
|------|--------------|
|
||
| 0 | `cargo build` 成功 |
|
||
| 1 | 运行单元测试验证 MemoryStore CRUD |
|
||
| 2 | CLI 测试:与 LLM 对话,工具调用正常 |
|
||
| 3 | `pnpm tauri dev` 启动应用,UI 可创建 Agent 并对话 |
|
||
| 4 | 技能加载、Hand 触发、通道消息正常 |
|
||
| 5 | 全新机器安装单一安装包可运行 |
|
||
|
||
### 最终验证清单
|
||
|
||
- [ ] `pnpm start:dev` 启动 Tauri 应用,无需外部进程
|
||
- [ ] 可创建、配置、删除 Agent
|
||
- [ ] 可与 Agent 对话,流式响应正常
|
||
- [ ] 工具调用正常(文件读写、网络请求)
|
||
- [ ] 技能加载和执行正常
|
||
- [ ] Hands 触发正常(浏览器自动化等)
|
||
- [ ] 智能层功能正常(心跳、反思、身份)
|
||
- [ ] 打包后的安装程序可独立运行
|
||
|
||
---
|
||
|
||
## Critical Files
|
||
|
||
### 需要修改的文件
|
||
|
||
- `Cargo.toml` - 添加 workspace 配置
|
||
- `desktop/src-tauri/Cargo.toml` - 加入 workspace,更新依赖
|
||
- `desktop/src-tauri/src/lib.rs` - Kernel 初始化,命令注册
|
||
- `start-all.ps1` - 移除 OpenFang 启动逻辑
|
||
- `CLAUDE.md` - 更新架构说明
|
||
|
||
### 需要创建的文件
|
||
|
||
- `crates/zclaw-types/Cargo.toml`
|
||
- `crates/zclaw-types/src/lib.rs`
|
||
- `crates/zclaw-memory/Cargo.toml`
|
||
- `crates/zclaw-memory/src/lib.rs`
|
||
- `crates/zclaw-runtime/Cargo.toml`
|
||
- `crates/zclaw-runtime/src/lib.rs`
|
||
- `crates/zclaw-kernel/Cargo.toml`
|
||
- `crates/zclaw-kernel/src/lib.rs`
|
||
- `crates/zclaw-skills/Cargo.toml`
|
||
- `crates/zclaw-skills/src/lib.rs`
|
||
- `crates/zclaw-hands/Cargo.toml`
|
||
- `crates/zclaw-hands/src/lib.rs`
|
||
- `crates/zclaw-channels/Cargo.toml`
|
||
- `crates/zclaw-channels/src/lib.rs`
|
||
- `crates/zclaw-protocols/Cargo.toml`
|
||
- `crates/zclaw-protocols/src/lib.rs`
|
||
|
||
### 需要删除的文件(阶段 5)
|
||
|
||
- `desktop/src-tauri/resources/openfang-runtime/` - 整个目录
|
||
|
||
---
|
||
|
||
## Reference
|
||
|
||
### OpenFang 架构参考
|
||
|
||
OpenFang 是成熟的 Rust workspace,包含 14 个 crate:
|
||
- `openfang-types` - 共享类型
|
||
- `openfang-memory` - SQLite 存储
|
||
- `openfang-runtime` - LLM 驱动、工具、Agent 循环
|
||
- `openfang-kernel` - 核心协调器
|
||
- `openfang-api` - HTTP API(ZCLAW 不需要,用 Tauri 命令替代)
|
||
- `openfang-channels` - 40 个通道适配器
|
||
- `openfang-skills` - 60 个技能
|
||
- `openfang-desktop` - Tauri 桌面应用
|
||
|
||
### 设计借鉴点
|
||
|
||
1. **分层架构** - types → memory → runtime → kernel
|
||
2. **LLM Driver 抽象** - 统一 trait,多 provider 实现
|
||
3. **能力系统** - Capability 枚举,权限检查
|
||
4. **Agent Loop** - 消息循环、工具调用、流式处理
|
||
5. **Loop Guard** - 防止 Agent 陷入循环
|
||
6. **WASM 沙箱** - 技能安全执行(可选)
|
||
|
||
### ZCLAW 独特价值
|
||
|
||
1. **智能层** - heartbeat, compactor, reflection, identity(已实现)
|
||
2. **中文优先** - 面向中文用户优化
|
||
3. **简化的架构** - 去除不需要的 HTTP API 层
|
||
4. **Tauri 原生集成** - 无进程间通信开销
|