Files
zclaw_openfang/docs/superpowers/specs/2026-03-30-saas-positioning-design.md
iven f79560a911 refactor(desktop): split kernel_commands/pipeline_commands into modules, add SaaS client libs and gateway modules
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>
2026-03-31 11:12:47 +08:00

409 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ZCLAW Admin V2 与 Desktop 系统定位设计
> 日期: 2026-03-30
> 状态: Draft
> 范围: Admin V2 定位 + Desktop 集成 + Token Pool + Agent 模板
## 1. 系统定位
### 1.1 Admin V2 — 资源管理与配置中心
**目标用户**: 系统管理员、运营人员
**核心职责**:
1. **账号管理** — 用户 CRUD、角色权限、LLM 路由模式配置
2. **Token 池管理** — 多提供商多密钥的统一池化管理,解决 Coding Plan 套餐的时段限额和资源浪费问题
3. **行业 Agent 模板** — 预调教好的行业 Agent 人设(含 soul.md、system_prompt、工具集供 Desktop 首次使用时获取
4. **系统监控** — 用量统计、日志审计、配置管理
### 1.2 Desktop (Agent 会话端) — 终端用户界面
**目标用户**: 终端用户AI Agent 操作者)
**核心职责**:
1. **智能对话** — 流式响应、多模型切换、上下文管理
2. **Agent 管理** — 创建、配置、切换 Agent支持从 SaaS 模板初始化)
3. **自主能力** — Hands 触发、工作流编排、技能调用
4. **智能成长** — 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` 表新增:
```sql
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` 返回值增加:
```typescript
{
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
```sql
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 种子模板示例 — 医疗行业
```typescript
{
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 值:
```sql
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 统一管控)