--- title: 客户端路由 updated: 2026-04-11 status: active tags: [module, routing, connection] --- # 客户端路由 > 从 [[index]] 导航。关联模块: [[chat]] [[saas]] ## 设计思想 **核心决策: Tauri 桌面端通过 SaaS Token Pool 中转访问 LLM,不直连。** 为什么? 1. **集中密钥管理** — 用户不需要自己的 API Key,SaaS 维护共享 Key 池 2. **用量追踪 + 计费** — 每次调用经过 SaaS,`record_usage` worker 记录 token 消耗 3. **模型白名单** — Admin 配置哪些模型可用,`listModels()` 返回白名单 4. **降级保障** — SaaS 挂了自动切本地 Kernel,桌面端不变砖 ## 代码逻辑 ### 4 分支决策树 入口: `connectionStore.ts:349` → `connect(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` ```ts 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 注入 |