fix(growth,kernel,runtime,desktop): 50 轮功能链路审计 7 项断链修复
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

P0 修复:
- B-MEM-2: 跨会话记忆丢失 — 添加 IdentityRecall 查询意图检测,
  身份类查询绕过 FTS5/LIKE 文本搜索,直接按 scope 检索全部偏好+知识记忆;
  缓存 GrowthIntegration 到 Kernel 避免每次请求重建空 scorer
- B-HAND-1: Hands 未触发 — 创建 HandTool wrapper 实现 Tool trait,
  在 create_tool_registry() 中注册所有已启用 Hands 为 LLM 可调用工具

P1 修复:
- B-SCHED-4: 一次性定时未拦截 — 添加 RE_ONE_SHOT_TODAY 正则匹配
  "下午3点半提醒我..."类无日期前缀的同日触发模式
- B-CHAT-2: 工具调用循环 — ToolErrorMiddleware 添加连续失败计数器,
  3 次连续失败后自动 AbortLoop 防止无限重试
- B-CHAT-5: Stream 竞态 — cancelStream 后添加 500ms cancelCooldown,
  防止后端 active-stream 检查竞态
This commit is contained in:
iven
2026-04-20 09:43:38 +08:00
parent 24b866fc28
commit f2917366a8
10 changed files with 746 additions and 49 deletions

View File

@@ -36,6 +36,9 @@ pub enum QueryIntent {
Code,
/// Configuration query
Configuration,
/// Identity/personal recall — user asks about themselves or past conversations
/// Triggers broad retrieval of all preference + knowledge memories
IdentityRecall,
}
/// Query analyzer
@@ -50,6 +53,8 @@ pub struct QueryAnalyzer {
code_indicators: HashSet<String>,
/// Stop words to filter out
stop_words: HashSet<String>,
/// Patterns indicating identity/personal recall queries
identity_patterns: Vec<String>,
}
impl QueryAnalyzer {
@@ -99,13 +104,38 @@ impl QueryAnalyzer {
.iter()
.map(|s| s.to_string())
.collect(),
identity_patterns: [
// Chinese identity recall patterns
"我是谁", "我叫什么", "我之前", "我告诉过你", "我之前告诉",
"还记得我", "你还记得", "我的名字", "我的身份", "我的信息",
"我的工作", "我在哪", "我的偏好", "我喜欢什么",
"关于我", "了解我", "记得我", "我之前说过",
// English identity recall patterns
"who am i", "what is my name", "what do you know about me",
"what did i tell", "do you remember me", "what do you remember",
"my preferences", "about me", "what have i shared",
]
.iter()
.map(|s| s.to_string())
.collect(),
}
}
/// Analyze a query string
pub fn analyze(&self, query: &str) -> AnalyzedQuery {
let keywords = self.extract_keywords(query);
let intent = self.classify_intent(&keywords);
// Check for identity recall patterns first (highest priority)
let query_lower = query.to_lowercase();
let is_identity = self.identity_patterns.iter()
.any(|pattern| query_lower.contains(&pattern.to_lowercase()));
let intent = if is_identity {
QueryIntent::IdentityRecall
} else {
self.classify_intent(&keywords)
};
let target_types = self.infer_memory_types(intent, &keywords);
let expansions = self.expand_query(&keywords);
@@ -189,6 +219,12 @@ impl QueryAnalyzer {
types.push(MemoryType::Preference);
types.push(MemoryType::Knowledge);
}
QueryIntent::IdentityRecall => {
// Identity recall needs all memory types
types.push(MemoryType::Preference);
types.push(MemoryType::Knowledge);
types.push(MemoryType::Experience);
}
}
types