Split monolithic kernel_commands.rs (2185 lines) and pipeline_commands.rs (1391 lines) into focused sub-modules under kernel_commands/ and pipeline_commands/ directories. Add gateway module (commands, config, io, runtime), health_check, and 15 new TypeScript client libraries for SaaS relay, auth, admin, telemetry, and kernel sub-systems (a2a, agent, chat, hands, skills, triggers). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
16 KiB
ZCLAW Admin V2 与 Desktop 系统定位设计
日期: 2026-03-30 状态: Draft 范围: Admin V2 定位 + Desktop 集成 + Token Pool + Agent 模板
1. 系统定位
1.1 Admin V2 — 资源管理与配置中心
目标用户: 系统管理员、运营人员
核心职责:
- 账号管理 — 用户 CRUD、角色权限、LLM 路由模式配置
- Token 池管理 — 多提供商多密钥的统一池化管理,解决 Coding Plan 套餐的时段限额和资源浪费问题
- 行业 Agent 模板 — 预调教好的行业 Agent 人设(含 soul.md、system_prompt、工具集),供 Desktop 首次使用时获取
- 系统监控 — 用量统计、日志审计、配置管理
1.2 Desktop (Agent 会话端) — 终端用户界面
目标用户: 终端用户(AI Agent 操作者)
核心职责:
- 智能对话 — 流式响应、多模型切换、上下文管理
- Agent 管理 — 创建、配置、切换 Agent(支持从 SaaS 模板初始化)
- 自主能力 — Hands 触发、工作流编排、技能调用
- 智能成长 — Agent 通过对话逐步成长,记忆、反思、身份演化
1.3 数据流
Admin V2 (配置) → SaaS API → PostgreSQL
↓
Desktop (登录) → SaaS API → 拉取 AccountProfile { llm_routing, available_templates }
↓
┌─────────┴──────────┐
│ │
relay 模式 local 模式
│ │
SaaS Relay Tauri Kernel
│ │
Key Pool 旋转 本地 API Key
│ │
LLM Provider LLM Provider
2. 账号级 LLM 路由
2.1 背景
国内 LLM 厂商推出 Coding Plan 套餐,但套餐有时段使用量限额。每个 Desktop 客户端各自配置 API Key 会造成资源浪费。在 Admin 端搭建 Token 池,多账号共享密钥资源,成本更优。
2.2 数据层
accounts 表新增:
ALTER TABLE accounts ADD COLUMN llm_routing TEXT NOT NULL DEFAULT 'local'
CHECK (llm_routing IN ('relay', 'local'));
COMMENT ON COLUMN accounts.llm_routing IS 'LLM路由模式: relay=SaaS中转, local=本地直连';
默认值 local,保持向后兼容。
2.3 API 层
登录响应扩展:
POST /api/v1/auth/login 和 GET /api/v1/auth/me 返回值增加:
{
token: string;
refresh_token: string;
account: {
id: string;
username: string;
role: string;
llm_routing: 'relay' | 'local'; // 新增
// ... 现有字段
}
}
Admin 端账号管理:
PATCH /api/v1/accounts/:id 请求体支持 llm_routing 字段更新,仅 account:admin 权限可修改。
2.4 Desktop 行为
saasStore 登录成功后读取 account.llm_routing,写入 connectionStore:
'relay'→ 使用SaaSClient.chatCompletion()走 SaaS Relay,无需启动本地 Kernel'local'→ 使用KernelClient走本地 Tauri Kernel
路由模式在登录时确定,会话期间不变。切换需要管理员修改 + 用户重新登录。
3. Token Pool / Key Pool 管理
3.1 现状
后端 Key Pool 已完整实现:
select_best_key(): 优先级排序 + RPM/TPM 滑窗检查mark_key_429(): 429 自动冷却 +Retry-After支持record_key_usage(): 分钟粒度用量记录- SSRF 防护、加密存储、降级回退
Admin UI 为只读(仅显示密钥列表),缺少添加/切换/删除操作。
3.2 Admin UI 补全
Providers 页面 Key Pool Modal 升级为完整管理:
| 操作 | 交互 | 说明 |
|---|---|---|
| 添加密钥 | 点击"添加"按钮 → 弹出表单 | 字段: label, key_value, priority, max_rpm(可选), max_tpm(可选) |
| 启用/禁用 | 切换 Switch 组件 | 调用 PUT /providers/:id/keys/:keyId/toggle |
| 删除密钥 | 点击删除 → Popconfirm 确认 | 调用 DELETE /providers/:id/keys/:keyId |
| 状态展示 | 表格列 | 每个密钥显示: 状态、priority、RPM/TPM 配额、当前窗口用量、总用量 |
前端使用 providerService.addKey(), providerService.toggleKey(), providerService.deleteKey() — 这些 service 方法已定义但未使用,直接接入即可。
3.3 缺陷修复
| 缺陷 | 修复方案 | 优先级 |
|---|---|---|
key_usage_window 无清理 |
Scheduler 增加定时任务,清理 >24h 的窗口记录 | P1 |
| 同优先级无负载分散 | select_best_key() 加入"最近最少使用"次排序 |
P2 |
quota_reset_interval 未使用 |
移除字段或实现按 interval 重置配额逻辑 | P3 |
4. 行业 Agent 模板系统
4.1 背景
通过预设行业 Agent 模板(如医疗行业),预先调教好完整的 Agent 人设。Desktop 端首次使用时从 SaaS 获取完整模板配置,之后 Agent 由用户对话驱动逐步成长,不再与模板同步。
4.2 数据层 — 扩展 agent_templates
ALTER TABLE agent_templates ADD COLUMN soul_content TEXT;
ALTER TABLE agent_templates ADD COLUMN scenarios TEXT NOT NULL DEFAULT '[]';
ALTER TABLE agent_templates ADD COLUMN welcome_message TEXT;
ALTER TABLE agent_templates ADD COLUMN quick_commands TEXT NOT NULL DEFAULT '[]';
ALTER TABLE agent_templates ADD COLUMN personality TEXT;
ALTER TABLE agent_templates ADD COLUMN communication_style TEXT;
ALTER TABLE agent_templates ADD COLUMN emoji TEXT;
ALTER TABLE agent_templates ADD COLUMN version INTEGER NOT NULL DEFAULT 1;
ALTER TABLE agent_templates ADD COLUMN source_id TEXT UNIQUE;
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
soul_content |
TEXT | SOUL.md 人格配置全文 (Markdown) |
scenarios |
JSON | 场景标签数组,如 ["临床辅助", "文献检索"] |
welcome_message |
TEXT | 首次问候语 |
quick_commands |
JSON | 快捷指令数组 [{label, prompt}] |
personality |
TEXT | 人格预设: professional/friendly/creative/concise |
communication_style |
TEXT | 沟通风格描述文本 |
emoji |
TEXT | Agent 图标 |
version |
INT | 模板版本号,用于新用户获取最新版 |
source_id |
TEXT | 模板唯一标识,用于 Desktop 去重 |
4.3 种子模板示例 — 医疗行业
{
name: "医疗助手",
source_id: "medical-assistant-v1",
category: "healthcare",
description: "医疗行业专业 AI 助手,熟悉临床流程、医学文献和诊疗规范",
emoji: "🏥",
personality: "professional",
system_prompt: "你是一位专业的医疗AI助手,具备以下能力:\n1. 临床辅助诊断建议\n2. 医学文献检索与解读\n3. 用药参考与相互作用检查\n4. 诊疗规范查询\n\n注意: 你的建议仅供参考,不能替代专业医生诊断。",
soul_content: `# SOUL.md
## 人格特质
- 专业严谨,使用准确的医学术语
- 耐心细致,对每个问题都给予充分解答
- 保守审慎,涉及诊断和用药建议时始终提示"仅供参考"
- 持续学习,关注最新医学研究进展
## 沟通风格
- 使用专业但易懂的语言
- 适当使用类比解释复杂医学概念
- 对不确定的内容明确标注置信度
- 主动提醒风险和注意事项
## 边界
- 不做明确诊断,只提供参考意见
- 不推荐处方药的具体用法用量
- 遇到紧急情况建议立即就医
`,
scenarios: ["临床辅助", "文献检索", "诊断建议", "用药参考", "病历整理"],
welcome_message: "你好!我是你的医疗AI助手。我可以帮你检索文献、解读检查报告、提供诊疗参考意见。请注意,我的建议仅供参考,不能替代专业医生的诊断。有什么我可以帮你的吗?",
quick_commands: [
{ label: "文献检索", prompt: "请帮我检索关于 {topic} 的最新医学文献" },
{ label: "用药查询", prompt: "请查询 {drug} 的药理作用、适应症和注意事项" },
{ label: "检查解读", prompt: "请帮我解读以下检查报告: {report}" },
{ label: "诊疗参考", prompt: "关于 {symptom} 的诊疗参考方案" }
],
model: "claude-sonnet-4-6",
tools: ["browser", "researcher", "collector"],
temperature: 0.3,
max_tokens: 4096,
communication_style: "使用专业但易懂的语言,适当使用类比,对不确定内容标注置信度"
}
4.4 API 层
新增端点:
| 端点 | 方法 | 权限 | 说明 |
|---|---|---|---|
/api/v1/agent-templates/available |
GET | 任何已认证 | 返回可浏览模板列表 (id, name, category, emoji, description, source_id) |
/api/v1/agent-templates/:id/full |
GET | 任何已认证 | 返回完整模板 (含 soul_content, welcome_message, quick_commands 等) |
现有端点扩展:
POST /api/v1/agent-templates 和 POST /api/v1/agent-templates/:id (update) 请求体支持所有新增字段。
4.5 Desktop 消费流程
1. 登录成功
→ saasStore 调用 GET /agent-templates/available
→ 缓存模板列表到 saasStore.availableTemplates
2. 用户创建 Agent(首次 / 新建)
→ AgentOnboardingWizard 增加 Step 0: 选择行业模板
→ 展示 Grid 卡片(emoji + 名称 + 分类 + 描述)
→ 两个入口: "空白 Agent" / "从模板创建"
3. 选择模板后
→ 调用 GET /agent-templates/:id/full 获取完整配置
→ 映射到 Desktop Clone + Kernel Agent:
| SaaS 字段 | Desktop 目标 |
|---------------------|-------------------------------------|
| name | Clone.name |
| emoji | Clone.emoji |
| personality | Clone.personality |
| scenarios | Clone.scenarios |
| communication_style | Clone.communicationStyle |
| model | Clone.model |
| system_prompt | → Kernel agent system_prompt |
| soul_content | → identity.updateFile('soul', ...) |
| welcome_message | → 首条消息展示 |
| quick_commands | → 本地缓存,快捷指令面板 |
| temperature | → Kernel agent config |
| max_tokens | → Kernel agent config |
| tools | → Kernel agent tools |
4. 创建完成
→ Agent 在本地成长
→ 不再与 SaaS 模板同步
→ 模板更新仅影响新用户
5. Admin V2 UI 变更汇总
5.1 Accounts 页面
- 编辑 Modal 增加 "LLM 路由模式" 字段
- 下拉选项: "SaaS 中转 (Token 池)" / "本地直连"
- 表格增加路由模式列
5.2 Providers 页面
- Key Pool Modal 从只读升级为完整管理
- 增加 "添加密钥" 按钮 → 表单 (label, key, priority, RPM, TPM)
- 密钥行增加启用/禁用 Switch 和删除按钮
- 增加用量统计展示
5.3 Agent Templates 页面
- 创建/编辑 Modal 增加新字段: emoji, personality, soul_content (大文本编辑器), scenarios (多选标签), welcome_message, quick_commands (动态列表), communication_style
- 列表增加 emoji 列和 category 筛选
- 预览功能: 展示模板效果(模拟 Agent 外观)
6. Desktop 端变更汇总
6.1 saasStore
- 登录响应增加
llm_routing解析 - 新增
fetchAvailableTemplates()方法 - 新增
availableTemplates状态
6.2 connectionStore
connect()根据账号llm_routing选择路径- relay 模式: 使用
SaaSClient.chatCompletion() - local 模式: 保持现有
KernelClient逻辑
6.3 AgentOnboardingWizard
- 新增 Step 0: 行业模板选择
- 模板 Grid 展示 (从 saasStore.availableTemplates 渲染)
- 选择模板后预填后续步骤默认值
6.4 agentStore
- 新增
createFromTemplate(template)方法 - 映射模板字段到 Clone + Kernel Agent
7. 文件变更清单
SaaS 后端 (Rust)
| 文件 | 变更 |
|---|---|
crates/zclaw-saas/migrations/20260331000001_accounts_llm_routing.sql |
新增: accounts 加 llm_routing 字段 |
crates/zclaw-saas/migrations/20260331000002_agent_templates_extensions.sql |
新增: agent_templates 加 soul_content 等 9 个扩展字段 |
crates/zclaw-saas/src/account/types.rs |
UpdateAccountRequest 增加 llm_routing 字段 |
crates/zclaw-saas/src/account/service.rs |
update_account SQL 增加 llm_routing 列 |
crates/zclaw-saas/src/account/handlers.rs |
update_account 支持 llm_routing |
crates/zclaw-saas/src/auth/types.rs |
AccountPublic 增加 llm_routing 字段 |
crates/zclaw-saas/src/auth/handlers.rs |
login/register/me 响应增加 llm_routing (4 个构建点) |
crates/zclaw-saas/src/agent_template/types.rs |
扩展 Create/Update/Info 类型 + 9 个新字段 |
crates/zclaw-saas/src/agent_template/service.rs |
支持 soul_content 等新字段 (考虑重构为 sqlx::FromRow) |
crates/zclaw-saas/src/agent_template/mod.rs |
新增 /available 和 /:id/full 路由 |
crates/zclaw-saas/src/relay/key_pool.rs |
select_best_key 加入 LRU 次排序 |
crates/zclaw-saas/src/scheduler.rs |
新增 key_usage_window 清理任务 |
crates/zclaw-saas/src/db.rs |
扩展种子模板数据 |
Admin V2 (TypeScript)
| 文件 | 变更 |
|---|---|
admin-v2/src/pages/Accounts.tsx |
编辑 Modal 增加 LLM 路由模式字段 |
admin-v2/src/pages/Providers.tsx |
Key Pool Modal 升级为完整管理 |
admin-v2/src/pages/AgentTemplates.tsx |
创建/编辑 Modal 增加扩展字段 |
admin-v2/src/services/providers.ts |
接入已有的 addKey/toggleKey/deleteKey |
admin-v2/src/services/agent-templates.ts |
新增 getFull 方法 |
admin-v2/src/types/index.ts |
扩展 AccountPublic 和 AgentTemplate 类型定义 |
Desktop (TypeScript)
| 文件 | 变更 |
|---|---|
desktop/src/store/saasStore.ts |
增加 llm_routing 解析 + fetchAvailableTemplates + availableTemplates 状态 |
desktop/src/store/connectionStore.ts |
connect() 按 llm_routing 覆盖 localStorage connectionMode |
desktop/src/store/agentStore.ts |
新增 createFromTemplate() + Clone 接口增加 source_template_id |
desktop/src/components/AgentOnboardingWizard.tsx |
新增 Step 0: 模板选择 |
desktop/src/lib/saas-client.ts |
SaaSAccountInfo 增加 llm_routing; 新增 fetchAvailableTemplates + fetchTemplateFull |
8. 关键设计决策说明
8.1 llm_routing 优先级规则
Desktop 端 connectionStore.connect() 的路由决策逻辑:
1. 读取 saasStore.account.llm_routing (Admin 配置)
2. 如果 llm_routing === 'relay' → 强制使用 SaaSClient,忽略 localStorage connectionMode
3. 如果 llm_routing === 'local' → 使用 KernelClient
4. llm_routing 优先级 > localStorage connectionMode
管理员对路由模式有最终控制权。用户无法通过修改 localStorage 绕过 Admin 配置。
8.2 模板获取失败降级
登录时模板获取 (GET /agent-templates/available) 失败时:
- 不阻塞登录流程
- saasStore.availableTemplates 设为空数组
- AgentOnboardingWizard Step 0 显示"模板加载失败"提示 + "空白 Agent"入口
- 模板功能降级为不可用,不影响核心聊天
8.3 模板引用不可用工具
模板指定 tools: ["browser", "researcher"] 但 Desktop 端某工具不可用时:
- 创建 Agent 时静默跳过不可用的工具
- Agent 创建后仍可正常使用,只是缺少该工具能力
- 在 Agent 详情中标注"部分工具不可用"
8.4 source_id 唯一约束
使用部分索引替代列级 UNIQUE 约束,允许 NULL 值:
CREATE UNIQUE INDEX idx_agent_templates_source_id ON agent_templates(source_id) WHERE source_id IS NOT NULL;
9. 不在范围内
以下事项本次设计不涉及:
- AccountTier / 订阅等级体系
- 实时配置推送 (WebSocket)
- 模板市场 / 用户自定义模板上传
- Token 池计费 / 用量配额限制
- Desktop 端路由模式用户自选 (由 Admin 统一管控)