fix(identity): 接通身份信号提取与持久化 — 对话中起名跨会话记忆
Some checks failed
CI / Rust Check (push) Has been cancelled
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

根因: 记忆提取管道(COMBINED_EXTRACTION_PROMPT)提取5种画像信号
但无身份信号(agent_name/user_name),不存在从对话到AgentConfig.name
或IdentityFiles的写回路径。

修复内容:
- ProfileSignals 增加 agent_name/user_name 字段
- COMBINED_EXTRACTION_PROMPT 增加身份提取指令
- parse_profile_signals 解析新字段 + 回退推断
- GrowthIntegration 存储身份信号到 VikingStorage
- post_conversation_hook 写回 soul.md + emit Tauri 事件
- streamStore 规则化检测 agent 名字并更新 AgentConfig.name
- cold-start-mapper 新增 detectAgentNameSuggestion

链路: 对话→提取→VikingStorage→hook写回soul.md→事件→前端刷新
This commit is contained in:
iven
2026-04-23 09:20:35 +08:00
parent 17a7a36608
commit 08812e541c
7 changed files with 431 additions and 22 deletions

View File

@@ -440,6 +440,39 @@ impl GrowthIntegration {
}
}
// Store identity signals as special memories for cross-session persistence
if combined.profile_signals.has_identity_signal() {
let agent_id_str = agent_id.to_string();
if let Some(ref agent_name) = combined.profile_signals.agent_name {
let entry = zclaw_growth::types::MemoryEntry::new(
&agent_id_str,
zclaw_growth::types::MemoryType::Preference,
"identity",
format!("助手的名字是{}", agent_name),
).with_importance(8)
.with_keywords(vec!["名字".to_string(), "称呼".to_string(), "identity".to_string(), agent_name.clone()]);
if let Err(e) = self.extractor.store_memory_entry(&entry).await {
tracing::warn!("[GrowthIntegration] Failed to store agent_name signal: {}", e);
} else {
tracing::info!("[GrowthIntegration] Stored agent_name '{}' for {}", agent_name, agent_id_str);
}
}
if let Some(ref user_name) = combined.profile_signals.user_name {
let entry = zclaw_growth::types::MemoryEntry::new(
&agent_id_str,
zclaw_growth::types::MemoryType::Preference,
"identity",
format!("用户的名字是{}", user_name),
).with_importance(8)
.with_keywords(vec!["名字".to_string(), "用户名".to_string(), "identity".to_string(), user_name.clone()]);
if let Err(e) = self.extractor.store_memory_entry(&entry).await {
tracing::warn!("[GrowthIntegration] Failed to store user_name signal: {}", e);
} else {
tracing::info!("[GrowthIntegration] Stored user_name '{}' for {}", user_name, agent_id_str);
}
}
}
// Convert extracted memories to structured facts
let facts: Vec<Fact> = combined
.memories