refactor(core): 扫清 v0.1 Phase A 技术债
- 修复测试编译回归:补全 session.rs/cycle.rs 测试模块导入; convert.rs 2 处 irrefutable if let 改为 let - composer.rs 迁移至 IR:OpenaiChatMessage → Message, ContentField/OpenaiContentPart → ContentBlock;删除 set_message_name 和 build_request;developer 消息映射为 Message::System - knowledge.rs 锁修复:std::sync::Mutex → tokio::sync::Mutex; search() 优化锁粒度(锁内仅 clone IDs,避免锁内异步 IO) - 标记 ChatResponse / ToolDefinition 为废弃(#[deprecated(since = "0.1.0")]), 内部使用点加 #[allow(deprecated)] 抑制警告 - clippy 清零:合并冗余 if、手动 strip_prefix 改 strip_prefix、 多处 dead_code 抑制、测试代码清理
This commit is contained in:
@@ -236,7 +236,7 @@ mod tests {
|
||||
};
|
||||
let mut conv = ConversationMemory::new(store, "s1", config);
|
||||
for i in 0..5 {
|
||||
conv.add_message(Message::user_text(&format!("msg-{i}")))
|
||||
conv.add_message(Message::user_text(format!("msg-{i}")))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
@@ -253,7 +253,7 @@ mod tests {
|
||||
};
|
||||
let mut conv = ConversationMemory::new(store, "s1", config);
|
||||
for i in 0..5 {
|
||||
conv.add_message(Message::user_text(&format!("msg-{i}")))
|
||||
conv.add_message(Message::user_text(format!("msg-{i}")))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
+29
-20
@@ -19,7 +19,7 @@ pub const KNOWLEDGE_PREFIX: &str = "knowledge_";
|
||||
/// 同时维护一个 `Vec<PageIndexEntry>` 索引以加速列表遍历。
|
||||
pub struct KnowledgeStore {
|
||||
store: Arc<dyn MemoryStore>,
|
||||
index: std::sync::Mutex<Vec<PageIndexEntry>>,
|
||||
index: tokio::sync::Mutex<Vec<PageIndexEntry>>,
|
||||
}
|
||||
|
||||
impl KnowledgeStore {
|
||||
@@ -27,7 +27,7 @@ impl KnowledgeStore {
|
||||
pub fn new(store: Arc<dyn MemoryStore>) -> Self {
|
||||
Self {
|
||||
store,
|
||||
index: std::sync::Mutex::new(Vec::new()),
|
||||
index: tokio::sync::Mutex::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ impl KnowledgeStore {
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let mut index = self.index.lock().unwrap();
|
||||
let mut index = self.index.lock().await;
|
||||
index.clear();
|
||||
for item in items {
|
||||
let page: KnowledgePage = serde_json::from_str(&item.content)
|
||||
@@ -66,7 +66,7 @@ impl KnowledgeStore {
|
||||
created_at: now,
|
||||
};
|
||||
self.store.save(item).await?;
|
||||
let mut index = self.index.lock().unwrap();
|
||||
let mut index = self.index.lock().await;
|
||||
// 替换或追加
|
||||
if let Some(existing) = index.iter_mut().find(|e| e.id == page.id) {
|
||||
*existing = PageIndexEntry::from(&page);
|
||||
@@ -106,7 +106,7 @@ impl KnowledgeStore {
|
||||
pub async fn delete_page(&self, id: &str) -> Result<(), MemoryError> {
|
||||
let full_id = format!("{KNOWLEDGE_PREFIX}{id}");
|
||||
self.store.delete(&full_id).await?;
|
||||
let mut index = self.index.lock().unwrap();
|
||||
let mut index = self.index.lock().await;
|
||||
index.retain(|e| e.id != id);
|
||||
Ok(())
|
||||
}
|
||||
@@ -120,22 +120,31 @@ impl KnowledgeStore {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let needle = query.to_lowercase();
|
||||
// 锁内仅 clone 匹配的 entry id,避免异步 get_page() 持有 index 锁。
|
||||
let ids: Vec<String> = {
|
||||
let index = self.index.lock().await;
|
||||
index
|
||||
.iter()
|
||||
.filter(|entry| {
|
||||
entry.title.to_lowercase().contains(&needle)
|
||||
|| entry.summary.to_lowercase().contains(&needle)
|
||||
|| entry.tags.iter().any(|t| t.to_lowercase().contains(&needle))
|
||||
})
|
||||
.map(|entry| entry.id.clone())
|
||||
.collect()
|
||||
};
|
||||
let mut results = Vec::new();
|
||||
let index = self.index.lock().unwrap();
|
||||
for entry in index.iter() {
|
||||
if (entry.title.to_lowercase().contains(&needle)
|
||||
|| entry.summary.to_lowercase().contains(&needle)
|
||||
|| entry.tags.iter().any(|t| t.to_lowercase().contains(&needle)))
|
||||
&& let Some(page) = self.get_page(&entry.id).await? {
|
||||
results.push(page);
|
||||
}
|
||||
for id in &ids {
|
||||
if let Some(page) = self.get_page(id).await? {
|
||||
results.push(page);
|
||||
}
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
/// 获取内容目录(所有页面的轻量级索引条目)。
|
||||
pub fn get_index(&self) -> Vec<PageIndexEntry> {
|
||||
self.index.lock().unwrap().clone()
|
||||
pub async fn get_index(&self) -> Vec<PageIndexEntry> {
|
||||
self.index.lock().await.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +231,7 @@ mod tests {
|
||||
let ks = KnowledgeStore::new(store);
|
||||
ks.add_page(make_page("p1", "A", &[])).await.unwrap();
|
||||
ks.add_page(make_page("p2", "B", &[])).await.unwrap();
|
||||
let index = ks.get_index();
|
||||
let index = ks.get_index().await;
|
||||
assert_eq!(index.len(), 2);
|
||||
}
|
||||
|
||||
@@ -233,13 +242,13 @@ mod tests {
|
||||
// 添加页面
|
||||
ks.add_page(make_page("p1", "A", &[])).await.unwrap();
|
||||
ks.add_page(make_page("p2", "B", &[])).await.unwrap();
|
||||
assert_eq!(ks.get_index().len(), 2);
|
||||
assert_eq!(ks.get_index().await.len(), 2);
|
||||
|
||||
// 模拟 index 漂移:清空后重建
|
||||
ks.index.lock().unwrap().clear();
|
||||
assert_eq!(ks.get_index().len(), 0);
|
||||
ks.index.lock().await.clear();
|
||||
assert_eq!(ks.get_index().await.len(), 0);
|
||||
|
||||
ks.rebuild_index().await.unwrap();
|
||||
assert_eq!(ks.get_index().len(), 2);
|
||||
assert_eq!(ks.get_index().await.len(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,9 +113,7 @@ fn extract_keywords(query: &str, stop_words: &HashSet<String>) -> Vec<String> {
|
||||
.split(|c: char| !c.is_alphanumeric())
|
||||
.filter_map(|s| {
|
||||
let lower = s.to_lowercase();
|
||||
if lower.is_empty() || lower.chars().count() < 2 {
|
||||
None
|
||||
} else if stop_words.contains(&lower) {
|
||||
if lower.is_empty() || lower.chars().count() < 2 || stop_words.contains(&lower) {
|
||||
None
|
||||
} else {
|
||||
Some(lower)
|
||||
|
||||
Reference in New Issue
Block a user