fix(test): pain_severity 测试断言修正 + 调试文档代码验证更新
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

- test_severity_ordering: 修正错误断言 — 2条挫折信号应触发High而非Medium
- DEBUGGING_PROMPT.md: 全量代码验证更新
  - 数字修正: 97组件/81lib/189命令/137路由/8 Worker
  - V13-GAP 状态更新: 5/6 已修复, 1 标注 DEPRECATED
  - 中间件优先级修正: ButlerRouter@80, DataMasking@90
  - SaaS Relay: resolve_model() 三级解析 (非精确匹配)
This commit is contained in:
iven
2026-04-14 22:03:51 +08:00
parent 3c42e0d692
commit d0aabf5f2e
2 changed files with 420 additions and 1 deletions

View File

@@ -610,13 +610,22 @@ mod tests {
#[test] #[test]
fn test_severity_ordering() { fn test_severity_ordering() {
// Single frustration signal → Medium
let messages = vec![
Message::user("这又来了"),
];
let result = analyze_for_pain_signals(&messages);
assert!(result.is_some());
assert_eq!(result.unwrap().severity, PainSeverity::Medium);
// Two frustration signals → High (len >= 2 triggers High)
let messages = vec![ let messages = vec![
Message::user("这又来了"), Message::user("这又来了"),
Message::user("还是不行"), Message::user("还是不行"),
]; ];
let result = analyze_for_pain_signals(&messages); let result = analyze_for_pain_signals(&messages);
assert!(result.is_some()); assert!(result.is_some());
assert_eq!(result.unwrap().severity, PainSeverity::Medium); assert_eq!(result.unwrap().severity, PainSeverity::High);
} }
#[test] #[test]

410
docs/DEBUGGING_PROMPT.md Normal file
View File

@@ -0,0 +1,410 @@
# ZCLAW 多端全链路调试提示词
> 基于 wiki 知识库 `g:\ZClaw_openfang\wiki\` 系统分析制定
> 用于新会话中系统性排查 ZCLAW 多端联调问题
---
## 系统架构概要
ZCLAW 是多层架构的 AI Agent 桌面客户端:
```
┌─────────────────────────────────────────────────────────────┐
│ 前端层: React 19 + TypeScript + Zustand │
│ ├── 97 个 React 组件 (desktop/src/components/) │
│ ├── 17 个 Zustand Store + 4 个 chat 子 store │
│ └── 81 个 lib 文件 (desktop/src/lib/) │
├─────────────────────────────────────────────────────────────┤
│ 桌面层: Tauri 2.x │
│ ├── 189 个 Tauri 命令定义 / 182 个注册 │
│ └── 3 种 ChatStream: KernelClient / SaaSRelay / Gateway │
├─────────────────────────────────────────────────────────────┤
│ Rust 后端: 10 crates + src-tauri │
│ ├── ~95K 行 Rust 代码 (335 个 .rs 文件) │
│ └── 14 层中间件链 (middleware/butler_router.rs 等) │
├─────────────────────────────────────────────────────────────┤
│ SaaS 平台: PostgreSQL + axum │
│ ├── 137 个 API 路由 (18 处 .merge() 汇聚) │
│ └── 8 个后台 Worker (Token Pool / 计费 / 用量等) │
└─────────────────────────────────────────────────────────────┘
```
---
## 核心数据流
### 客户端路由决策树
入口: `desktop/src/store/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 + 用户自定义模型配置
└── [4] External Gateway (fallback)
GatewayClient via WebSocket/REST
```
### 完整消息流 (Tauri SaaS Relay 主路径)
```
UI: ChatArea.tsx
streamStore.sendMessage(content)
kernelClient.chatStream()
├── Tauri invoke('kernel_chat', ...)
│ │
│ ▼
│ Kernel::boot()
│ │
│ ▼
│ loop_runner → 14 层中间件链
│ │
│ ├── @80 ButlerRouter (TF-IDF 75 技能路由) ✅
│ ├── @90 DataMasking (敏感数据脱敏)
│ ├── @100 Compaction (对话压缩, 条件注册: threshold>0)
│ ├── @150 Memory (记忆提取)
│ ├── @180 Title (会话标题)
│ ├── @200 SkillIndex (技能索引注入, 条件注册: entries非空)
│ ├── @300 DanglingTool
│ ├── @350 ToolError
│ ├── @360 ToolOutputGuard
│ ├── @400 Guardrail (安全规则)
│ ├── @500 LoopGuard (防无限循环)
│ ├── @550 SubagentLimit
│ ├── @650 TrajectoryRecorder (✅ V13-GAP-01 已修复)
│ └── @700 TokenCalibration
│ │
│ ▼
│ LLM Driver (OpenAI compatible)
│ │
│ ▼
│ POST {baseUrl}/chat/completions
│ Bearer {SaaS JWT}
│ model: {modelToUse}
│ │
│ ▼
│ SaaS Relay Handler
│ cache.resolve_model(model_name) ── 三级解析:
│ 1. 精确 model_id 匹配
│ 2. alias 字段匹配
│ 3. 前缀匹配 (e.g. "glm-4-flash" → "glm-4-flash-250414")
│ │
│ ▼
│ Token Pool 轮换
│ (priority → last_used → RPM/TPM 滑动窗口)
│ │
│ ▼
│ 真实 LLM API
│ │
│ ▼
│ SSE 流式响应
│ │
▼ ▼
Tauri Event emit('chat-response-delta', ...)
├── onDelta(text) → streamStore 追加
├── onThinkingDelta → 显示思考过程
├── onTool(tool) → toolStore 更新
├── onHand(hand) → handStore 更新
└── onComplete() → conversationStore 持久化
```
---
## V13 已知断链清单2026-04-14 验证更新)
> 验证时间: 2026-04-14 | 6 项中 5 项已修复1 项已标注待清理
| ID | 优先级 | 状态 | 问题 | 验证位置 |
|----|--------|------|------|----------|
| **V13-GAP-01** | P1 | ✅ 已修复 | TrajectoryRecorderMiddleware @650 已注册到 `create_middleware_chain()` | `crates/zclaw-kernel/src/kernel/mod.rs:356-361` |
| **V13-GAP-02** | P1 | ✅ 已修复 | industryStore 已被 `ButlerPanel/index.tsx` 导入消费 | `desktop/src/components/ButlerPanel/index.tsx:4` |
| **V13-GAP-03** | P1 | ✅ 已修复 | Knowledge Search API 已接入: saas-knowledge.ts → saas-client.ts → VikingPanel.tsx | `desktop/src/components/VikingPanel.tsx:105` |
| **V13-GAP-04** | P2 | ⚠️ 标注 | Webhook 迁移文件已标 DEPRECATEDRust 零消费,待物理删除 | `crates/zclaw-saas/migrations/20260403000002_webhooks.sql` |
| **V13-GAP-05** | P2 | ✅ 已修复 | Structured Data Source 有完整 Admin-v2 消费链: service → Knowledge.tsx → StructuredSourcesPanel | `admin-v2/src/services/knowledge.ts:67-207` |
| **V13-GAP-06** | P2 | ✅ 已修复 | PersistentMemoryStore struct 已移除,仅保留 API 响应类型 | `desktop/src-tauri/src/memory/persistent.rs` |
---
## 调试入口和关键文件
### 前端层
| 文件 | 职责 | 调试要点 |
|------|------|----------|
| `desktop/src/store/connectionStore.ts` | 路由决策核心 | `connect()` 方法, `getClient()` |
| `desktop/src/store/chat/streamStore.ts` | 流式消息编排 | `sendMessage()`, `chatStream()` 回调 |
| `desktop/src/store/chat/conversationStore.ts` | 会话管理 | `currentModel` 持久化 |
| `desktop/src/lib/kernel-chat.ts` | Kernel ChatStream (Tauri) | Tauri invoke 调用 |
| `desktop/src/lib/saas-relay-client.ts` | SaaS Relay ChatStream | SSE 连接 |
| `desktop/src/lib/gateway-client.ts` | Gateway ChatStream (WS) | WebSocket 连接 |
| `desktop/src/components/ButlerPanel.tsx` | 管家面板 | industryStore 已导入 ✅ (V13-GAP-02 已修复) |
### Tauri 命令层
| 文件 | 命令数 | 调试要点 |
|------|--------|----------|
| `desktop/src-tauri/src/lib.rs` | 189 定义 / 182 注册 | `kernel_chat`, `kernel_init` 等 |
| `desktop/src-tauri/src/kernel_commands/` | Hand/MCP/Skill | 8+4+? 命令 |
| `desktop/src-tauri/src/memory_commands.rs` | 13 个 | memory CRUD |
### Rust 中间件层
| 文件 | 中间件数 | 调试要点 |
|------|----------|----------|
| `crates/zclaw-runtime/src/middleware.rs` | AgentMiddleware trait | 4 个 hook 点 |
| `crates/zclaw-runtime/src/middleware/` | 14 个中间件实现 | TrajectoryRecorder @650 ✅ |
| `crates/zclaw-kernel/src/kernel/mod.rs:206-371` | `create_middleware_chain()` | V13-GAP-01 已修复 ✅ |
### SaaS 后端层
| 文件 | 路由数 | 调试要点 |
|------|--------|----------|
| `crates/zclaw-saas/src/main.rs` | 137 个 .route() | 18 个 .merge() 注册 |
| `crates/zclaw-saas/src/relay/handlers.rs` | 聊天中转 | `cache.resolve_model()` 三级解析 |
| `crates/zclaw-saas/src/workers/` | 8 个 Worker | Token Pool / 用量记录 |
---
## 系统性调试步骤
### 第一阶段:问题定位
**步骤 1确定症状层级**
问题出现在哪一层?
- [ ] **前端 UI 层** — 组件渲染、用户交互异常
- [ ] **前端 Store 层** — 状态管理、数据流异常
- [ ] **Tauri 命令层** — invoke 调用失败或返回错误
- [ ] **Rust 中间件层** — 中间件链执行异常
- [ ] **LLM Driver 层** — 模型调用失败
- [ ] **SaaS Relay 层** — Token Pool / 模型匹配问题
- [ ] **SaaS 后端层** — API 路由 / 数据库问题
**步骤 2缩小范围**
根据症状判断问题来源:
| 症状 | 怀疑层级 | 优先检查 |
|------|----------|----------|
| 模型 400 错误 | SaaS Relay | `cache.resolve_model()` 三级解析是否匹配到 model_id |
| 中间件未生效 | Rust 中间件层 | TrajectoryRecorder @650 已注册 ✅ |
| 行业配置不显示 | 前端 Store 层 | industryStore 已被 ButlerPanel 导入 ✅ |
| 流式响应中断 | Tauri 命令层 | kernel-chat.ts:76 超时守护 |
| Token Pool 耗尽 | SaaS 后端 | Workers 是否正常调度 |
| JWT 失效 | SaaS 认证 | password_version 是否匹配 |
| 记忆提取失败 | Rust Memory 层 | `MemoryExtractor` 是否正常工作 |
| Skill 未匹配 | 语义路由 | `SemanticSkillRouter` TF-IDF 计算 |
### 第二阶段:分层验证
**步骤 3前端层验证**
```bash
# TypeScript 类型检查
cd desktop && pnpm tsc --noEmit
# 运行单元测试
cd desktop && pnpm vitest run
# 检查 Store 状态 (在 DevTools Console)
# streamStore.getState()
# conversationStore.getState()
# connectionStore.getState()
# 检查组件是否正确导入
grep -r "industryStore" desktop/src/components/
grep -r "saas-knowledge" desktop/src/
```
**步骤 4Tauri 命令层验证**
```bash
# 列出所有注册的 Tauri 命令
grep "#[tauri::command]" desktop/src-tauri/src/ -r
# 验证 kernel 命令
grep "kernel_chat\|kernel_init" desktop/src-tauri/src/ -r
# 验证中间件注册
grep -A3 "TrajectoryRecorder" crates/zclaw-kernel/src/kernel/mod.rs
```
**步骤 5Rust 中间件链验证**
```bash
# 验证 14 层中间件注册顺序
grep "chain.register" crates/zclaw-kernel/src/kernel/mod.rs
# 验证 ButlerRouter 语义路由
grep -r "SemanticSkillRouter\|TF-IDF" crates/zclaw-runtime/src/middleware/
# 验证 Memory 中间件
grep -r "Memory" crates/zclaw-runtime/src/middleware/
```
**步骤 6SaaS Relay 验证**
```bash
# 验证路由注册
grep "\.route(" crates/zclaw-saas/src/main.rs
# 验证模型缓存匹配
grep "cache.get_model\|model_id" crates/zclaw-saas/src/relay/ -r
# 验证 Token Pool 轮换逻辑
grep -r "priority\|last_used\|cooldown" crates/zclaw-saas/src/relay/
```
### 第三阶段:完整链路检查
**步骤 7按检查点逐步验证**
```
[检查点 1] streamStore.sendMessage()
└── 验证: sessionKey, agentId, chatMode 是否正确传递
└── 代码: desktop/src/store/chat/streamStore.ts
[检查点 2] KernelClient.chatStream()
└── 验证: Tauri invoke 调用是否发出, 参数是否正确
└── 代码: desktop/src/lib/kernel-chat.ts
[检查点 3] Kernel::boot()
└── 验证: config.model, config.baseUrl, config.apiKey
└── 代码: desktop/src-tauri/src/kernel/mod.rs
[检查点 4] Middleware Chain (14 层)
└── 验证: 每层 middleware.before_completion() 是否按优先级执行
└── 重点: TrajectoryRecorder @650 已注册 ✅ (V13-GAP-01 已修复)
└── 代码: crates/zclaw-kernel/src/kernel/mod.rs:create_middleware_chain()
[检查点 5] LLM Driver
└── 验证: 请求是否发往正确 baseUrl, Authorization header 是否正确
└── 代码: crates/zclaw-runtime/src/driver/
[检查点 6] SaaS Relay Handler
└── 验证: model_id 是否被 resolve_model() 三级解析命中, Token Pool 是否可用
└── 代码: crates/zclaw-saas/src/relay/handlers.rs
[检查点 7] Token Pool 轮换
└── 验证: RPM/TPM 是否在阈值内, cooldown 状态
└── 代码: crates/zclaw-saas/src/relay/cache.rs
[检查点 8] SSE 流式响应
└── 验证: Tauri Event 是否正确 emit, onDelta 回调是否触发
└── 代码: desktop/src/lib/kernel-chat.ts
[检查点 9] Store 状态更新
└── 验证: conversationStore 持久化, messageStore 更新
└── 代码: desktop/src/store/chat/
```
---
## 根因分类与修复策略
### 协议问题
| 问题 | 原因 | 修复策略 |
|------|------|----------|
| 模型 400 | model_id 不在 SaaS 模型缓存中(三级解析均未命中) | 检查模型是否已在 Admin 启用,或 model_id 拼写 |
| JWT 失效 | password_version 不匹配 | 重新登录,或检查 JWT 刷新逻辑 |
| 流式中断 | 5 分钟超时守护触发 | 检查 kernel-chat.ts:76 超时配置 |
### 状态问题
| 问题 | 原因 | 修复策略 |
|------|------|----------|
| Store 不同步 | 多个 Store 实例 | 检查 store/index.ts 的 initializeStores() |
| 模型切换失败 | currentModel 未持久化 | 检查 conversationStore 的 persist 配置 |
| 行业配置不显示 | industryStore 导入 ✅ 已修复 | 如仍有问题检查 API 连接和 Store 初始化 |
### 中间件问题
| 问题 | 原因 | 修复策略 |
|------|------|----------|
| TrajectoryRecorder 未记录轨迹 | 数据库连接或 Store 初始化问题 | 检查 TrajectoryStore::new(pool) 连接 (V13-GAP-01 已修复) |
| Memory 提取失败 | MiddlewareContext 未正确传递 | 检查 middleware/memory.rs 的 before_completion |
| Skill 未匹配 | SemanticSkillRouter TF-IDF 计算异常 | 检查 crates/zclaw-skills/src/semantic_router.rs |
### 配置问题
| 问题 | 原因 | 修复策略 |
|------|------|----------|
| baseUrl 错误 | SaaS URL 未配置或硬编码错误 | 检查 config.toml 和环境变量 |
| API Key 错误 | SaaS JWT vs LLM Key 混淆 | 确认 kernelClient 使用 SaaS JWT |
---
## 执行命令参考
```bash
# 1. 前端验证
cd desktop && pnpm tsc --noEmit
cd desktop && pnpm vitest run
# 2. Rust 验证
cargo check --workspace --exclude zclaw-saas
cargo test --workspace --exclude zclaw-saas
# 3. SaaS 集成测试 (需要 PostgreSQL)
export TEST_DATABASE_URL="postgresql://postgres:123123@localhost:5432/zclaw"
cargo test -p zclaw-saas -- --test-threads=1
# 4. 检查中间件注册
grep -n "TrajectoryRecorder" crates/zclaw-kernel/src/kernel/mod.rs
grep -n "chain.register" crates/zclaw-kernel/src/kernel/mod.rs
# 5. 检查 V13 断链修复
grep -n "V13-GAP" crates/zclaw-kernel/src/kernel/mod.rs
# 6. 检查 industryStore 导入
grep -rn "industryStore" desktop/src/components/
```
---
## 调试记录模板
发现问题时,按以下格式记录:
```markdown
## [日期] [问题描述]
**症状**: [用户可见的问题表现]
**怀疑层级**: [前端/Tauri/Rust中间件/LLM/SaaS Relay/SaaS后端]
**怀疑位置**: [具体文件和行号]
**验证步骤**:
1. [x] [检查项]
2. [x] [检查项]
3. [ ] [检查项]
**根因**: [确定后填写]
**修复方案**: [确定后填写]
**影响范围**: [涉及的模块]
```
---
> 提示词版本: 2026-04-14-v2 (代码验证更新)
> 基于: wiki/index.md, wiki/routing.md, wiki/chat.md, wiki/middleware.md,
> wiki/memory.md, wiki/hands-skills.md, wiki/saas.md, wiki/known-issues.md