Files
zclaw_openfang/docs/features/SYSTEM_ARCHITECTURE.md
iven 7de294375b
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
feat(auth): 添加异步密码哈希和验证函数
refactor(relay): 复用HTTP客户端和请求体序列化结果

feat(kernel): 添加获取单个审批记录的方法

fix(store): 改进SaaS连接错误分类和降级处理

docs: 更新审计文档和系统架构文档

refactor(prompt): 优化SQL查询参数化绑定

refactor(migration): 使用静态SQL和COALESCE更新配置项

feat(commands): 添加审批执行状态追踪和事件通知

chore: 更新启动脚本以支持Admin后台

fix(auth-guard): 优化授权状态管理和错误处理

refactor(db): 使用异步密码哈希函数

refactor(totp): 使用异步密码验证函数

style: 清理无用文件和注释

docs: 更新功能全景和审计文档

refactor(service): 优化HTTP客户端重用和请求处理

fix(connection): 改进SaaS不可用时的降级处理

refactor(handlers): 使用异步密码验证函数

chore: 更新依赖和工具链配置
2026-03-29 21:45:29 +08:00

811 lines
32 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 多端系统架构文档
> 版本: 1.1 | 日期: 2026-03-29 | 状态: 已更新 (Worker + Scheduler + SQL 迁移 + 多环境配置)
---
## 目录
1. [系统总览](#1-系统总览)
2. [端口与协议分配](#2-端口与协议分配)
3. [技术栈选型](#3-技术栈选型)
4. [数据流向](#4-数据流向)
5. [SaaS 后端 API 接口清单](#5-saas-后端-api-接口清单)
6. [桌面端内部通信](#6-桌面端内部通信)
7. [权限体系](#7-权限体系)
8. [各端交互逻辑](#8-各端交互逻辑)
9. [部署与启动](#9-部署与启动)
10. [接口设计背景与业务价值](#10-接口设计背景与业务价值)
---
## 1. 系统总览
ZCLAW 是面向中文用户的 AI Agent 桌面客户端,由 **4 个独立服务/端** 组成:
```
┌─────────────────────────────────────────────────────────────────┐
│ ZCLAW 系统架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Desktop App │ │ Admin Web │ │ SaaS Backend │ │
│ │ (Tauri+React)│ │ (Next.js) │ │ (Axum + PostgreSQL) │ │
│ │ Port: 1420 │ │ Port: 3000 │ │ Port: 8080 │ │
│ │ │ │ │ │ │ │
│ │ 内核模式: │ │ 管理后台 │ │ REST API │ │
│ │ Tauri IPC │ │ JWT 鉴权 │ │ JWT + API Token │ │
│ │ │ │ │ │ RBAC 权限 │ │
│ │ 网关模式: │ │ │ │ │ │
│ │ WS :50051 │ │ │ │ ┌────────────────┐ │ │
│ │ WS :4200 │ │ │ │ │ PostgreSQL │ │ │
│ │ │ │ │ │ │ Port: 5432 │ │ │
│ │ SaaS 模式: │ │ │ │ └────────────────┘ │ │
│ │ HTTPS REST │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ ZCLAW 网关 │ │ LLM 服务商 │ │
│ │ (独立二进制) │ │ (外部) │ │
│ │ Port: 4200 │ │ OpenAI 等 │ │
│ │ Port: 50051 │ │ │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### 核心设计理念
- **双模式架构**: 桌面端支持「本地内核」(离线/低延迟) 和「远程网关」(团队协作) 两种运行模式
- **统一 LLM 接入**: 4 条 LLM 路径 (直连 OpenAI、直连火山引擎、SaaS 中转、网关透传)
- **集中管控**: SaaS 后端统一管理账号、模型、服务商、Prompt 模板、配置同步
- **安全审计**: 完整的操作日志 + TOTP 2FA + JWT + RBAC
---
## 2. 端口与协议分配
| 端口 | 服务 | 协议 | 用途 | 启动方式 |
|------|------|------|------|----------|
| 1420 | Vite Dev Server | HTTP | 桌面端前端开发服务 (仅 dev) | `pnpm tauri dev` |
| 3000 | Next.js Dev Server | HTTP | Admin 管理后台开发服务 | `pnpm dev` (admin/) |
| 4200 | ZCLAW Gateway/Kernel | WebSocket + REST | 网关备用端口 | ZCLAW 二进制 |
| 50051 | ZCLAW Gateway | WebSocket + REST | 网关主端口 | ZCLAW 二进制 |
| 5432 | PostgreSQL | PostgreSQL Wire | SaaS 后端数据库 | Docker/start-all.ps1 |
| 8080 | SaaS Backend | HTTP REST | 管理后台 API + 中转代理 | start-saas.ps1 |
| 4444 | ChromeDriver | WebDriver HTTP | 浏览器 Hand 自动化 | start-all.ps1 |
| N/A | Tauri IPC | invoke() | 桌面端内部进程通信 | 内嵌 |
---
## 3. 技术栈选型
### 3.1 桌面端 (Desktop)
| 层级 | 技术 | 选型理由 |
|------|------|----------|
| 桌面框架 | Tauri 2.x | Rust 原生性能,小体积,安全 IPC |
| 前端框架 | React 18 + TypeScript | 生态丰富,类型安全 |
| 状态管理 | Zustand | 轻量、灵活、无 boilerplate |
| 样式方案 | Tailwind CSS | 原子化 CSS暗色主题友好 |
| 数据存储 | SQLite (本地) | 离线优先FTS5 全文搜索 |
### 3.2 Admin 管理后台
| 层级 | 技术 | 选型理由 |
|------|------|----------|
| 框架 | Next.js 14 (App Router) | SSR/CSR 灵活切换API 代理 |
| 数据获取 | SWR 2.x | 缓存+去重+自动重验证stale-while-revalidate |
| UI 组件 | shadcn/ui | 暗色主题原生支持,可定制 |
| 图表 | Recharts | React 原生集成,轻量 |
### 3.3 SaaS 后端
| 层级 | 技术 | 选型理由 |
|------|------|----------|
| Web 框架 | Axum | Rust 高性能异步 Web 框架 |
| 数据库 | PostgreSQL | 关系型,复杂查询支持好 |
| ORM | sqlx | 编译时 SQL 检查,零开销 |
| 认证 | JWT + TOTP | 无状态鉴权 + 双因素认证 |
| 加密 | AES-256-GCM | API Key 加密存储 |
| 后台任务 | Worker trait + mpsc Channel | 异步非阻塞,支持自动重试 |
| 定时任务 | 声明式 Scheduler (TOML) | 无需改代码调整调度时间 |
| 连接池 | sqlx PgPool (50 max / 5 min) | 高并发,自动管理生命周期 |
| 迁移系统 | SQL 文件 + Schema 版本控制 | TIMESTAMPTZ 类型,向后兼容 |
| 多环境 | ZCLAW_ENV (dev/prod/test) | 配置隔离,环境变量覆盖 |
### 3.4 核心运行时 (Rust Workspace)
```
zclaw-types → 基础类型 (AgentId, Message, Error)
zclaw-memory → 存储层 (SQLite, FTS5, TF-IDF, Embeddings)
zclaw-runtime → 运行时 (LLM 驱动, 工具, Agent 循环)
zclaw-kernel → 核心协调 (注册, 调度, 事件, 工作流)
zclaw-skills → 技能系统 (SKILL.md 解析, WASM 执行器)
zclaw-hands → 自主能力 (Hand/Trigger 注册管理)
zclaw-protocols → 协议支持 (MCP, A2A)
zclaw-saas → SaaS 后端 (独立服务, 8080 端口)
```
---
## 4. 数据流向
### 4.1 Admin 管理后台数据流
```
用户操作 → React UI → SWR Hook → api-client.ts → Next.js Rewrites → SaaS 后端 (:8080)
↑ ↓
└── SWR Cache ←── JSON Response ←── PostgreSQL (:5432) ←─┘
```
**关键路径:**
- Admin 前端所有请求通过 `next.config.js rewrites` 代理到 `localhost:8080`
- API 基路径: `/api/v1/*` (前端) → `http://localhost:8080/api/v1/*` (后端)
- SWR 缓存: 页面切换后缓存 5s 去重stale-while-revalidate 模式
### 4.2 桌面端数据流 (Tauri 模式)
```
React UI → Zustand Store → invoke() IPC → Rust Tauri Commands → Kernel → LLM/Tools/Skills/Hands
SQLite (~/.zclaw/data.db)
```
### 4.3 桌面端数据流 (网关模式)
```
React UI → gateway-client.ts → WebSocket (:50051) → ZCLAW Gateway → Kernel
→ REST API (/api/*) →
```
### 4.4 桌面端数据流 (SaaS 模式)
```
React UI → saas-client.ts → HTTPS REST → SaaS 后端 (:8080)
llm-service.ts → relay/chat/completions → Provider → LLM API
```
### 4.5 LLM 请求路由 (4 条路径)
```
┌─────────────┐ ┌─ Direct OpenAI ────→ api.openai.com
│ │ ├─ Direct Volcengine ─→ volcengine endpoint
│ llm-service│────┤
│ │ ├─ SaaS Relay ────────→ saas.zclaw.com/relay → Provider
│ │ └─ Gateway ───────────→ invoke('agent_chat') or REST
└─────────────┘
```
---
## 5. SaaS 后端 API 接口清单
### 5.0 通用规范
- **Base URL**: `http://localhost:8080/api/v1`
- **认证方式**: `Authorization: Bearer <JWT_TOKEN>``Authorization: Bearer zclaw_<API_KEY>`
- **Content-Type**: `application/json`
- **分页响应格式**: `{ items: T[], total: number, page: number, page_size: number }`
- **错误响应格式**: `{ error: string, message: string }`
- **HTTP 状态码**: 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 500 Internal Error
### 5.1 公开接口 (无需认证)
| # | 方法 | 路径 | 用途 | 业务价值 |
|---|------|------|------|----------|
| 1 | GET | `/api/health` | 健康检查 | 运维监控探针,检测 DB 连通性 |
| 2 | POST | `/api/v1/auth/register` | 用户注册 | 自助开户,降低运营成本 |
| 3 | POST | `/api/v1/auth/login` | 用户登录 | 身份验证入口,支持 TOTP 2FA |
| 4 | POST | `/api/v1/auth/refresh` | Token 刷新 | 无感续期,单次使用 refresh_token |
**POST /api/v1/auth/login**
请求:
```typescript
{
username: string // 接受用户名或邮箱
password: string // 8-128 字符
totp_code?: string // 6 位数字,启用 TOTP 时必填
}
```
响应:
```typescript
{
token: string // JWT access token
refresh_token: string // 单次使用 refresh token
account: AccountPublic
}
```
### 5.2 认证自服务接口 (需登录)
| # | 方法 | 路径 | 用途 |
|---|------|------|------|
| 5 | GET | `/api/v1/auth/me` | 获取当前用户信息 |
| 6 | PUT | `/api/v1/auth/password` | 修改密码 |
| 7 | POST | `/api/v1/auth/totp/setup` | 生成 TOTP 密钥 |
| 8 | POST | `/api/v1/auth/totp/verify` | 激活 TOTP 2FA |
| 9 | POST | `/api/v1/auth/totp/disable` | 关闭 TOTP 2FA |
### 5.3 账号管理接口 (Admin)
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 10 | GET | `/api/v1/accounts` | 账号列表 (支持搜索/筛选/分页) | `account:admin` |
| 11 | GET | `/api/v1/accounts/:id` | 账号详情 | `account:admin` |
| 12 | PATCH | `/api/v1/accounts/:id` | 更新账号信息 | `account:admin` |
| 13 | PATCH | `/api/v1/accounts/:id/status` | 变更账号状态 | `account:admin` |
| 14 | GET | `/api/v1/logs/operations` | 操作日志列表 | `account:admin` |
| 15 | GET | `/api/v1/stats/dashboard` | 仪表盘统计聚合 | `account:admin` |
| 16 | GET | `/api/v1/devices` | 用户设备列表 | 认证用户 |
| 17 | POST | `/api/v1/devices/register` | 注册/更新设备 | 认证用户 |
| 18 | POST | `/api/v1/devices/heartbeat` | 设备心跳 | 认证用户 |
**GET /api/v1/accounts** 查询参数:
```typescript
{
page?: number // 页码,默认 1
page_size?: number // 每页条数,默认 20
search?: string // 搜索用户名/邮箱/显示名
role?: string // 按角色筛选: super_admin | admin | user
status?: string // 按状态筛选: active | disabled | suspended
}
```
**GET /api/v1/stats/dashboard** 响应:
```typescript
{
total_accounts: number
active_accounts: number
tasks_today: number
active_providers: number
active_models: number
tokens_today_input: number
tokens_today_output: number
}
```
### 5.4 服务商管理接口
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 19 | GET | `/api/v1/providers` | 服务商列表 | 认证用户 |
| 20 | GET | `/api/v1/providers/:id` | 服务商详情 | 认证用户 |
| 21 | POST | `/api/v1/providers` | 创建服务商 | `provider:manage` |
| 22 | PATCH | `/api/v1/providers/:id` | 更新服务商 | `provider:manage` |
| 23 | DELETE | `/api/v1/providers/:id` | 删除服务商 | `provider:manage` |
| 24 | GET | `/api/v1/providers/:id/models` | 服务商下的模型列表 | 认证用户 |
**Provider 数据结构:**
```typescript
{
id: string
name: string // 唯一标识名,如 "openai"
display_name: string // 显示名,如 "OpenAI"
base_url: string // API 基地址
api_protocol: 'openai' | 'anthropic'
enabled: boolean
rate_limit_rpm?: number // 每分钟请求限制
rate_limit_tpm?: number // 每分钟 Token 限制
created_at: string
updated_at: string
}
```
### 5.5 模型管理接口
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 25 | GET | `/api/v1/models` | 模型列表 | 认证用户 |
| 26 | GET | `/api/v1/models/:id` | 模型详情 | 认证用户 |
| 27 | POST | `/api/v1/models` | 创建模型 | `model:manage` |
| 28 | PATCH | `/api/v1/models/:id` | 更新模型 | `model:manage` |
| 29 | DELETE | `/api/v1/models/:id` | 删除模型 | `model:manage` |
**Model 数据结构:**
```typescript
{
id: string
provider_id: string
model_id: string // 如 "gpt-4o"
alias: string // 显示别名
context_window: number // 上下文窗口大小
max_output_tokens: number // 最大输出 Token
supports_streaming: boolean
supports_vision: boolean
enabled: boolean
pricing_input: number // $/1M tokens
pricing_output: number // $/1M tokens
}
```
### 5.6 API Key 管理接口
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 30 | GET | `/api/v1/keys` | 当前用户的 API Key 列表 | 认证用户 |
| 31 | POST | `/api/v1/keys` | 创建 API Key | 认证用户 |
| 32 | POST | `/api/v1/keys/:id/rotate` | 轮换 API Key | 认证用户 |
| 33 | DELETE | `/api/v1/keys/:id` | 撤销 API Key | 认证用户 |
### 5.7 Key Pool 管理接口 (Admin)
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 34 | GET | `/api/v1/providers/:id/keys` | 服务商 Key Pool 列表 | `provider:manage` |
| 35 | POST | `/api/v1/providers/:id/keys` | 添加 Key 到 Pool | `provider:manage` |
| 36 | PUT | `/api/v1/providers/:id/keys/:keyId/toggle` | 启用/禁用 Key | `provider:manage` |
| 37 | DELETE | `/api/v1/providers/:id/keys/:keyId` | 删除 Key | `provider:manage` |
**业务价值**: Key Pool 实现多 API Key 智能轮转,自动绕过 429 限流,提升整体吞吐量。
### 5.8 中转代理接口 (Relay)
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 38 | POST | `/api/v1/relay/chat/completions` | LLM 中转请求 | `relay:use` |
| 39 | GET | `/api/v1/relay/tasks` | 中转任务列表 | 认证用户 |
| 40 | GET | `/api/v1/relay/tasks/:id` | 任务详情 | 认证用户 |
| 41 | POST | `/api/v1/relay/tasks/:id/retry` | 重试失败任务 | `relay:admin` |
| 42 | GET | `/api/v1/relay/models` | 可用模型列表 | 认证用户 |
**POST /api/v1/relay/chat/completions** — 核心中转接口
请求: OpenAI 兼容格式
```typescript
{
model: string
messages: Array<{ role: string, content: string }>
temperature?: number
max_tokens?: number
stream?: boolean // 支持 SSE 流式响应
// ... 其他字段透传给服务商
}
```
响应:
- 非流式: `application/json` — 原始服务商响应
- 流式: `text/event-stream` — SSE 事件流
**业务价值**: 统一入口代理多家 LLM 服务商,自动 Key Pool 轮转、429 处理、用量计费。
### 5.9 用量统计接口
| # | 方法 | 路径 | 用途 |
|---|------|------|------|
| 43 | GET | `/api/v1/usage` | 用量统计 (按天/按模型) |
**查询参数:**
```typescript
{
from?: string // ISO 8601 开始日期
to?: string // ISO 8601 结束日期
provider_id?: string // 按服务商筛选
model_id?: string // 按模型筛选
group_by?: 'day' | 'model'
days?: number // 最近 N 天
}
```
**响应:**
```typescript
{
total_requests: number
total_input_tokens: number
total_output_tokens: number
by_model: Array<{ model_id, count, input_tokens, output_tokens }>
by_day: Array<{ day, count, input_tokens, output_tokens }>
}
```
### 5.10 配置管理接口
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 44 | GET | `/api/v1/config/items` | 配置项列表 | 认证用户 |
| 45 | GET | `/api/v1/config/items/:id` | 配置项详情 | 认证用户 |
| 46 | POST | `/api/v1/config/items` | 创建配置项 | `config:write` |
| 47 | PATCH | `/api/v1/config/items/:id` | 更新配置项 | `config:write` |
| 48 | DELETE | `/api/v1/config/items/:id` | 删除配置项 | `config:write` |
| 49 | GET | `/api/v1/config/analysis` | 配置分析 | 认证用户 |
| 50 | POST | `/api/v1/config/seed` | 种子配置 | `config:write` |
| 51 | POST | `/api/v1/config/sync` | 双向配置同步 | `config:write` |
| 52 | POST | `/api/v1/config/diff` | 配置差异比较 | 认证用户 |
| 53 | GET | `/api/v1/config/sync-logs` | 同步日志 | 认证用户 |
| 54 | GET | `/api/v1/config/pull` | 批量拉取配置 | 认证用户 |
**业务价值**: 集中管理所有运行参数服务器、Agent、记忆、LLM、安全策略支持桌面端双向同步推送/拉取/合并三种模式。
### 5.11 角色与权限接口
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 55 | GET | `/api/v1/roles` | 角色列表 | `account:read` |
| 56 | GET | `/api/v1/roles/:id` | 角色详情 | `account:read` |
| 57 | POST | `/api/v1/roles` | 创建角色 | `account:admin` |
| 58 | PUT | `/api/v1/roles/:id` | 更新角色 | `account:admin` |
| 59 | DELETE | `/api/v1/roles/:id` | 删除角色 | `account:admin` |
| 60 | GET | `/api/v1/roles/:id/permissions` | 角色权限列表 | `account:read` |
| 61 | GET | `/api/v1/permission-templates` | 权限模板列表 | `account:read` |
| 62 | GET | `/api/v1/permission-templates/:id` | 权限模板详情 | `account:read` |
| 63 | POST | `/api/v1/permission-templates` | 创建权限模板 | `account:admin` |
| 64 | DELETE | `/api/v1/permission-templates/:id` | 删除权限模板 | `account:admin` |
| 65 | POST | `/api/v1/permission-templates/:id/apply` | 批量应用权限模板 | `account:admin` |
### 5.12 Prompt 模板管理接口
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 66 | GET | `/api/v1/prompts` | 模板列表 | `prompt:read` |
| 67 | POST | `/api/v1/prompts` | 创建模板 | `prompt:write` |
| 68 | GET | `/api/v1/prompts/:name` | 模板详情 | `prompt:read` |
| 69 | PUT | `/api/v1/prompts/:name` | 更新模板元数据 | `prompt:write` |
| 70 | DELETE | `/api/v1/prompts/:name` | 归档模板 | `prompt:admin` |
| 71 | GET | `/api/v1/prompts/:name/versions` | 版本历史 | `prompt:read` |
| 72 | GET | `/api/v1/prompts/:name/versions/:v` | 特定版本 | `prompt:read` |
| 73 | POST | `/api/v1/prompts/:name/versions` | 发布新版本 | `prompt:write` |
| 74 | POST | `/api/v1/prompts/:name/rollback/:v` | 回滚版本 | `prompt:admin` |
| 75 | POST | `/api/v1/prompts/check` | OTA 更新检查 | 认证用户 |
**POST /api/v1/prompts/check** — OTA 更新检查
请求:
```typescript
{
device_id: string
versions: Record<string, number> // { "reflection": 3, "compaction": 2 }
}
```
响应:
```typescript
{
updates: Array<{
name: string
version: number
system_prompt: string
user_prompt_template?: string
variables: PromptVariable[]
source: string
min_app_version?: string
}>
server_time: string
}
```
**业务价值**: 集中管理 Prompt 模板,桌面端每 30 分钟检查更新,无需发版即可优化提示词。
### 5.13 Agent 模板管理接口
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 76 | GET | `/api/v1/agent-templates` | Agent 模板列表 | `model:read` |
| 77 | POST | `/api/v1/agent-templates` | 创建 Agent 模板 | `model:manage` |
| 78 | GET | `/api/v1/agent-templates/:id` | 模板详情 | `model:read` |
| 79 | POST | `/api/v1/agent-templates/:id` | 更新模板 | `model:manage` |
| 80 | DELETE | `/api/v1/agent-templates/:id` | 归档模板 | `model:manage` |
**AgentTemplate 数据结构:**
```typescript
{
id: string
name: string
description?: string
category: string
source: 'builtin' | 'custom'
model?: string
system_prompt?: string
tools: string[]
capabilities: string[]
temperature?: number
max_tokens?: number
visibility: 'public' | 'team' | 'private'
status: 'active' | 'archived'
current_version: number
}
```
### 5.14 遥测接口
| # | 方法 | 路径 | 用途 | 权限 |
|---|------|------|------|------|
| 81 | POST | `/api/v1/telemetry/report` | 上报遥测数据 | 认证用户 |
| 82 | GET | `/api/v1/telemetry/stats` | 按模型统计 | 认证用户 |
| 83 | GET | `/api/v1/telemetry/daily` | 按天统计 | 认证用户 |
| 84 | POST | `/api/v1/telemetry/audit` | 上报审计摘要 | 认证用户 |
**POST /api/v1/telemetry/report** 请求:
```typescript
{
device_id: string
app_version: string
entries: Array<{
model_id: string
input_tokens: number
output_tokens: number
latency_ms?: number
success: boolean
error_type?: string
timestamp: string
connection_mode: 'tauri' | 'saas'
}> // 最多 500 条/请求
}
```
**业务价值**: 桌面端批量上报本地 LLM 用量,管理员可在后台查看所有设备的 Token 消耗、延迟、成功率。
---
## 6. 桌面端内部通信
### 6.1 Tauri Commands 清单
桌面端通过 `invoke()` IPC 暴露以下命令组:
| 命令组 | 文件 | 命令数 | 用途 |
|--------|------|--------|------|
| 进程管理 | lib.rs | 10 | zclaw_start/stop/restart, doctor, health_check |
| 内核操作 | kernel_commands.rs | 20+ | agent_create/chat_stream, skill_execute, hand_execute |
| 工作流 | pipeline_commands.rs | 9 | pipeline_run/progress/cancel, route_intent |
| 持久记忆 | memory_commands.rs | 12 | memory_store/get/search/export |
| Viking 存储 | viking_commands.rs | 9 | viking_add/find/grep/read |
| 智能钩子 | intelligence_hooks.rs | 2 | pre/post_conversation_hook |
### 6.2 WebSocket 事件类型
| 方向 | 事件 | 说明 |
|------|------|------|
| Server→Client | `text_delta` | 流式文本片段 |
| Server→Client | `phase` | 阶段切换 (thinking/tool) |
| Server→Client | `tool_call` / `tool_result` | 工具调用与结果 |
| Server→Client | `hand` | Hand 自主能力触发 |
| Server→Client | `error` | 错误通知 |
| Client→Server | `message` | 发送消息 |
| Client→Server | `auth_challenge` / `auth_response` | Ed25519 握手 |
| 双向 | `ping` / `pong` | 心跳 (30s 间隔) |
---
## 7. 权限体系
### 7.1 角色定义
| 角色 | 权限范围 |
|------|----------|
| `super_admin` | 全部权限 (`admin:full`) |
| `admin` | 账号管理、服务商/模型管理、中转管理、配置读写、Prompt 读写发布 |
| `user` | 模型读取、中转使用、配置读取、Prompt 读取 |
### 7.2 权限清单
| 权限 | 说明 |
|------|------|
| `admin:full` | 超级权限,绕过所有检查 |
| `account:admin` | 账号管理 (列表、状态变更、角色分配) |
| `account:read` | 读取账号、角色、权限模板 |
| `provider:manage` | 创建/更新/删除服务商、管理 Key Pool |
| `model:manage` | 创建/更新/删除模型、Agent 模板 |
| `model:read` | 读取模型、Agent 模板 |
| `relay:use` | 使用中转 (chat completions) |
| `relay:admin` | 查看任意中转任务、重试失败任务 |
| `config:write` | 创建/更新/删除配置项、同步、种子 |
| `prompt:read` | 读取 Prompt 模板和版本 |
| `prompt:write` | 创建/更新 Prompt 模板和版本 |
| `prompt:admin` | 归档 Prompt、回滚版本 |
---
## 8. 各端交互逻辑
### 8.1 Admin 管理后台 ↔ SaaS 后端
```
┌───────────────────────────────────────────────────────────┐
│ Admin 浏览器 (localhost:3000) │
│ │
│ ┌──────────┐ SWR Cache ┌──────────────┐ │
│ │ React UI │◄────────────►│ api-client │ │
│ │ 11 页面 │ │ JWT 鉴权 │ │
│ └──────────┘ └──────┬───────┘ │
│ │ fetch() │
└──────────────────────────────────┼────────────────────────┘
Next.js Rewrite│ /api/* → localhost:8080/api/*
┌──────────────────────────────────┼────────────────────────┐
│ SaaS Backend (:8080) │ │
│ ┌──────▼───────┐ │
│ │ Axum Router │ │
│ │ 中间件栈: │ │
│ │ 1. Auth │ │
│ │ 2. RateLimit │ │
│ │ 3. RequestID │ │
│ │ 4. Version │ │
│ └──────┬───────┘ │
│ │ │
│ ┌─────────────▼──────────────┐ │
│ │ Handlers (72 个端点) │ │
│ │ auth/account/model/relay/ │ │
│ │ config/prompt/telemetry/ │ │
│ └─────────────┬──────────────┘ │
│ │ │
│ ┌─────────────▼──────────────┐ │
│ │ PostgreSQL (:5432) │ │
│ └─────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘
```
### 8.2 桌面端交互矩阵
| 场景 | 通信方式 | 目标 | 数据 |
|------|----------|------|------|
| 本地对话 | Tauri IPC invoke() | Kernel | 消息、Agent、Skills |
| 流式响应 | Tauri Event listen() | Kernel | stream:chunk 事件 |
| 远程对话 | WebSocket :50051 | ZCLAW Gateway | 消息、事件流 |
| SaaS 登录 | HTTPS REST | SaaS :8080 | JWT 认证 |
| LLM 中转 | HTTPS REST | SaaS :8080/relay | OpenAI 兼容请求 |
| Prompt OTA | HTTPS REST | SaaS :8080/prompts/check | 版本号 → 更新 |
| 配置同步 | HTTPS REST | SaaS :8080/config/sync | 双向键值对 |
| 遥测上报 | HTTPS REST | SaaS :8080/telemetry/report | 批量用量数据 |
---
## 9. 部署与启动
### 9.1 完整启动顺序
```powershell
# start-all.ps1 启动顺序:
1. PostgreSQL :5432 (Docker 或本地服务)
2. SaaS Backend :8080 (zclaw-saas.exe)
3. ChromeDriver :4444 (可选, 用于 Browser Hand)
4. Desktop Dev :1420 (Tauri dev)
```
### 9.2 SaaS 后端配置
#### 配置加载优先级
```
ZCLAW_SAAS_CONFIG (精确路径) > ZCLAW_ENV (环境选择) > ./saas-config.toml (默认)
```
环境配置文件:
- `ZCLAW_ENV=development` -> `config/saas-development.toml`
- `ZCLAW_ENV=production` -> `config/saas-production.toml`
- `ZCLAW_ENV=test` -> `config/saas-test.toml`
环境变量覆盖:
- `ZCLAW_DATABASE_URL` — 覆盖数据库 URL (避免配置文件存密码)
- `ZCLAW_SAAS_JWT_SECRET` — JWT 签名密钥 (生产环境必须设置)
- `ZCLAW_TOTP_ENCRYPTION_KEY` — TOTP/AES-256-GCM 加密密钥 (hex 64 字符)
- `ZCLAW_SAAS_DEV` — 开发模式 (允许使用不安全的默认密钥)
#### 配置结构
```toml
# saas-config.toml
[server]
host = "0.0.0.0"
port = 8080
cors_origins = []
[database]
url = "postgres://postgres:123123@localhost:5432/zclaw"
[auth]
jwt_expiration_hours = 24
totp_issuer = "ZCLAW SaaS"
refresh_token_hours = 168 # 7 天
[relay]
max_queue_size = 1000
max_concurrent_per_provider = 5 # 预留
batch_window_ms = 50 # 预留
retry_delay_ms = 1000
max_attempts = 3
[rate_limit]
requests_per_minute = 60
burst = 10
# 声明式定时任务 (新增)
[[scheduler.jobs]]
name = "cleanup-refresh-tokens"
interval = "1h"
task = "cleanup_refresh_tokens"
run_on_start = false
[[scheduler.jobs]]
name = "cleanup-rate-limit"
interval = "5m"
task = "cleanup_rate_limit"
run_on_start = false
```
#### 连接池参数
| 参数 | 值 | 说明 |
|------|-----|------|
| max_connections | 50 | 最大并发连接数 |
| min_connections | 5 | 最小空闲连接数 |
| acquire_timeout | 10s | 获取连接超时 |
| idle_timeout | 300s | 空闲连接回收 |
| max_lifetime | 1800s | 连接最大生命周期 |
#### Worker 系统
| Worker | 职责 | 触发方式 |
|--------|------|---------|
| LogOperationWorker | 异步写入操作日志 | Handler 派发 |
| CleanupRefreshTokensWorker | 清理过期 Refresh Token | Scheduler 定时 |
| CleanupRateLimitWorker | 清理过期限流条目 | Scheduler 定时 |
| RecordUsageWorker | 记录 Token 用量 | Relay Handler 派发 |
| UpdateLastUsedWorker | 更新 Key 最后使用时间 | Relay Handler 派发 |
#### SQL 迁移系统
- Schema 版本: **v6**
- 迁移目录: `crates/zclaw-saas/migrations/`
- 时间戳类型: **TIMESTAMPTZ** (新库),向后兼容 TEXT (旧库)
- 迁移文件按文件名排序执行
---
## 10. 接口设计背景与业务价值
### 10.1 中转代理 (Relay) — 核心收入引擎
**背景**: 多家 LLM 服务商 API 各不相同,用户需统一入口。
**设计价值**:
- OpenAI 兼容接口降低接入成本
- Key Pool 智能轮转绕过限流
- 自动 429 处理 + 冷却恢复
- 按账号精确计费 (input/output tokens)
### 10.2 Prompt OTA — 无感更新
**背景**: Prompt 工程需要频繁迭代,但桌面端发版周期长。
**设计价值**:
- 集中管理 reflection/compaction/extraction 等核心 Prompt
- 桌面端每 30 分钟自动检查更新
- 版本化 + 回滚能力
- min_app_version 兼容性控制
### 10.3 配置同步 — 多设备一致
**背景**: 用户多台设备需保持配置一致。
**设计价值**:
- push/pull/merge 三种同步模式
- 乐观锁 (client_timestamps) 冲突检测
- 只读 diff 不修改数据
- 同步日志可追溯
### 10.4 Key Pool — 高可用保障
**背景**: 单个 API Key 容易触发限流 (429)。
**设计价值**:
- 多 Key 按优先级智能选择
- 429 自动冷却 + 切换
- RPM/TPM 限额独立配置
- 配额重置周期支持
### 10.5 遥测上报 — 数据驱动优化
**背景**: 桌面端本地 LLM 用量无法直接观测。
**设计价值**:
- 批量上报 (500 条/次) 减少请求
- 按模型聚合: Token 消耗、延迟、成功率
- 按天聚合: 请求量、设备活跃度
- 审计摘要: 操作类型 + 结果
---
> **文档统计**: 84 个 API 端点 | 5 个通信通道 | 12 种权限 | 4 个独立服务 | 5 个 Workers | 声明式 Scheduler | SQL Schema v6