Fix clippy warnings: reduce 17 warnings to 0
All checks were successful
BotServer CI/CD / build (push) Successful in 6m58s
All checks were successful
BotServer CI/CD / build (push) Successful in 6m58s
- Fix double_ended_iterator_last: use next_back() instead of last() - Fix manual_clamp: use .clamp() instead of min().max() - Fix too_many_arguments: create KbInjectionContext struct - Fix needless_borrow: remove unnecessary & reference - Fix let_and_return: return value directly - Fix await_holding_lock: drop guard before await - Fix collapsible_else_if: collapse nested if-else All changes verified with cargo clippy (0 warnings, 0 errors) Note: Local botserver crashes with existing panic during LocalFileMonitor initialization This panic exists in original code too, not caused by these changes
This commit is contained in:
parent
9f55e864ff
commit
4d7297243e
9 changed files with 63 additions and 50 deletions
|
|
@ -184,7 +184,7 @@ async fn think_kb_search(
|
||||||
/// Calculate confidence score based on multiple factors
|
/// Calculate confidence score based on multiple factors
|
||||||
fn calculate_confidence(avg_relevance: f64, result_count: usize, source_count: usize) -> f64 {
|
fn calculate_confidence(avg_relevance: f64, result_count: usize, source_count: usize) -> f64 {
|
||||||
// Base confidence from average relevance (0.0 to 1.0)
|
// Base confidence from average relevance (0.0 to 1.0)
|
||||||
let relevance_factor = avg_relevance.min(1.0).max(0.0);
|
let relevance_factor = avg_relevance.clamp(0.0, 1.0);
|
||||||
|
|
||||||
// Boost confidence with more results (diminishing returns)
|
// Boost confidence with more results (diminishing returns)
|
||||||
let result_factor = (result_count as f64 / 10.0).min(1.0);
|
let result_factor = (result_count as f64 / 10.0).min(1.0);
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,15 @@ pub struct KbSearchResult {
|
||||||
pub chunk_tokens: usize,
|
pub chunk_tokens: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct KbInjectionContext<'a> {
|
||||||
|
pub session_id: Uuid,
|
||||||
|
pub bot_id: Uuid,
|
||||||
|
pub bot_name: &'a str,
|
||||||
|
pub user_query: &'a str,
|
||||||
|
pub messages: &'a mut serde_json::Value,
|
||||||
|
pub max_context_tokens: usize,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct KbContextManager {
|
pub struct KbContextManager {
|
||||||
kb_manager: Arc<KnowledgeBaseManager>,
|
kb_manager: Arc<KnowledgeBaseManager>,
|
||||||
|
|
@ -479,28 +488,23 @@ fn estimate_tokens(text: &str) -> usize {
|
||||||
pub async fn inject_kb_context(
|
pub async fn inject_kb_context(
|
||||||
kb_manager: Arc<KnowledgeBaseManager>,
|
kb_manager: Arc<KnowledgeBaseManager>,
|
||||||
db_pool: DbPool,
|
db_pool: DbPool,
|
||||||
session_id: Uuid,
|
context: KbInjectionContext<'_>,
|
||||||
bot_id: Uuid,
|
|
||||||
bot_name: &str,
|
|
||||||
user_query: &str,
|
|
||||||
messages: &mut serde_json::Value,
|
|
||||||
max_context_tokens: usize,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let context_manager = KbContextManager::new(kb_manager.clone(), db_pool.clone());
|
let context_manager = KbContextManager::new(kb_manager.clone(), db_pool.clone());
|
||||||
|
|
||||||
let kb_contexts = context_manager
|
let kb_contexts = context_manager
|
||||||
.search_active_kbs(session_id, bot_id, bot_name, user_query, 5, max_context_tokens / 2)
|
.search_active_kbs(context.session_id, context.bot_id, context.bot_name, context.user_query, 5, context.max_context_tokens / 2)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let website_contexts = context_manager
|
let website_contexts = context_manager
|
||||||
.search_active_websites(session_id, user_query, 5, max_context_tokens / 2)
|
.search_active_websites(context.session_id, context.user_query, 5, context.max_context_tokens / 2)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut all_contexts = kb_contexts;
|
let mut all_contexts = kb_contexts;
|
||||||
all_contexts.extend(website_contexts);
|
all_contexts.extend(website_contexts);
|
||||||
|
|
||||||
if all_contexts.is_empty() {
|
if all_contexts.is_empty() {
|
||||||
debug!("No KB or website context found for session {}", session_id);
|
debug!("No KB or website context found for session {}", context.session_id);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,10 +530,10 @@ pub async fn inject_kb_context(
|
||||||
info!(
|
info!(
|
||||||
"Injecting {} characters of KB/website context into prompt for session {}",
|
"Injecting {} characters of KB/website context into prompt for session {}",
|
||||||
sanitized_context.len(),
|
sanitized_context.len(),
|
||||||
session_id
|
context.session_id
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(messages_array) = messages.as_array_mut() {
|
if let Some(messages_array) = context.messages.as_array_mut() {
|
||||||
let system_msg_idx = messages_array.iter().position(|m| m["role"] == "system");
|
let system_msg_idx = messages_array.iter().position(|m| m["role"] == "system");
|
||||||
|
|
||||||
if let Some(idx) = system_msg_idx {
|
if let Some(idx) = system_msg_idx {
|
||||||
|
|
|
||||||
|
|
@ -676,15 +676,18 @@ impl BotOrchestrator {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(kb_manager) = self.state.kb_manager.as_ref() {
|
if let Some(kb_manager) = self.state.kb_manager.as_ref() {
|
||||||
|
let context = crate::core::bot::kb_context::KbInjectionContext {
|
||||||
|
session_id,
|
||||||
|
bot_id: session.bot_id,
|
||||||
|
bot_name: &bot_name_for_context,
|
||||||
|
user_query: &message_content,
|
||||||
|
messages: &mut messages,
|
||||||
|
max_context_tokens: 8000,
|
||||||
|
};
|
||||||
if let Err(e) = inject_kb_context(
|
if let Err(e) = inject_kb_context(
|
||||||
kb_manager.clone(),
|
kb_manager.clone(),
|
||||||
self.state.conn.clone(),
|
self.state.conn.clone(),
|
||||||
session_id,
|
context,
|
||||||
session.bot_id,
|
|
||||||
&bot_name_for_context,
|
|
||||||
&message_content,
|
|
||||||
&mut messages,
|
|
||||||
8000,
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -71,14 +71,13 @@ INSTALL_LOCK = true
|
||||||
|
|
||||||
// Try to create admin user and get runner token via HTTP API
|
// Try to create admin user and get runner token via HTTP API
|
||||||
// Note: Forgejo CLI binary may segfault on some systems, so we use curl
|
// Note: Forgejo CLI binary may segfault on some systems, so we use curl
|
||||||
let runner_token = match try_alm_api_setup(alm_url, &username, &password, data_path.to_str().unwrap_or(".")).await {
|
let runner_token = match try_alm_api_setup(alm_url, username, &password, data_path.to_str().unwrap_or(".")).await {
|
||||||
Ok(token) => token,
|
Ok(token) => token,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("ALM automated setup unavailable via API: {}", e);
|
warn!("ALM automated setup unavailable via API: {}", e);
|
||||||
warn!("ALM will need manual configuration. Create admin user and runner token via web UI.");
|
warn!("ALM will need manual configuration. Create admin user and runner token via web UI.");
|
||||||
// Store placeholder credentials
|
// Store placeholder credentials
|
||||||
let placeholder_token = generate_random_string(40);
|
generate_random_string(40)
|
||||||
placeholder_token
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1548,7 +1548,7 @@ VAULT_CACERT={}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write default credentials to Vault for all components
|
// Write default credentials to Vault for all components
|
||||||
self.seed_vault_defaults(&vault_addr, &root_token, &ca_cert, &vault_bin)?;
|
self.seed_vault_defaults(&vault_addr, root_token, &ca_cert, &vault_bin)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,12 @@ pub async fn init_secrets_manager() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_database_url() -> Result<String> {
|
pub async fn get_database_url() -> Result<String> {
|
||||||
let guard = SECRETS_MANAGER.read().map_err(|e| anyhow::anyhow!("Lock poisoned: {}", e))?;
|
let manager = {
|
||||||
if let Some(ref manager) = *guard {
|
let guard = SECRETS_MANAGER.read().map_err(|e| anyhow::anyhow!("Lock poisoned: {}", e))?;
|
||||||
|
(*guard).as_ref().map(|manager| manager.clone())
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(manager) = manager {
|
||||||
return manager.get_database_url().await;
|
return manager.get_database_url().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,9 +118,17 @@ pub async fn create_s3_operator(
|
||||||
};
|
};
|
||||||
|
|
||||||
let (access_key, secret_key) = if config.access_key.is_empty() || config.secret_key.is_empty() {
|
let (access_key, secret_key) = if config.access_key.is_empty() || config.secret_key.is_empty() {
|
||||||
let guard = SECRETS_MANAGER.read().map_err(|e| format!("Lock poisoned: {}", e))?;
|
let (manager, is_vault_enabled) = {
|
||||||
if let Some(ref manager) = *guard {
|
let guard = SECRETS_MANAGER.read().map_err(|e| format!("Lock poisoned: {}", e))?;
|
||||||
if manager.is_enabled() {
|
if let Some(ref manager) = *guard {
|
||||||
|
(Some(manager.clone()), manager.is_enabled())
|
||||||
|
} else {
|
||||||
|
(None, false)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match (manager, is_vault_enabled) {
|
||||||
|
(Some(manager), true) => {
|
||||||
match manager.get_drive_credentials().await {
|
match manager.get_drive_credentials().await {
|
||||||
Ok((ak, sk)) => (ak, sk),
|
Ok((ak, sk)) => (ak, sk),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -124,11 +136,8 @@ pub async fn create_s3_operator(
|
||||||
(config.access_key.clone(), config.secret_key.clone())
|
(config.access_key.clone(), config.secret_key.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
(config.access_key.clone(), config.secret_key.clone())
|
|
||||||
}
|
}
|
||||||
} else {
|
_ => (config.access_key.clone(), config.secret_key.clone())
|
||||||
(config.access_key.clone(), config.secret_key.clone())
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(config.access_key.clone(), config.secret_key.clone())
|
(config.access_key.clone(), config.secret_key.clone())
|
||||||
|
|
|
||||||
|
|
@ -333,16 +333,14 @@ impl LocalFileMonitor {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
stack.push(path);
|
stack.push(path);
|
||||||
} else {
|
} else if let Ok(meta) = tokio::fs::metadata(&path).await {
|
||||||
if let Ok(meta) = tokio::fs::metadata(&path).await {
|
let mtime = meta.modified()
|
||||||
let mtime = meta.modified()
|
.map(|t| t.duration_since(SystemTime::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0))
|
||||||
.map(|t| t.duration_since(SystemTime::UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0))
|
.unwrap_or(0);
|
||||||
.unwrap_or(0);
|
let size = meta.len();
|
||||||
let size = meta.len();
|
// Simple combinatorial hash
|
||||||
// Simple combinatorial hash
|
hash = hash.wrapping_mul(31).wrapping_add(mtime.wrapping_mul(37).wrapping_add(size));
|
||||||
hash = hash.wrapping_mul(31).wrapping_add(mtime.wrapping_mul(37).wrapping_add(size));
|
file_count += 1;
|
||||||
file_count += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -337,11 +337,11 @@ pub async fn init_redis() -> Option<Arc<redis::Client>> {
|
||||||
Ok(mut conn) => {
|
Ok(mut conn) => {
|
||||||
match redis::cmd("PING").query::<String>(&mut conn) {
|
match redis::cmd("PING").query::<String>(&mut conn) {
|
||||||
Ok(response) if response == "PONG" => {
|
Ok(response) if response == "PONG" => {
|
||||||
log::info!("Cache initialized - Valkey connected via {}", cache_url.split('@').last().unwrap_or(&cache_url));
|
log::info!("Cache initialized - Valkey connected via {}", cache_url.split('@').next_back().unwrap_or(&cache_url));
|
||||||
Ok(Some(Arc::new(client)))
|
Ok(Some(Arc::new(client)))
|
||||||
}
|
}
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
log::info!("Cache initialized - Valkey connected via {} (PING: {})", cache_url.split('@').last().unwrap_or(&cache_url), response);
|
log::info!("Cache initialized - Valkey connected via {} (PING: {})", cache_url.split('@').next_back().unwrap_or(&cache_url), response);
|
||||||
Ok(Some(Arc::new(client)))
|
Ok(Some(Arc::new(client)))
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ impl TlsIntegration {
|
||||||
let qdrant_secure = qdrant_url.replace("http://", "https://");
|
let qdrant_secure = qdrant_url.replace("http://", "https://");
|
||||||
let qdrant_port: u16 = qdrant_url
|
let qdrant_port: u16 = qdrant_url
|
||||||
.split(':')
|
.split(':')
|
||||||
.last()
|
.next_back()
|
||||||
.and_then(|p| p.parse().ok())
|
.and_then(|p| p.parse().ok())
|
||||||
.unwrap_or(6333);
|
.unwrap_or(6333);
|
||||||
let qdrant_tls_port: u16 = qdrant_secure
|
let qdrant_tls_port: u16 = qdrant_secure
|
||||||
.split(':')
|
.split(':')
|
||||||
.last()
|
.next_back()
|
||||||
.and_then(|p| p.parse().ok())
|
.and_then(|p| p.parse().ok())
|
||||||
.unwrap_or(6334);
|
.unwrap_or(6334);
|
||||||
|
|
||||||
|
|
@ -62,12 +62,12 @@ impl TlsIntegration {
|
||||||
let llm_secure = llm_url.replace("http://", "https://");
|
let llm_secure = llm_url.replace("http://", "https://");
|
||||||
let llm_port: u16 = llm_url
|
let llm_port: u16 = llm_url
|
||||||
.split(':')
|
.split(':')
|
||||||
.last()
|
.next_back()
|
||||||
.and_then(|p| p.parse().ok())
|
.and_then(|p| p.parse().ok())
|
||||||
.unwrap_or(8081);
|
.unwrap_or(8081);
|
||||||
let llm_tls_port: u16 = llm_secure
|
let llm_tls_port: u16 = llm_secure
|
||||||
.split(':')
|
.split(':')
|
||||||
.last()
|
.next_back()
|
||||||
.and_then(|p| p.parse().ok())
|
.and_then(|p| p.parse().ok())
|
||||||
.unwrap_or(8444);
|
.unwrap_or(8444);
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ impl TlsIntegration {
|
||||||
};
|
};
|
||||||
let drive_port: u16 = drive_host
|
let drive_port: u16 = drive_host
|
||||||
.split(':')
|
.split(':')
|
||||||
.last()
|
.next_back()
|
||||||
.and_then(|p| p.parse().ok())
|
.and_then(|p| p.parse().ok())
|
||||||
.unwrap_or(9100);
|
.unwrap_or(9100);
|
||||||
|
|
||||||
|
|
@ -123,12 +123,12 @@ impl TlsIntegration {
|
||||||
let directory_secure = directory_url.replace("http://", "https://");
|
let directory_secure = directory_url.replace("http://", "https://");
|
||||||
let directory_port: u16 = directory_url
|
let directory_port: u16 = directory_url
|
||||||
.split(':')
|
.split(':')
|
||||||
.last()
|
.next_back()
|
||||||
.and_then(|p| p.parse().ok())
|
.and_then(|p| p.parse().ok())
|
||||||
.unwrap_or(9000);
|
.unwrap_or(9000);
|
||||||
let directory_tls_port: u16 = directory_secure
|
let directory_tls_port: u16 = directory_secure
|
||||||
.split(':')
|
.split(':')
|
||||||
.last()
|
.next_back()
|
||||||
.and_then(|p| p.parse().ok())
|
.and_then(|p| p.parse().ok())
|
||||||
.unwrap_or(8446);
|
.unwrap_or(8446);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue