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:
徐涛
2026-07-03 15:19:37 +08:00
parent c2c0d498ee
commit c084c57e2c
16 changed files with 138 additions and 181 deletions
+2 -2
View File
@@ -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
View File
@@ -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);
}
}
+1 -3
View File
@@ -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)