Files
zclaw_openfang/docs/knowledge-base/zclaw-technical-reference.md
iven 3ff08faa56 release(v0.2.0): streaming, MCP protocol, Browser Hand, security enhancements
## Major Features

### Streaming Response System
- Implement LlmDriver trait with `stream()` method returning async Stream
- Add SSE parsing for Anthropic and OpenAI API streaming
- Integrate Tauri event system for frontend streaming (`stream:chunk` events)
- Add StreamChunk types: Delta, ToolStart, ToolEnd, Complete, Error

### MCP Protocol Implementation
- Add MCP JSON-RPC 2.0 types (mcp_types.rs)
- Implement stdio-based MCP transport (mcp_transport.rs)
- Support tool discovery, execution, and resource operations

### Browser Hand Implementation
- Complete browser automation with Playwright-style actions
- Support Navigate, Click, Type, Scrape, Screenshot, Wait actions
- Add educational Hands: Whiteboard, Slideshow, Speech, Quiz

### Security Enhancements
- Implement command whitelist/blacklist for shell_exec tool
- Add SSRF protection with private IP blocking
- Create security.toml configuration file

## Test Improvements
- Fix test import paths (security-utils, setup)
- Fix vi.mock hoisting issues with vi.hoisted()
- Update test expectations for validateUrl and sanitizeFilename
- Add getUnsupportedLocalGatewayStatus mock

## Documentation Updates
- Update architecture documentation
- Improve configuration reference
- Add quick-start guide updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 03:24:24 +08:00

756 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ZCLAW Kernel 技术参考文档
> **文档版本**: v2.0
> **更新日期**: 2026-03-22
> **目标**: 为 ZCLAW 内部 Kernel 架构提供技术参考
---
## 一、项目概述
### 1.1 基本信息
| 属性 | 值 |
|------|-----|
| **项目名称** | ZCLAW |
| **架构** | 8 个 Rust Crates 模块化设计 |
| **定位** | AI Agent 桌面客户端 |
| **许可** | MIT |
### 1.2 核心特性
```
┌─────────────────────────────────────────────────────────────────┐
│ ZCLAW 核心特性 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 🚀 内部 Kernel 架构 │
│ ├── 无外部进程依赖 │
│ ├── 单一安装包可运行 │
│ └── 即时启动 │
│ │
│ 🤖 多 LLM Provider 支持 │
│ ├── Kimi Code (kimi) │
│ ├── 百炼/通义千问 (qwen) │
│ ├── DeepSeek (deepseek) │
│ ├── 智谱 GLM (zhipu) │
│ ├── OpenAI (openai) │
│ ├── Anthropic (anthropic) │
│ └── 本地模型 (local/ollama) │
│ │
│ 🔒 UI 配置 │
│ ├── 无需编辑配置文件 │
│ ├── "模型与 API"设置页面配置 │
│ └── 配置存储在 localStorage │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 二、Crate 架构
### 2.1 模块结构
```
ZCLAW/
├── crates/ # Rust Workspace
│ │
│ ├── zclaw-types/ # L1: 基础类型(无依赖)
│ │ ├── AgentId, SessionId, Message
│ │ ├── Capability, Tool, Event
│ │ ├── Config, Error
│ │ └── 共享 trait 定义
│ │
│ ├── zclaw-memory/ # L2: 存储层(依赖 types
│ │ ├── KV StoreAgent 配置、状态)
│ │ ├── Session Manager对话历史
│ │ ├── Semantic Search向量搜索
│ │ └── SQLite 持久化
│ │
│ ├── zclaw-runtime/ # L3: 运行时依赖types, memory
│ │ ├── LLM DriversAnthropic, OpenAI, Gemini, Local
│ │ ├── Tool Runner23 个内置工具)
│ │ ├── Agent Loop消息循环、流式处理
│ │ ├── Loop Guard防循环
│ │ └── Session Compactor上下文压缩
│ │
│ ├── zclaw-kernel/ # L4: 核心协调(依赖所有下层)
│ │ ├── Agent Registry注册、生命周期
│ │ ├── Scheduler配额、调度
│ │ ├── Capability Manager权限
│ │ ├── Event Bus事件发布
│ │ ├── Workflow Engine工作流
│ │ ├── Trigger Engine触发器
│ │ └── Supervisor健康监控
│ │
│ ├── zclaw-skills/ # 技能系统
│ │ ├── Skill LoaderTOML/SKILL.md 解析)
│ │ ├── Skill RunnerPython/WASM/PromptOnly
│ │ └── Bundled Skills内置技能
│ │
│ ├── zclaw-hands/ # Hands 自主能力
│ │ ├── Hand/Trigger trait 定义
│ │ ├── HandRegistry/TriggerRegistry 实现
│ │ ├── Browser Hand
│ │ ├── 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 初始化
│ │ │ ├── kernel_commands.rs # Tauri 命令封装
│ │ │ └── state.rs # 应用状态
│ │ └── Cargo.toml # 依赖内部 crates
│ └── src/ # React 前端
└── Cargo.toml # Workspace 定义
```
### 2.2 依赖关系
```
zclaw-types (无依赖)
zclaw-memory (→ types)
zclaw-runtime (→ types, memory)
zclaw-kernel (→ types, memory, runtime)
desktop/src-tauri (→ kernel, skills, hands, channels, protocols)
```
---
## 三、zclaw-types
### 3.1 核心 ID 类型
```rust
pub struct AgentId(Uuid);
pub struct SessionId(Uuid);
pub struct ToolId(String);
```
### 3.2 消息类型
```rust
pub enum Message {
User { content: String },
Assistant { content: String, thinking: Option<String> },
ToolUse { tool: ToolId, input: Value },
ToolResult { tool: ToolId, output: Value, error: bool },
}
```
### 3.3 Agent 配置
```rust
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 struct ModelConfig {
pub provider: String,
pub model: String,
pub api_key_env: Option<String>,
pub base_url: Option<String>,
}
```
### 3.4 统一错误类型
```rust
pub enum ZclawError {
NotFound(String),
PermissionDenied(String),
LlmError(String),
ToolError(String),
StorageError(String),
ConfigError(String),
}
```
---
## 四、zclaw-memory
### 4.1 MemoryStore
```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>>;
}
```
### 4.2 数据库 Schema
```sql
-- Agent 配置表
CREATE TABLE agents (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
config JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 会话表
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (agent_id) REFERENCES agents(id)
);
-- 消息表
CREATE TABLE messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
role TEXT NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (session_id) REFERENCES sessions(id)
);
```
---
## 五、zclaw-runtime
### 5.1 LLM Driver Trait
```rust
#[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>>;
}
```
### 5.2 Driver 实现
```rust
// Anthropic Claude
pub struct AnthropicDriver {
api_key: SecretString,
}
// OpenAI 兼容(支持 Kimi, Qwen, DeepSeek, Zhipu 等)
pub struct OpenAiDriver {
api_key: SecretString,
base_url: String,
}
impl OpenAiDriver {
pub fn with_base_url(api_key: SecretString, base_url: String) -> Self {
Self { api_key, base_url }
}
}
// Google Gemini
pub struct GeminiDriver {
api_key: SecretString,
}
// 本地模型Ollama/LMStudio
pub struct LocalDriver {
base_url: String,
}
```
### 5.3 Agent Loop
```rust
pub struct AgentLoop {
driver: Arc<dyn LlmDriver>,
tools: Vec<Tool>,
memory: Arc<MemoryStore>,
loop_guard: LoopGuard,
// 模型配置2026-03-22 添加)
model: String,
system_prompt: Option<String>,
max_tokens: u32,
temperature: f32,
}
impl AgentLoop {
pub fn new(...) -> Self;
pub fn with_model(self, model: impl Into<String>) -> Self;
pub fn with_system_prompt(self, prompt: impl Into<String>) -> Self;
pub fn with_max_tokens(self, max_tokens: u32) -> Self;
pub fn with_temperature(self, temperature: f32) -> Self;
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>>;
}
```
**重要**: `AgentLoop` 必须通过 builder 方法配置模型,否则将使用默认值。`run()` 方法会从 `CompletionResponse.content` 中提取 `ContentBlock::Text` 作为响应内容。
---
## 六、zclaw-kernel
### 6.1 Kernel 主结构
```rust
pub struct Kernel {
registry: AgentRegistry,
scheduler: Scheduler,
capabilities: CapabilityManager,
events: EventBus,
workflows: WorkflowEngine,
triggers: TriggerEngine,
supervisor: Supervisor,
memory: Arc<MemoryStore>,
config: KernelConfig,
}
```
### 6.2 Kernel 方法
```rust
impl Kernel {
/// 启动 Kernel
pub async fn boot(config: KernelConfig) -> Result<Self>;
/// 关闭 Kernel
pub async fn shutdown(self) -> Result<()>;
// Agent 生命周期
pub async fn spawn_agent(&self, config: AgentConfig) -> Result<AgentId>;
pub async fn kill_agent(&self, id: &AgentId) -> Result<()>;
pub fn list_agents(&self) -> Vec<AgentInfo>;
pub fn get_agent(&self, id: &AgentId) -> Option<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>>;
}
// send_message 实现:从 AgentConfig 获取模型配置传递给 AgentLoop
// 优先级agent_config.model > kernel_config.default_model
```
**消息处理流程**:
```
send_message(agent_id, message)
├── 获取 AgentConfig: registry.get(agent_id)
├── 确定模型:
│ if !agent_config.model.model.is_empty():
│ model = agent_config.model.model
│ else:
│ model = kernel_config.default_model
├── 创建 AgentLoop (使用 builder 模式):
│ AgentLoop::new(...)
│ .with_model(model)
│ .with_max_tokens(agent_config.max_tokens || kernel_config.max_tokens)
│ .with_temperature(agent_config.temperature || kernel_config.temperature)
│ .with_system_prompt(agent_config.system_prompt) // 可选
└── 运行: loop_runner.run(session_id, message)
├── 调用 LLM: driver.complete(request)
└── 提取响应: 从 ContentBlock::Text 获取内容
```
// 工作流
pub async fn run_workflow(&self, workflow_id: &str, input: Value) -> Result<Value>;
// 事件
pub fn subscribe(&self) -> broadcast::Receiver<Event>;
}
```
### 6.3 KernelConfig
```rust
pub struct KernelConfig {
// 数据库
pub database_url: String,
// 默认 Provider 和模型
pub default_provider: String,
pub default_model: String,
// API Keys从 UI 传入)
pub anthropic_api_key: Option<String>,
pub openai_api_key: Option<String>,
pub gemini_api_key: Option<String>,
pub kimi_api_key: Option<String>,
pub qwen_api_key: Option<String>,
pub deepseek_api_key: Option<String>,
pub zhipu_api_key: Option<String>,
// Base URLs
pub kimi_base_url: String,
pub qwen_base_url: String,
pub deepseek_base_url: String,
pub zhipu_base_url: String,
pub local_base_url: Option<String>,
// 生成参数
pub max_tokens: u32,
pub temperature: f32,
}
```
### 6.4 create_driver 方法
```rust
impl KernelConfig {
pub fn create_driver(&self) -> Result<Arc<dyn LlmDriver>> {
match self.default_provider.as_str() {
"anthropic" => {
let key = self.anthropic_api_key.clone()
.ok_or_else(|| ZclawError::ConfigError("ANTHROPIC_API_KEY not set".into()))?;
Ok(Arc::new(AnthropicDriver::new(SecretString::new(key))))
}
"kimi" => {
let key = self.kimi_api_key.clone()
.ok_or_else(|| ZclawError::ConfigError("KIMI_API_KEY not set".into()))?;
Ok(Arc::new(OpenAiDriver::with_base_url(
SecretString::new(key),
self.kimi_base_url.clone(),
)))
}
"qwen" => {
let key = self.qwen_api_key.clone()
.ok_or_else(|| ZclawError::ConfigError("QWEN_API_KEY not set".into()))?;
Ok(Arc::new(OpenAiDriver::with_base_url(
SecretString::new(key),
self.qwen_base_url.clone(),
)))
}
"deepseek" => {
let key = self.deepseek_api_key.clone()
.ok_or_else(|| ZclawError::ConfigError("DEEPSEEK_API_KEY not set".into()))?;
Ok(Arc::new(OpenAiDriver::with_base_url(
SecretString::new(key),
self.deepseek_base_url.clone(),
)))
}
"zhipu" => {
let key = self.zhipu_api_key.clone()
.ok_or_else(|| ZclawError::ConfigError("ZHIPU_API_KEY not set".into()))?;
Ok(Arc::new(OpenAiDriver::with_base_url(
SecretString::new(key),
self.zhipu_base_url.clone(),
)))
}
"openai" => {
let key = self.openai_api_key.clone()
.ok_or_else(|| ZclawError::ConfigError("OPENAI_API_KEY not set".into()))?;
Ok(Arc::new(OpenAiDriver::new(SecretString::new(key))))
}
"gemini" => {
let key = self.gemini_api_key.clone()
.ok_or_else(|| ZclawError::ConfigError("GEMINI_API_KEY not set".into()))?;
Ok(Arc::new(GeminiDriver::new(SecretString::new(key))))
}
"local" | "ollama" => {
let base_url = self.local_base_url.clone()
.unwrap_or_else(|| "http://localhost:11434/v1".to_string());
Ok(Arc::new(LocalDriver::new(base_url)))
}
_ => Err(ZclawError::ConfigError(
format!("Unknown provider: {}", self.default_provider)
)),
}
}
}
```
---
## 七、Tauri 集成
### 7.1 命令封装
```rust
// desktop/src-tauri/src/kernel_commands.rs
/// Kernel 状态包装器
pub type KernelState = Arc<Mutex<Option<Kernel>>>;
/// 初始化 Kernel
#[tauri::command]
pub async fn kernel_init(
state: State<'_, KernelState>,
config_request: Option<KernelConfigRequest>,
) -> Result<KernelStatusResponse, String> {
// ...
}
/// 创建 Agent
#[tauri::command]
pub async fn agent_create(
state: State<'_, KernelState>,
request: CreateAgentRequest,
) -> Result<CreateAgentResponse, String> {
// ...
}
/// 发送消息
#[tauri::command]
pub async fn agent_chat(
state: State<'_, KernelState>,
request: ChatRequest,
) -> Result<ChatResponse, String> {
// ...
}
```
### 7.2 lib.rs 注册
```rust
// desktop/src-tauri/src/lib.rs
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.setup(|app| {
app.manage(kernel_commands::create_kernel_state());
Ok(())
})
.invoke_handler(tauri::generate_handler![
kernel_commands::kernel_init,
kernel_commands::kernel_status,
kernel_commands::kernel_shutdown,
kernel_commands::agent_create,
kernel_commands::agent_list,
kernel_commands::agent_get,
kernel_commands::agent_delete,
kernel_commands::agent_chat,
])
.run(tauri::generate_context!())
}
```
---
## 八、前端集成
### 8.1 KernelClient
```typescript
// desktop/src/lib/kernel-client.ts
export class KernelClient {
private config: KernelConfig = {};
private defaultAgentId: string = '';
setConfig(config: KernelConfig): void {
this.config = config;
}
async connect(): Promise<void> {
if (!this.config.provider || !this.config.model || !this.config.apiKey) {
throw new Error('请先在"模型与 API"设置页面配置模型');
}
const status = await invoke<KernelStatus>('kernel_init', {
configRequest: {
provider: this.config.provider,
model: this.config.model,
apiKey: this.config.apiKey,
baseUrl: this.config.baseUrl || null,
},
});
// 创建默认 Agent
const agents = await this.listAgents();
if (agents.length === 0) {
const agent = await this.createAgent({
name: 'Default Agent',
provider: this.config.provider,
model: this.config.model,
});
this.defaultAgentId = agent.id;
}
}
async chat(message: string, opts?: ChatOptions): Promise<ChatResponse> {
return invoke<ChatResponse>('agent_chat', {
request: {
agentId: opts?.agentId || this.defaultAgentId,
message,
},
});
}
}
```
### 8.2 ConnectionStore
```typescript
// desktop/src/store/connectionStore.ts
connect: async (url?: string, token?: string) => {
const useInternalKernel = isTauriRuntime();
if (useInternalKernel) {
const kernelClient = getKernelClient();
const modelConfig = getDefaultModelConfig();
if (!modelConfig) {
throw new Error('请先在"模型与 API"设置页面添加自定义模型配置');
}
kernelClient.setConfig({
provider: modelConfig.provider,
model: modelConfig.model,
apiKey: modelConfig.apiKey,
baseUrl: modelConfig.baseUrl,
});
await kernelClient.connect();
set({ client: kernelClient, gatewayVersion: '0.2.0-internal' });
return;
}
// 非 Tauri 环境...
}
```
---
## 九、支持的 Provider
### 9.1 Provider 列表
| Provider | Driver | Base URL | API 协议 |
|----------|--------|----------|----------|
| kimi | OpenAiDriver | `https://api.kimi.com/coding/v1` | OpenAI 兼容 |
| qwen | OpenAiDriver | `https://dashscope.aliyuncs.com/compatible-mode/v1` | OpenAI 兼容 |
| deepseek | OpenAiDriver | `https://api.deepseek.com/v1` | OpenAI 兼容 |
| zhipu | OpenAiDriver | `https://open.bigmodel.cn/api/paas/v4` | OpenAI 兼容 |
| openai | OpenAiDriver | `https://api.openai.com/v1` | OpenAI |
| anthropic | AnthropicDriver | `https://api.anthropic.com` | Anthropic |
| gemini | GeminiDriver | `https://generativelanguage.googleapis.com` | Gemini |
| local | LocalDriver | `http://localhost:11434/v1` | OpenAI 兼容 |
### 9.2 配置示例
```typescript
// Kimi Code 配置
{
provider: 'kimi',
model: 'kimi-k2-turbo',
apiKey: 'your-kimi-api-key',
baseUrl: 'https://api.kimi.com/coding/v1'
}
// 百炼 Qwen 配置
{
provider: 'qwen',
model: 'qwen-plus',
apiKey: 'your-qwen-api-key',
baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1'
}
```
---
## 十、开发命令
### 10.1 构建命令
```bash
# 构建所有 crates
cargo build
# 构建生产版本
cargo build --release
# 运行测试
cargo test
# 启动开发环境
pnpm start:dev
```
### 10.2 常用命令
```bash
# 安装依赖
pnpm install
# 类型检查
pnpm tsc --noEmit
# 运行测试
pnpm vitest run
# E2E 测试
pnpm test:e2e
```
---
## 十一、参考资料
### 11.1 相关文档
- [快速启动指南](../quick-start.md)
- [模型配置指南](./configuration.md)
- [通信层文档](../features/00-architecture/01-communication-layer.md)
- [后端集成文档](../features/06-tauri-backend/00-backend-integration.md)
### 11.2 架构演进
| 版本 | 架构 | 说明 |
|------|------|------|
| v1.x | 外部 OpenFang | 需要启动独立后端进程 |
| v2.0 | 内部 Kernel | Kernel 集成在 Tauri 中,无需外部进程 |
---
*文档版本: v2.0 | 更新日期: 2026-03-22*