架构概览

本文描述 Wesclaw 的整体技术架构,帮助开发者和高级用户理解系统的运作方式。


双进程架构

Wesclaw 桌面版采用双进程架构:

┌──────────────────────────────┐
│    Electron 主进程(Node.js)  │
│  ┌────────────────────────┐  │
│  │   Renderer (React)     │  │
│  │   window.wesclaw.rpc() │  │
│  └─────────┬──────────────┘  │
└────────────┼─────────────────┘
             │ stdio JSON-RPC
┌────────────▼─────────────────┐
│    Go 后端进程 (wesclaw rpc)  │
│  ┌────────────────────────┐  │
│  │   wesgine Hypervisor   │  │
│  │   └── Cell "main"      │  │
│  │       └── Runtime      │  │
│  └────────────────────────┘  │
└──────────────────────────────┘

两个入口命令

命令用途说明
wesclaw rpcElectron RPC 模式stdio JSON-RPC,桌面唯一热路径
wesclaw serve本机 HTTP 模式N=1 单 Cell HTTP,不是 SaaS

通信方式

桌面版:stdio JSON-RPC

Renderer → Electron Main → Go 后端
         window.wesclaw.rpc(method, params)

SaaS 版:HTTP + SSE + JWT

浏览器 → nginx → 平台 :8080 / 引擎 :8081

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",
})

关键约束


前端不感知 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 1store.RunMigrationsPRAGMA user_version + MigrationSteptc_conversations 等 8 表user_version
Chain 2group.Migrate()IF NOT EXISTS + legacy 检测tc_groups 等 4 表无显式版本
Chain 3auth.Migrate()IF NOT EXISTS + DEV-1 重建tc_session无显式版本

无冲突的理由:三链管理的表集合完全不相交。

降级策略

迁移失败时:关闭 DB → 归档旧文件为 .migration-failed → 清除 WAL/SHM → 重新打开全新 DB → 第二次失败才 fatal。


wesgine 直连审计

Wesclaw 直连 14 个 wesgine 子包,2026-09 审计确认全部合理:

包文件数理由
message10Shared Kernel 消息 DTO
config10Provider/CellSpec 配置类型
engine5原始 Event/Plan 类型
adapter/mcp5Boot/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 wesgineimport wesclaw(从其他产品)
import wesappimport wesgine/internal
import weisyn/sdkimport 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-seconds86400(24h),与 INV-TERM-01 对齐

取消 Run 的唯一途径:用户 interrupt、CycleDetector HITL 超时、BudgetCheckFn、Cell Stop。