fix(desktop): DeerFlow UI — ChatArea refactor + ai-elements + dead CSS cleanup
ChatArea retry button uses setInput instead of direct sendToGateway, fix bootstrap spinner stuck for non-logged-in users, remove dead CSS (aurora-title/sidebar-open/quick-action-chips), add ai components (ReasoningBlock/StreamingText/ChatMode/ModelSelector/TaskProgress), add ClassroomPlayer + ResizableChatLayout + artifact panel Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -44,13 +44,7 @@ impl Worker for GenerateEmbeddingWorker {
|
||||
}
|
||||
};
|
||||
|
||||
// 2. 删除旧分块(full refresh on each update)
|
||||
sqlx::query("DELETE FROM knowledge_chunks WHERE item_id = $1")
|
||||
.bind(&args.item_id)
|
||||
.execute(db)
|
||||
.await?;
|
||||
|
||||
// 3. 分块
|
||||
// 2. 分块
|
||||
let chunks = crate::knowledge::service::chunk_content(&content, 512, 64);
|
||||
|
||||
if chunks.is_empty() {
|
||||
@@ -58,13 +52,32 @@ impl Worker for GenerateEmbeddingWorker {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// 4. 写入分块(带关键词继承)
|
||||
// 3. 在事务中删除旧分块 + 插入新分块(防止并发竞争条件)
|
||||
let mut tx = db.begin().await?;
|
||||
|
||||
// 锁定条目行防止并发 worker 同时处理同一条目
|
||||
let locked: Option<(String,)> = sqlx::query_as(
|
||||
"SELECT id FROM knowledge_items WHERE id = $1 FOR UPDATE"
|
||||
)
|
||||
.bind(&args.item_id)
|
||||
.fetch_optional(&mut *tx)
|
||||
.await?;
|
||||
|
||||
if locked.is_none() {
|
||||
tx.rollback().await?;
|
||||
tracing::warn!("GenerateEmbedding: item {} was deleted during processing", args.item_id);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
sqlx::query("DELETE FROM knowledge_chunks WHERE item_id = $1")
|
||||
.bind(&args.item_id)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
for (idx, chunk) in chunks.iter().enumerate() {
|
||||
let chunk_id = uuid::Uuid::new_v4().to_string();
|
||||
|
||||
// 为每个 chunk 提取额外关键词(简单策略:标题 + 继承关键词)
|
||||
let mut chunk_keywords = keywords.clone();
|
||||
// 从 chunk 内容提取高频词作为补充关键词
|
||||
extract_chunk_keywords(chunk, &mut chunk_keywords);
|
||||
|
||||
sqlx::query(
|
||||
@@ -76,10 +89,12 @@ impl Worker for GenerateEmbeddingWorker {
|
||||
.bind(idx as i32)
|
||||
.bind(chunk)
|
||||
.bind(&chunk_keywords)
|
||||
.execute(db)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
}
|
||||
|
||||
tx.commit().await?;
|
||||
|
||||
tracing::info!(
|
||||
"GenerateEmbedding: item '{}' → {} chunks (keywords: {})",
|
||||
title,
|
||||
|
||||
@@ -8,7 +8,8 @@ use super::Worker;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct UpdateLastUsedArgs {
|
||||
pub token_id: String,
|
||||
/// token_hash 用于 WHERE 条件匹配
|
||||
pub token_hash: String,
|
||||
}
|
||||
|
||||
pub struct UpdateLastUsedWorker;
|
||||
@@ -23,9 +24,9 @@ impl Worker for UpdateLastUsedWorker {
|
||||
|
||||
async fn perform(&self, db: &PgPool, args: Self::Args) -> SaasResult<()> {
|
||||
let now = chrono::Utc::now().to_rfc3339();
|
||||
sqlx::query("UPDATE api_tokens SET last_used_at = $1 WHERE id = $2")
|
||||
sqlx::query("UPDATE api_tokens SET last_used_at = $1 WHERE token_hash = $2")
|
||||
.bind(&now)
|
||||
.bind(&args.token_id)
|
||||
.bind(&args.token_hash)
|
||||
.execute(db)
|
||||
.await?;
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user