架构概览
本文描述 Wesclaw 的整体技术架构,帮助开发者和高级用户理解系统的运作方式。
双进程架构
Wesclaw 桌面版采用双进程架构:
┌──────────────────────────────┐
│ Electron 主进程(Node.js) │
│ ┌────────────────────────┐ │
│ │ Renderer (React) │ │
│ │ window.wesclaw.rpc() │ │
│ └─────────┬──────────────┘ │
└────────────┼─────────────────┘
│ stdio JSON-RPC
┌────────────▼─────────────────┐
│ Go 后端进程 (wesclaw rpc) │
│ ┌────────────────────────┐ │
│ │ wesgine Hypervisor │ │
│ │ └── Cell "main" │ │
│ │ └── Runtime │ │
│ └────────────────────────┘ │
└──────────────────────────────┘
两个入口命令
| 命令 | 用途 | 说明 |
|---|---|---|
wesclaw rpc | Electron RPC 模式 | stdio JSON-RPC,桌面唯一热路径 |
wesclaw serve | 本机 HTTP 模式 | N=1 单 Cell HTTP,不是 SaaS |
通信方式
桌面版:stdio JSON-RPC
Renderer → Electron Main → Go 后端
window.wesclaw.rpc(method, params)
- Renderer 不直接 fetch
- 所有 RPC 通过
window.wesclaw.rpc()走 stdio - SSE 流通过
sseRouteStream→http/routestream_id 实现
SaaS 版:HTTP + SSE + JWT
浏览器 → nginx → 平台 :8080 / 引擎 :8081
- JWT 验证 weisyn 公钥
- 独立进程、独立数据目录
- 源码锁
split_guard_test.go确保不混用
Boot 装配
启动流程
// 1. 创建 Hypervisor
hyp, _ := wesgine.NewHypervisor(ctx, wesgine.HypervisorConfig{
DataDir: xdg.NewAppDirs("wesclaw", "WESCLAW").DataDir(),
CrashDir: xdg.NewAppDirs("wesclaw", "WESCLAW").CrashDir(),
})
must(hyp.Start(ctx))
// 2. 绑定 ProviderLiveKeyFn(GetOrCreate 前必须完成)
liveTokens := &providerid.LiveTokenSource{}
spec.ProviderLiveKeyFn = liveTokens.Key
// 3. 创建或获取 main Cell
cell, _ := hyp.Cells().GetOrCreate(ctx, wesgine.CellSpec{
ID: "main",
Timezone: "Asia/Shanghai",
Locale: "zh-CN",
Governance: wesgine.DefaultGovernance(),
ProviderStrategy: "own_only",
Compliance: "standard",
})
关键约束
hyp.Start()只挂身份骨架(Cool/Cold),永不Cell.StartGetOrCreate前必须绑齐json:"-"进程 hookwes:/org:落盘SourceLive却不绑 getter → fail-loud- 禁止
ActivatePersisted
前端不感知 Cell(PROD-1)
Wesclaw 桌面版遵循 PROD-1 原则:
| 规则 | 说明 |
|---|---|
无 activeCell store | 前端没有 Cell 概念 |
无 cell_id RPC 参数 | 后端单 Cell 绑定 |
无 cell/list RPC | 不暴露 Cell 列表 |
| 切账号 = Go 进程重启 | 不是 per-RPC cell_id |
// Go 后端 Handler.instance 永远绑定 boot 时创建的 main Cell
type Handler struct {
instance *wesgine.Cell
runtime *wesgine.RuntimeHandle
}
UI 禁词
以下术语不得出现在面向用户的 UI 中:
Cell / CellID / cell.db / Hypervisor / Governance
GovernMode / ScopeOwner / MemoryScope / scope
数据目录结构
$XDG_DATA_HOME/wesclaw/ # 唯一数据根
├── hypervisor.db # Cell 注册表
├── cells/main/ # 默认 Cell
│ ├── meta.db # Cell 元数据
│ ├── sessions.db # 会话(Memory / Sessions)
│ ├── state.db # 运行时状态(Traces / Observe)
│ ├── skills/ # Tier C 技能包
│ ├── knowledge/ # 知识库文件
│ ├── workspace/ # 工作区文件
│ ├── .scratch/ # 临时计算域
│ └── .plans/ # Plan artifact
├── db/
│ ├── wesclaw.db # 应用数据(tc_* 表)
│ └── wescode_auth.db # 登录 session(跨 Cell 共享)
├── crashes/ # 崩溃日志
└── logs/ # Go 后端日志
平台路径
| 系统 | 数据目录 |
|---|---|
| macOS | ~/Library/Application Support/wesclaw/ |
| Linux | ~/.local/share/wesclaw/ |
| 环境变量 | WESCLAW_DATA_DIR 覆盖 |
三链 SQLite 迁移共存
wesclaw.db 上同时运行三条独立迁移链:
| 链 | 调用点 | 策略 | 管理的表 | 版本跟踪 |
|---|---|---|---|---|
| Chain 1 | store.RunMigrations | PRAGMA user_version + MigrationStep | tc_conversations 等 8 表 | user_version |
| Chain 2 | group.Migrate() | IF NOT EXISTS + legacy 检测 | tc_groups 等 4 表 | 无显式版本 |
| Chain 3 | auth.Migrate() | IF NOT EXISTS + DEV-1 重建 | tc_session | 无显式版本 |
无冲突的理由:三链管理的表集合完全不相交。
降级策略
迁移失败时:关闭 DB → 归档旧文件为 .migration-failed → 清除 WAL/SHM → 重新打开全新 DB → 第二次失败才 fatal。
wesgine 直连审计
Wesclaw 直连 14 个 wesgine 子包,2026-09 审计确认全部合理:
| 包 | 文件数 | 理由 |
|---|---|---|
message | 10 | Shared Kernel 消息 DTO |
config | 10 | Provider/CellSpec 配置类型 |
engine | 5 | 原始 Event/Plan 类型 |
adapter/mcp | 5 | Boot/CellSpec 装配配置 |
tool | — | 引擎 SPI,wesapp 无 tool 包 |
agent | — | AgentConfig 类型 |
skill | — | Skill manifest 类型 |
| 其他 | — | wesapp 已删对应包 |
禁止直连的仍然是 wesgine/internal/...。
SDK 层关系
wesgine 引擎内核
wesui 前端渲染(零 fetch / 零 store / 零路由)
wesapp 引擎消费层 Go SDK
weisyn/sdk 平台客户端(auth / wes / wesclient / jwtauth)
▲
产品:wesclaw | wescode | wescraft | teleclaw
产品之间互不 import
依赖规则
| 允许 | 禁止 |
|---|---|
import wesgine | import wesclaw(从其他产品) |
import wesapp | import wesgine/internal |
import weisyn/sdk | import weisyn/pkg(不存在) |
| 产品直连 wesgine 公共包 | 产品 import 其他产品 |
前端层关系
wesui(组件库) → 通过 Vite alias + tsconfig paths 源码共享
├── wesclaw/web (消费方)
├── wescode/web (消费方)
└── wescraft/web (消费方)
wesui 是纯 UI 渲染层:零 fetch、零 store、零路由。
SSE 流稳定性
Run 生命周期与 SSE 连接完全解耦:
| 特性 | 说明 |
|---|---|
| Run 不随 SSE 断开而死 | 引擎 Run 继续执行 |
| hasActiveRun 门控 | 同 session 已有活跃 Run → 409 |
| run_recovered 事件 | SSE 断开后 Run 完成时补拉消息 |
| timeout-seconds | 86400(24h),与 INV-TERM-01 对齐 |
取消 Run 的唯一途径:用户 interrupt、CycleDetector HITL 超时、BudgetCheckFn、Cell Stop。