Fix clippy warnings: reduce 17 warnings to 0
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:
Rodrigo Rodriguez (Pragmatismo) 2026-04-03 22:34:43 -03:00
parent 9f55e864ff
commit 4d7297243e
9 changed files with 63 additions and 50 deletions

View file

@ -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);

View file

@ -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 {

View file

@ -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
{ {

View file

@ -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
} }
}; };

View file

@ -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(())
} }

View file

@ -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())

View file

@ -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;
}
} }
} }
} }

View file

@ -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) => {

View file

@ -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);