Files
zclaw_openfang/wiki/routing.md
iven 36a1c87d87
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
docs(wiki): 重构为模块化知识库 — 按模块组织而非按文档类型
问题: 旧 wiki 按文档类型组织(architecture/data-flows/file-map),
修复 Butler Router 需要读 4 个文件才能拼凑全貌。
且 SaaS Relay 主路径 vs 本地降级的优先级描述不准确。

重构为模块化结构,每个模块页自包含:
- 设计思想: 为什么这样设计
- 代码逻辑: 数据流 + 关键代码
- 关联模块: 依赖关系

新增模块页:
- routing.md: 客户端路由 (明确 SaaS Relay 是主路径,不是本地模式)
- chat.md: 聊天系统 (3种实现 + Token Pool 中转机制)
- butler.md: 管家模式 (路由/冷启动/痛点/双模式UI)
- memory.md: 记忆管道 (提取→FTS5→检索→注入)
- saas.md: SaaS平台 (认证/Token池/计费/Admin)
- middleware.md: 中间件链 (14层 + 优先级)
- hands-skills.md: Hands(9) + Skills(75)
- pipeline.md: Pipeline DSL

删除旧文件: architecture.md, data-flows.md, module-status.md, file-map.md
(内容已分布到对应模块页中)

添加 .gitignore 排除 Obsidian 工作区状态文件
2026-04-11 00:36:26 +08:00

3.5 KiB
Raw Blame History

title, updated, status, tags
title updated status tags
客户端路由 2026-04-11 active
module
routing
connection

客户端路由

index 导航。关联模块: chat saas

设计思想

核心决策: Tauri 桌面端通过 SaaS Token Pool 中转访问 LLM不直连。

为什么?

  1. 集中密钥管理 — 用户不需要自己的 API KeySaaS 维护共享 Key 池
  2. 用量追踪 + 计费 — 每次调用经过 SaaSrecord_usage worker 记录 token 消耗
  3. 模型白名单 — Admin 配置哪些模型可用,listModels() 返回白名单
  4. 降级保障 — SaaS 挂了自动切本地 Kernel桌面端不变砖

代码逻辑

4 分支决策树

入口: connectionStore.ts:349connect(url?, token?)

connect()
  │
  ├── [1] Admin 强制路由: localStorage llm_routing
  │     ├── "relay" → 强制 SaaS Relay 模式
  │     └── "local" → 强制本地 Kernel (adminForceLocal=true)
  │
  ├── [2] SaaS Relay 模式: localStorage('zclaw-connection-mode') === 'saas'
  │     ├── Tauri: KernelClient + baseUrl = saasUrl/api/v1/relay
  │     │         apiKey = SaaS JWT (不是 LLM Key!)
  │     ├── Browser: SaaSRelayGatewayClient (SSE)
  │     └── SaaS 不可达 → 降级到本地 Kernel
  │
  ├── [3] 本地 Kernel: isTauriRuntime() === true
  │     KernelClient + 用户自定义模型配置
  │     用户需要自己的 API Key
  │
  └── [4] External Gateway (fallback)
        GatewayClient via WebSocket/REST

SaaS Relay 主路径 (Tauri 桌面端)

关键代码: connectionStore.ts:482-535

kernelClient.setConfig({
  provider: 'custom',
  model: modelToUse,                          // 从 SaaS listModels() 获取
  apiKey: session.token,                      // SaaS JWT不是 LLM Key
  baseUrl: `${session.saasUrl}/api/v1/relay`, // 指向 SaaS relay
  apiProtocol: 'openai',
});

注意: Kernel 仍然执行 LLM 调用逻辑,但请求发往 SaaS relay 而非直连 LLM。 SaaS relay 接到请求后,从 Token Pool 中取一个可用 Key转发给真实 LLM。

SaaS 降级流程

关键代码: connectionStore.ts:446-468

listModels() 失败
  → 401 → session 过期 → logout → 要求重新登录
  → 其他错误 → saasDegraded = true
    → saasStore.saasReachable = false
    → 降级到本地 Kernel 模式

客户端类型

客户端 传输 文件 用途
GatewayClient WebSocket + REST lib/gateway-client.ts 外部 Gateway 进程
KernelClient Tauri invoke() lib/kernel-chat.ts 内置 Kernel (桌面端)
SaaSRelayGatewayClient HTTP SSE lib/saas-relay-client.ts 浏览器端 SaaS 中继

getClient() 定义: connectionStore.ts:844 所有 Store 通过 initializeStores() (store/index.ts:94) 获取共享 client。

关联模块

  • chat — 路由决定使用哪种 ChatStream
  • saas — Token Pool、认证、模型管理
  • middleware — 请求经过中间件链处理
  • butler — 管家模式通过 ButlerRouter 中间件介入

关键文件

文件 职责
desktop/src/store/connectionStore.ts 路由决策核心 (844行)
desktop/src/lib/gateway-client.ts WebSocket 客户端
desktop/src/lib/kernel-chat.ts Tauri 内核聊天
desktop/src/lib/saas-relay-client.ts SaaS SSE 中继
desktop/src/lib/saas-client.ts SaaS API 客户端
desktop/src/store/index.ts Store 协调器 + client 注入