diff --git a/docs/待决策.md b/docs/待决策.md index 63751f4..8c41310 100644 --- a/docs/待决策.md +++ b/docs/待决策.md @@ -298,7 +298,11 @@ #### DEC-260628-04 消息级溯源 P2 切读 - **决策**:✅ b 一次性切读(保留原表数据不删) - **记录**:读写路径从 `ai_conversations.messages` 切到 `ai_messages` 表,原列保留 -- **状态**:🟢 已决·待推进 +- **核验(2026-06-28)**:✅ 全部已完成—— + - 写路径:`save_conversation` 已全量重写 ai_messages + - 读路径:`ai_conversation_switch`/`ai_conversation_export`/`remote_bridge::route_load_messages` 优先读 ai_messages,表空时 fallback 旧 JSON(老库兼容) + - 最后一处补全:`knowledge_inject::extract_knowledge_from_conversation` 也切到 ai_messages +- **状态**:✅ 已决·已实施 #### DEC-260628-05 SMELL-P1-6 String→newtype - **决策**:✅ b 路线(仅 Rust 内部 newtype) diff --git a/src-tauri/src/commands/ai/knowledge_inject.rs b/src-tauri/src/commands/ai/knowledge_inject.rs index 450edd5..7206a94 100644 --- a/src-tauri/src/commands/ai/knowledge_inject.rs +++ b/src-tauri/src/commands/ai/knowledge_inject.rs @@ -12,7 +12,7 @@ use df_ai::provider::{ChatMessage, CompletionRequest, LlmProvider, MessageRole}; use df_ai::router::{ select_model_id, Modality, TaskRequirements, }; -use df_storage::crud::{AiConversationRepo, KnowledgeRepo}; +use df_storage::crud::{AiConversationRepo, AiMessageRepo, KnowledgeRepo}; use df_storage::db::Database; use df_storage::models::{AiProviderRecord, KnowledgeRecord}; @@ -566,12 +566,21 @@ async fn extract_knowledge_from_conversation( .filter(|t| !t.trim().is_empty()) .unwrap_or_else(|| "未命名对话".to_string()); - let messages: Vec = match serde_json::from_str(&conv.messages) { - Ok(v) => v, - Err(e) => { - tracing::warn!(error = %e, "[ai] 对话消息 JSON 解析失败,降级空消息(知识提炼跳过)"); - Vec::new() + // 消息读取:优先 ai_messages 表(消息拆分存储真相源),表空时 fallback 旧 messages JSON 列(老库兼容) + let msg_repo = AiMessageRepo::new(db); + let records = msg_repo.list_by_conversation(conv_id).await.unwrap_or_default(); + let messages: Vec = if !records.is_empty() { + records.iter().map(crate::commands::ai::commands::record_to_message).collect() + } else { + // 老库未迁移或坏数据:回退旧 messages JSON 列(与 ai_conversation_switch 同一兼容路径) + let has_legacy = conv.messages != "[]" && !conv.messages.is_empty(); + if has_legacy { + tracing::warn!( + conv_id, + "[KNOWLEDGE-EXTRACT] ai_messages 表为空,回退旧 messages JSON 列(老库兼容)" + ); } + serde_json::from_str(&conv.messages).unwrap_or_default() }; // 过滤 user/assistant,取最后 6 条 let recent: Vec<&ChatMessage> = messages