From e161952046438b1d45d6db92746875176882dbe9 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Feb 2026 12:55:18 +0000 Subject: [PATCH 1/2] fix: resolve all clippy warnings to prevent build failures with warnings=deny The project has `[lints.rust] warnings = "deny"` in Cargo.toml which turns all compiler and clippy warnings into hard errors. This causes build failures on different Rust toolchain versions that may introduce new warnings. Fixes include: - Replace manual strip_prefix/strip_suffix with std methods - Use Display trait instead of inherent to_string() methods - Simplify filter_map/find_map where possible - Remove unnecessary format!/to_string calls - Fix empty lines after doc comments - Use clamp() instead of manual min/max pattern - Replace &Vec with &[T] in function signatures - Use if-let instead of is_some()+unwrap() - Add #[allow] for structural issues (too_many_arguments, type_complexity) Closes #6 https://claude.ai/code/session_01J96NRV6o9dKTmr7igJmcaG --- src/auth/token_manager.rs | 2 +- src/branch/comparison.rs | 19 ++-- src/branch/merge.rs | 9 +- src/branch/mod.rs | 2 - .../repository/branch_message_repository.rs | 4 +- .../repository/branch_metadata_repository.rs | 4 +- src/branch/service/branch_service.rs | 9 +- src/branch/tree.rs | 8 +- src/chat/demo.rs | 6 +- src/chat/formatter.rs | 27 +++--- src/chat/interactive.rs | 8 +- src/commands/chat.rs | 2 +- src/commands/commit.rs | 24 ++--- src/commands/mod.rs | 33 ++++--- src/commands/preset.rs | 34 +++---- src/commands/rebase.rs | 12 +-- src/commands/session.rs | 7 +- src/commands/stash.rs | 20 ++--- src/commands/tag.rs | 6 +- src/config/project.rs | 8 +- src/config/service/claude_config.rs | 2 +- src/config/service/config_service.rs | 5 +- src/config/service/open_ai_config.rs | 2 +- src/context/analyzer.rs | 14 ++- src/context/chunker.rs | 2 +- src/context/config.rs | 18 ++-- src/context/detector.rs | 8 +- src/context/mod.rs | 2 +- src/context/multi_session.rs | 2 +- src/context/template_manager.rs | 6 +- src/context/templates.rs | 1 + src/discovery.rs | 2 +- src/git/diff.rs | 7 +- src/git/hooks.rs | 20 ++--- src/git/mod.rs | 1 - src/llm/common/model/role.rs | 15 ++-- src/llm/openai/adapter/gpt5_adapter.rs | 7 +- src/llm/openai/config/gpt5_config.rs | 4 +- src/llm/openai/model/codex_api.rs | 4 +- src/llm/openai/model/custom_tools.rs | 9 +- src/llm/openai/model/mod.rs | 1 + src/llm/openai/model/model.rs | 89 ++++++++++--------- src/llm/openai/model/verbosity.rs | 26 +++--- src/llm/openai/service/chat.rs | 4 +- src/llm/openai/service/codex.rs | 4 +- src/llm/openai/tools/executor.rs | 2 +- src/main.rs | 1 - src/manpage.rs | 6 +- src/output/export.rs | 3 +- src/output/streaming.rs | 7 +- src/output/syntax.rs | 15 ++-- src/path/extract.rs | 16 ++-- src/preset/manager.rs | 14 +-- src/preset/mod.rs | 1 - src/session/entity/smart_context_entity.rs | 1 + src/session/model/message.rs | 11 +-- src/session/model/session.rs | 4 +- src/session/model/smart_context.rs | 1 + .../repository/smart_context_repository.rs | 1 + src/session/service/sessions_service.rs | 14 +-- src/session/service/smart_context_service.rs | 5 +- src/setup/wizard.rs | 2 +- 62 files changed, 269 insertions(+), 334 deletions(-) diff --git a/src/auth/token_manager.rs b/src/auth/token_manager.rs index 1bb959b..3f7cc24 100644 --- a/src/auth/token_manager.rs +++ b/src/auth/token_manager.rs @@ -41,7 +41,7 @@ impl<'a, R: ConfigRepository> TokenManager<'a, R> { .ok() .and_then(|c| DateTime::parse_from_rfc3339(&c.value).ok()) .map(|dt| dt.with_timezone(&Utc)) - .unwrap_or_else(|| Utc::now()); + .unwrap_or_else(Utc::now); let id_token = config_service::fetch_by_key(self.repo, &ConfigKeys::CodexIdToken.to_key()) .ok() diff --git a/src/branch/comparison.rs b/src/branch/comparison.rs index 13fa1f6..bc7c0d1 100644 --- a/src/branch/comparison.rs +++ b/src/branch/comparison.rs @@ -1,9 +1,8 @@ /// Branch comparison features for TermAI -#[allow(dead_code)] -/// +/// /// This module provides sophisticated comparison capabilities between conversation branches, /// allowing users to analyze different approaches, solutions, and outcomes side-by-side. - +#[allow(dead_code)] use crate::branch::entity::branch_entity::BranchEntity; use crate::branch::service::BranchService; use crate::repository::db::SqliteRepository; @@ -168,7 +167,7 @@ impl BranchComparator { // Header output.push_str(&format!("{}\n", "šŸ“Š Side-by-Side Branch Comparison".bright_green().bold())); output.push_str(&format!("{}\n", "═".repeat(40).dimmed())); - output.push_str("\n"); + output.push('\n'); // Branch headers let branch_names: Vec = comparison.branches.iter() @@ -269,7 +268,7 @@ impl BranchComparator { output.push_str(&format!("{}\n", "šŸ“‹ Comparison Summary".bright_yellow().bold())); output.push_str(&format!("{}\n", "═".repeat(20).dimmed())); - output.push_str("\n"); + output.push('\n'); let summary = &comparison.summary; @@ -282,7 +281,7 @@ impl BranchComparator { "Overall similarity:".bright_cyan(), summary.similarity_percentage )); - output.push_str("\n"); + output.push('\n'); // Quality scores if !summary.quality_scores.is_empty() { @@ -305,7 +304,7 @@ impl BranchComparator { } )); } - output.push_str("\n"); + output.push('\n'); } // Unique insights @@ -327,7 +326,7 @@ impl BranchComparator { insight.description )); } - output.push_str("\n"); + output.push('\n'); } // Recommendations @@ -647,7 +646,7 @@ impl QuickCompare { let mut output = String::new(); output.push_str(&format!("{}\n", "šŸŽÆ Branch Outcomes Comparison".bright_green().bold())); output.push_str(&format!("{}\n", "═".repeat(30).dimmed())); - output.push_str("\n"); + output.push('\n'); for (i, branch) in comparison.branches.iter().enumerate() { let branch_name = branch.branch_name.as_deref().unwrap_or("unnamed"); @@ -678,7 +677,7 @@ impl QuickCompare { output.push_str(&format!(" {} {}\n", "Description:".dimmed(), description.dimmed())); } - output.push_str("\n"); + output.push('\n'); } // Add recommendations diff --git a/src/branch/merge.rs b/src/branch/merge.rs index b3424bb..74b3e25 100644 --- a/src/branch/merge.rs +++ b/src/branch/merge.rs @@ -2,7 +2,6 @@ /// /// This module provides sophisticated merging capabilities for conversation branches, /// allowing users to consolidate insights, resolve conflicts, and maintain conversation flow. - use crate::branch::entity::branch_entity::BranchEntity; use crate::branch::service::BranchService; use crate::branch::comparison::{BranchComparator, BranchComparison}; @@ -301,7 +300,7 @@ impl BranchMerger { output.push_str(&format!("{}\n", "šŸ“‹ Merge Preview".bright_green().bold())); output.push_str(&format!("{}\n", "═".repeat(15).dimmed())); - output.push_str("\n"); + output.push('\n'); // Source branches output.push_str(&format!("{}\n", "Source branches:".bright_cyan())); @@ -324,7 +323,7 @@ impl BranchMerger { }; output.push_str(&format!("{} {}\n", "Strategy:".bright_cyan(), strategy_desc.bright_white())); - output.push_str("\n"); + output.push('\n'); // Conflicts if !merge.conflicts.is_empty() { @@ -349,7 +348,7 @@ impl BranchMerger { } // Resolution plan - output.push_str("\n"); + output.push('\n'); output.push_str(&format!("{}\n", "šŸŽÆ Resolution Plan:".bright_yellow().bold())); for action in &merge.resolution_plan.suggested_actions { output.push_str(&format!(" • {}\n", action)); @@ -564,7 +563,7 @@ impl BranchMerger { branch.created_at.format("%Y-%m-%d %H:%M:%S") )); output.push_str(&format!("Status: {}\n", branch.status)); - output.push_str("\n"); + output.push('\n'); for (i, message) in messages.iter().enumerate() { output.push_str(&format!("Message {} ({:?}):\n", i + 1, message.role)); diff --git a/src/branch/mod.rs b/src/branch/mod.rs index dff8e29..db329ea 100644 --- a/src/branch/mod.rs +++ b/src/branch/mod.rs @@ -5,10 +5,8 @@ /// - Compare different approaches and solutions /// - Merge successful branches back into main conversations /// - Navigate complex problem-solving workflows efficiently - #[allow(dead_code)] #[allow(unused_imports)] - pub mod entity; pub mod repository; pub mod service; diff --git a/src/branch/repository/branch_message_repository.rs b/src/branch/repository/branch_message_repository.rs index 5333544..90f9371 100644 --- a/src/branch/repository/branch_message_repository.rs +++ b/src/branch/repository/branch_message_repository.rs @@ -63,7 +63,7 @@ impl BranchMessageRepository { )?; let rows = stmt.query_map(params![branch_id], |row| { - Ok(row.get::<_, String>(0)?) + row.get::<_, String>(0) })?; let mut message_ids = Vec::new(); @@ -139,7 +139,7 @@ impl BranchMessageRepository { )?; let rows = stmt.query_map(params![message_id], |row| { - Ok(row.get::<_, String>(0)?) + row.get::<_, String>(0) })?; let mut branch_ids = Vec::new(); diff --git a/src/branch/repository/branch_metadata_repository.rs b/src/branch/repository/branch_metadata_repository.rs index d429e76..559624c 100644 --- a/src/branch/repository/branch_metadata_repository.rs +++ b/src/branch/repository/branch_metadata_repository.rs @@ -30,7 +30,7 @@ impl BranchMetadataRepository { )?; let mut rows = stmt.query_map(params![branch_id, key], |row| { - Ok(row.get::<_, String>(0)?) + row.get::<_, String>(0) })?; match rows.next() { @@ -93,7 +93,7 @@ impl BranchMetadataRepository { )?; let rows = stmt.query_map(params![key, value], |row| { - Ok(row.get::<_, String>(0)?) + row.get::<_, String>(0) })?; let mut branch_ids = Vec::new(); diff --git a/src/branch/service/branch_service.rs b/src/branch/service/branch_service.rs index d75194f..2bcda2f 100644 --- a/src/branch/service/branch_service.rs +++ b/src/branch/service/branch_service.rs @@ -48,7 +48,7 @@ impl BranchService { // Copy messages if needed if let Some(parent_id) = &parent_branch_id { - Self::copy_branch_messages_to_point(repo, &parent_id, &branch_id, from_message_index)?; + Self::copy_branch_messages_to_point(repo, parent_id, &branch_id, from_message_index)?; } else { Self::copy_session_messages_to_point(repo, session_id, &branch_id, from_message_index)?; } @@ -147,7 +147,6 @@ impl BranchService { } /// Internal helper methods - fn create_branch_in_db(repo: &mut SqliteRepository, branch: &BranchEntity) -> Result<()> { repo.conn.execute( "INSERT INTO conversation_branches (id, session_id, parent_branch_id, branch_name, description, created_at, last_activity, status) @@ -174,7 +173,7 @@ impl BranchService { )?; let rows = stmt.query_map(params![branch_id], |row| { - Ok(row.get::<_, String>(0)?) + row.get::<_, String>(0) })?; let mut message_ids = Vec::new(); @@ -455,7 +454,7 @@ impl BranchService { let mut children_map: std::collections::HashMap> = std::collections::HashMap::new(); for branch in branches { if let Some(parent_id) = &branch.parent_branch_id { - children_map.entry(parent_id.clone()).or_insert_with(Vec::new).push(branch); + children_map.entry(parent_id.clone()).or_default().push(branch); } } @@ -495,7 +494,7 @@ impl BranchService { let mut children_map: std::collections::HashMap> = std::collections::HashMap::new(); for branch in branches { if let Some(parent_id) = &branch.parent_branch_id { - children_map.entry(parent_id.clone()).or_insert_with(Vec::new).push(branch); + children_map.entry(parent_id.clone()).or_default().push(branch); } } diff --git a/src/branch/tree.rs b/src/branch/tree.rs index 94fd5ae..5f8e949 100644 --- a/src/branch/tree.rs +++ b/src/branch/tree.rs @@ -45,7 +45,7 @@ impl BranchTree { } // Add legend - output.push_str("\n"); + output.push('\n'); output.push_str(&format!("{}\n", "Legend:".bright_yellow().bold())); output.push_str(&format!(" {} Current branch\n", "*".bright_green())); output.push_str(&format!(" {} Active branch\n", "ā—".bright_blue())); @@ -68,7 +68,7 @@ impl BranchTree { if let Some(parent_id) = &branch.parent_branch_id { children_map.entry(parent_id.clone()) - .or_insert_with(Vec::new) + .or_default() .push(branch.clone()); } } @@ -174,7 +174,7 @@ impl BranchTree { // Format timestamp let time_info = format!(" [{}]", - node.branch.created_at.format("%Y-%m-%d").to_string() + node.branch.created_at.format("%Y-%m-%d") ).dimmed(); // Add line to output @@ -273,7 +273,7 @@ impl BranchTree { output.push_str(&format!("{}\n", "🌳 Interactive Branch Navigator".bright_green().bold())); output.push_str(&format!("{}\n", "═".repeat(32).dimmed())); output.push_str(&format!("{}\n", "[↑↓] Navigate [Enter] Switch [q] Quit".bright_yellow())); - output.push_str("\n"); + output.push('\n'); for root_node in &tree_nodes { Self::render_interactive_node(&mut output, root_node, "", true, selected_branch_id)?; diff --git a/src/chat/demo.rs b/src/chat/demo.rs index c926852..034a805 100644 --- a/src/chat/demo.rs +++ b/src/chat/demo.rs @@ -11,8 +11,7 @@ pub async fn demo_enhanced_chat_formatting() -> Result<()> { let mut formatter = ChatFormatter::new(); // Demo different types of responses that would come from an AI - let sample_responses = vec![ - ( + let sample_responses = [( "Simple response", "Hello! I'm your AI assistant. How can I help you today?" ), @@ -120,8 +119,7 @@ async fn main() -> Result<(), Box> { > The key is that async operations don't block the thread while waiting! This makes your applications much more efficient when dealing with I/O-bound workloads."# - ), - ]; + )]; // Demonstrate each type of response for (i, (description, content)) in sample_responses.iter().enumerate() { diff --git a/src/chat/formatter.rs b/src/chat/formatter.rs index 0a324b6..7f83294 100644 --- a/src/chat/formatter.rs +++ b/src/chat/formatter.rs @@ -406,24 +406,21 @@ impl ChatFormatter { let trimmed = line.trim(); // Handle headers - improved styling with better visual separation - if trimmed.starts_with("### ") { - let title = &trimmed[4..]; // Remove "### " + if let Some(title) = trimmed.strip_prefix("### ") { + // Remove "### " return format!("šŸ”· {}", title).bright_cyan().bold().to_string().into(); - } else if trimmed.starts_with("##") { - let title = if trimmed.starts_with("## ") { - &trimmed[3..] // Remove "## " - } else { - &trimmed[2..] // Remove "##" - }; + } else if let Some(title) = trimmed.strip_prefix("## ") { + return format!("šŸ”µ {}", title.trim()).bright_blue().bold().to_string().into(); + } else if let Some(title) = trimmed.strip_prefix("##") { return format!("šŸ”µ {}", title.trim()).bright_blue().bold().to_string().into(); - } else if trimmed.starts_with("# ") { - let title = &trimmed[2..]; // Remove "# " + } else if let Some(title) = trimmed.strip_prefix("# ") { + // Remove "# " return format!("🟢 {}", title).bright_green().bold().to_string().into(); } // Handle lists - if trimmed.starts_with("- ") || trimmed.starts_with("* ") { - return format!(" • {}", &trimmed[2..]).bright_yellow().to_string().into(); + if let Some(item) = trimmed.strip_prefix("- ").or_else(|| trimmed.strip_prefix("* ")) { + return format!(" • {}", item).bright_yellow().to_string().into(); } // Handle numbered lists @@ -434,8 +431,8 @@ impl ChatFormatter { } // Handle blockquotes - if trimmed.starts_with("> ") { - return format!("│ {}", &trimmed[2..]).bright_magenta().italic().to_string().into(); + if let Some(quote) = trimmed.strip_prefix("> ") { + return format!("│ {}", quote).bright_magenta().italic().to_string().into(); } // Handle bold and italic @@ -738,7 +735,7 @@ impl ChatFormatter { pub fn format_context_info(&self, context_size: usize, files: &[String]) -> String { let mut info = String::new(); info.push_str( - &format!("šŸ“ Context Information:\n") + &"šŸ“ Context Information:\n".to_string() .bright_blue() .bold() .to_string(), diff --git a/src/chat/interactive.rs b/src/chat/interactive.rs index 50eeb33..3652616 100644 --- a/src/chat/interactive.rs +++ b/src/chat/interactive.rs @@ -172,7 +172,7 @@ where sessions_service::session_add_messages( self.session_repo, self.message_repo, - &mut self.session, + &self.session, )?; self.repl .print_message(&self.formatter.format_session_saved(&session_name)); @@ -349,7 +349,7 @@ where sessions_service::session_add_messages( self.session_repo, self.message_repo, - &mut self.session, + &self.session, )?; } Err(e) => { @@ -444,7 +444,7 @@ where } // Extract content from the path - let new_context = extract_content(&Some(path.to_string()), &vec![], &vec![]); + let new_context = extract_content(&Some(path.to_string()), &[], &[]); if let Some(mut files) = new_context { // Remove duplicates and add new files @@ -513,7 +513,7 @@ where sessions_service::session_add_messages( self.session_repo, self.message_repo, - &mut self.session, + &self.session, )?; self.repl.print_message( &self diff --git a/src/commands/chat.rs b/src/commands/chat.rs index 513828b..585f16f 100644 --- a/src/commands/chat.rs +++ b/src/commands/chat.rs @@ -212,7 +212,7 @@ async fn suggest_presets_for_context(files: &[Files]) -> Result Result { ResponseOutput::Message { content, .. } => { let message_text: String = content .into_iter() - .filter_map(|item| match item { - ContentItem::OutputText { text, .. } => Some(text), + .map(|item| match item { + ContentItem::OutputText { text, .. } => text, }) .collect::>() .join("\n"); @@ -806,11 +806,7 @@ async fn execute_commit( // Get the current HEAD commit (parent) let parent_commit = if let Ok(head) = repo.head() { - if let Ok(commit) = head.peel_to_commit() { - Some(commit) - } else { - None - } + head.peel_to_commit().ok() } else { None // First commit }; @@ -839,19 +835,13 @@ async fn execute_commit( println!("{}", "āœ… Commit created successfully!".green().bold()); println!( - "{}", - format!( - " Commit ID: {}", - commit_id.to_string()[..8].bright_yellow() - ) - ); - println!( - "{}", - format!(" Message: {}", commit_message.subject.bright_white()) + " Commit ID: {}", + commit_id.to_string()[..8].bright_yellow() ); + println!(" Message: {}", commit_message.subject.bright_white()); if let Some(ref body) = commit_message.body { - println!("{}", format!(" Body: {}", body.dimmed())); + println!(" Body: {}", body.dimmed()); } Ok(()) diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 369fc98..edfd14e 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -43,7 +43,7 @@ pub async fn dispatch_command(args: &Args, repo: &SqliteRepository) -> Result Result { ask::handle_ask_command(ask_args, repo) .await .context("āŒ Ask command failed") - .map_err(|e| enhance_ask_error(e))?; + .map_err(enhance_ask_error)?; Ok(true) } Some(Commands::Commit(commit_args)) => { commit::handle_commit_command(commit_args, repo) .await .context("āŒ Commit command failed") - .map_err(|e| enhance_commit_error(e))?; + .map_err(enhance_commit_error)?; Ok(true) } Some(Commands::Review(review_args)) => { review::handle_review_command(review_args, repo) .await .context("āŒ Review command failed") - .map_err(|e| enhance_review_error(e))?; + .map_err(enhance_review_error)?; Ok(true) } Some(Commands::BranchSummary(branch_args)) => { @@ -111,7 +111,7 @@ pub async fn dispatch_command(args: &Args, repo: &SqliteRepository) -> Result Result Result { stash::handle_stash_command(stash_args, repo) .await .context("āŒ Stash command failed") - .map_err(|e| enhance_stash_error(e))?; + .map_err(enhance_stash_error)?; Ok(true) } Some(Commands::Tag(tag_args)) => { tag::handle_tag_command(tag_args, repo) .await .context("āŒ Tag command failed") - .map_err(|e| enhance_tag_error(e))?; + .map_err(enhance_tag_error)?; Ok(true) } Some(Commands::Rebase(rebase_args)) => { rebase::handle_rebase_command(rebase_args, repo) .await .context("āŒ Rebase command failed") - .map_err(|e| enhance_rebase_error(e))?; + .map_err(enhance_rebase_error)?; Ok(true) } Some(Commands::Conflicts(conflicts_args)) => { conflicts::handle_conflicts_command(conflicts_args, repo) .await .context("āŒ Conflicts command failed") - .map_err(|e| enhance_conflicts_error(e))?; + .map_err(enhance_conflicts_error)?; Ok(true) } Some(Commands::Preset(preset_args)) => { preset::handle_preset_command(preset_args, repo) .await .context("āŒ Preset command failed") - .map_err(|e| enhance_preset_error(e))?; + .map_err(enhance_preset_error)?; Ok(true) } Some(Commands::Completion { @@ -183,7 +183,7 @@ pub async fn dispatch_command(args: &Args, repo: &SqliteRepository) -> Result { @@ -274,7 +274,6 @@ fn print_config(repo: &SqliteRepository) -> Result<()> { } /// Enhanced error handlers that provide actionable guidance messages - fn enhance_setup_error(error: anyhow::Error) -> anyhow::Error { let guidance = format!( "\n{}\n{}\n• {}\n• {}\n• {}", diff --git a/src/commands/preset.rs b/src/commands/preset.rs index 797f82a..5e7ea16 100644 --- a/src/commands/preset.rs +++ b/src/commands/preset.rs @@ -177,10 +177,10 @@ async fn handle_list_presets( }; println!("│ {} │ {} │ {} │ {} │", - format!("{:<19}", name_display).bright_green(), - format!("{:<11}", preset.category).bright_cyan(), - format!("{:<32}", description_truncated), - format!("{:<7}", usage_display).bright_white() + format_args!("{:<19}", name_display).to_string().bright_green(), + format_args!("{:<11}", preset.category).to_string().bright_cyan(), + format_args!("{:<32}", description_truncated), + format_args!("{:<7}", usage_display).to_string().bright_white(), ); } println!("ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜"); @@ -194,6 +194,7 @@ async fn handle_list_presets( } /// Handle using a preset +#[allow(clippy::too_many_arguments)] async fn handle_use_preset( manager: &PresetManager, name: &str, @@ -595,7 +596,7 @@ async fn handle_delete_preset( if !force { use dialoguer::Confirm; if !Confirm::new() - .with_prompt(&format!("Are you sure you want to delete preset '{}'?", name)) + .with_prompt(format!("Are you sure you want to delete preset '{}'?", name)) .default(false) .interact()? { println!("āŒ Cancelled by user."); @@ -657,7 +658,7 @@ async fn handle_edit_preset( use dialoguer::Confirm; if !Confirm::new() - .with_prompt(&format!("Built-in presets cannot be edited directly. Create a custom copy of '{}'?", name)) + .with_prompt(format!("Built-in presets cannot be edited directly. Create a custom copy of '{}'?", name)) .default(true) .interact()? { println!("āŒ Edit cancelled."); @@ -1070,7 +1071,7 @@ fn format_files_for_template(files: &[Files]) -> String { "java" => result.push_str("java"), "kt" => result.push_str("kotlin"), "cpp" | "cc" | "cxx" => result.push_str("cpp"), - "c" => result.push_str("c"), + "c" => result.push('c'), "cs" => result.push_str("csharp"), "php" => result.push_str("php"), "rb" => result.push_str("ruby"), @@ -1093,7 +1094,6 @@ fn format_files_for_template(files: &[Files]) -> String { } /// Helper functions for enhanced preset creation - /// Detect template variables from content using regex fn detect_template_variables(content: &str) -> Vec { use regex::Regex; @@ -1146,7 +1146,7 @@ fn define_template_variables(var_names: &[String]) -> Result Re preset.template.template = new_content; println!("āœ… Template updated via external editor"); - return Ok(true); + Ok(true) } else { println!("ā„¹ļø No template changes made"); - return Ok(false); + Ok(false) } } 1 => { @@ -1371,10 +1371,10 @@ async fn edit_preset_template(preset: &mut crate::preset::manager::Preset) -> Re if new_content != preset.template.template { preset.template.template = new_content; println!("āœ… Template updated"); - return Ok(true); + Ok(true) } else { println!("ā„¹ļø No template changes made"); - return Ok(false); + Ok(false) } } 2 => { @@ -1393,7 +1393,7 @@ async fn edit_preset_template(preset: &mut crate::preset::manager::Preset) -> Re return Box::pin(edit_preset_template(preset)).await; } - return Ok(false); + Ok(false) } _ => Ok(false), } @@ -1469,7 +1469,7 @@ fn edit_preset_variables(preset: &mut crate::preset::manager::Preset) -> Result< continue; } - let vars = define_template_variables(&vec![name.clone()])?; + let vars = define_template_variables(std::slice::from_ref(&name))?; if let Some(var_def) = vars.get(&name) { preset.template.variables.insert(name.clone(), var_def.clone()); println!("āœ… Added variable '{}'", name.bright_green()); @@ -1490,7 +1490,7 @@ fn edit_preset_variables(preset: &mut crate::preset::manager::Preset) -> Result< let var_name = var_names[var_choice].clone(); println!("āœļø Editing variable: {}", var_name.bright_cyan()); - let new_vars = define_template_variables(&vec![var_name.clone()])?; + let new_vars = define_template_variables(std::slice::from_ref(&var_name))?; if let Some(new_var_def) = new_vars.get(&var_name) { preset.template.variables.insert(var_name.clone(), new_var_def.clone()); println!("āœ… Updated variable '{}'", var_name.bright_green()); @@ -1510,7 +1510,7 @@ fn edit_preset_variables(preset: &mut crate::preset::manager::Preset) -> Result< let var_name = var_names[var_choice].clone(); if Confirm::new() - .with_prompt(&format!("Remove variable '{}'?", var_name)) + .with_prompt(format!("Remove variable '{}'?", var_name)) .default(false) .interact()? { diff --git a/src/commands/rebase.rs b/src/commands/rebase.rs index d8fb8bf..8c0e238 100644 --- a/src/commands/rebase.rs +++ b/src/commands/rebase.rs @@ -617,11 +617,9 @@ async fn handle_rebase_conflicts(conflicts: &[String], args: &crate::args::Rebas println!(" • Consider keeping changes from both sides if they're complementary"); println!(" • Test the resolution before continuing"); - let suggestions = vec![ - "Use 'git mergetool' to resolve conflicts interactively", + let suggestions = ["Use 'git mergetool' to resolve conflicts interactively", "After resolving, stage files with 'git add '", - "Continue rebase with 'termai rebase continue'", - ]; + "Continue rebase with 'termai rebase continue'"]; println!("\n{}", "šŸ’” Resolution Steps:".bright_yellow().bold()); for (i, suggestion) in suggestions.iter().enumerate() { @@ -635,12 +633,10 @@ async fn handle_rebase_conflicts(conflicts: &[String], args: &crate::args::Rebas async fn provide_continue_suggestions(_state: &RebaseState) -> Result<()> { println!("\n{}", "šŸ¤– AI Continue Suggestions:".bright_cyan().bold()); - let suggestions = vec![ - "Verify all conflicts have been resolved", + let suggestions = ["Verify all conflicts have been resolved", "Check that tests still pass after conflict resolution", "Review the merged changes for logical consistency", - "Ensure commit messages are still appropriate", - ]; + "Ensure commit messages are still appropriate"]; for (i, suggestion) in suggestions.iter().enumerate() { println!(" {}. {}", (i + 1).to_string().bright_yellow(), suggestion); diff --git a/src/commands/session.rs b/src/commands/session.rs index 9fa33ed..fee50da 100644 --- a/src/commands/session.rs +++ b/src/commands/session.rs @@ -76,13 +76,10 @@ fn delete_session(repo: &SqliteRepository, session_name: &str) -> Result<()> { .context(format!("Session '{}' not found", session_name)) .map_err(|e| { let guidance = format!( - "\n{}\n{}\n• {}\n• {}", + "\n{}\n{}\n• Run '{}' to see available sessions\n• {}", "šŸ’” Session Troubleshooting:".bright_yellow().bold(), " The specified session could not be found.".white(), - format!( - "Run '{}' to see available sessions", - "termai session list".cyan() - ), + "termai session list".cyan(), "Check the session name spelling and try again".white() ); anyhow::anyhow!("{}\n{}", e, guidance) diff --git a/src/commands/stash.rs b/src/commands/stash.rs index 27dda7d..efec5a1 100644 --- a/src/commands/stash.rs +++ b/src/commands/stash.rs @@ -184,8 +184,8 @@ async fn push_stash(git_repo: &GitRepository, args: &crate::args::StashArgs) -> println!(" {}", stash_message.bright_white()); // Confirm stash creation - if args.interactive { - if !Confirm::new() + if args.interactive + && !Confirm::new() .with_prompt("Create stash with this message?") .default(true) .interact()? @@ -193,7 +193,6 @@ async fn push_stash(git_repo: &GitRepository, args: &crate::args::StashArgs) -> println!("{}", "Stash creation cancelled".yellow()); return Ok(()); } - } // Create the stash println!("\n{}", "šŸ”„ Creating stash...".cyan()); @@ -250,16 +249,15 @@ async fn pop_stash(_git_repo: &GitRepository, args: &crate::args::StashArgs) -> ); println!(" {} 5 files will be restored", "šŸ“".cyan()); - if args.interactive { - if !Confirm::new() - .with_prompt(&format!("Apply and remove {}?", stash_ref)) + if args.interactive + && !Confirm::new() + .with_prompt(format!("Apply and remove {}?", stash_ref)) .default(true) .interact()? { println!("{}", "Stash pop cancelled".yellow()); return Ok(()); } - } // Apply the stash println!("\n{}", "šŸ”„ Applying stash changes...".cyan()); @@ -322,7 +320,7 @@ async fn drop_stash(_git_repo: &GitRepository, args: &crate::args::StashArgs) -> if args.interactive || Confirm::new() - .with_prompt(&format!("Are you sure you want to drop {}?", stash_ref)) + .with_prompt(format!("Are you sure you want to drop {}?", stash_ref)) .default(false) .interact()? { @@ -467,11 +465,11 @@ async fn generate_smart_stash_message( .unwrap_or_else(|_| "unknown".to_string()); // Generate message based on changes - let message = if status.staged_files.len() > 0 && status.unstaged_files.len() > 0 { + let message = if !status.staged_files.is_empty() && !status.unstaged_files.is_empty() { "WIP: Mixed staged and unstaged changes" - } else if status.staged_files.len() > 0 { + } else if !status.staged_files.is_empty() { "WIP: Staged changes ready for commit" - } else if status.unstaged_files.len() > 0 { + } else if !status.unstaged_files.is_empty() { "WIP: Unstaged changes in progress" } else { "WIP: Work in progress" diff --git a/src/commands/tag.rs b/src/commands/tag.rs index a1c09cf..0eeeda8 100644 --- a/src/commands/tag.rs +++ b/src/commands/tag.rs @@ -313,7 +313,7 @@ async fn delete_tag(_git_repo: &GitRepository, args: &crate::args::TagArgs) -> R println!(" If the tag is pushed to remote, you'll need to delete it there too"); if !Confirm::new() - .with_prompt(&format!( + .with_prompt(format!( "Are you sure you want to delete tag '{}'?", tag_name )) @@ -368,7 +368,7 @@ async fn show_tag(_git_repo: &GitRepository, args: &crate::args::TagArgs) -> Res println!("\n{}", "šŸ’­ Tag Message:".bright_cyan().bold()); println!(" feat: major feature update with OAuth2 support"); - println!(""); + println!(); println!(" This release includes:"); println!(" - OAuth2 authentication integration"); println!(" - Performance improvements"); @@ -491,8 +491,6 @@ async fn suggest_next_tag(_git_repo: &GitRepository) -> Result<()> { "v2.0.0" } else if analysis.new_features { "v1.3.0" - } else if analysis.bug_fixes { - "v1.2.1" } else { "v1.2.1" }; diff --git a/src/config/project.rs b/src/config/project.rs index 17dbd67..c0d8314 100644 --- a/src/config/project.rs +++ b/src/config/project.rs @@ -194,14 +194,10 @@ impl ProjectConfigService { /// Extract repository name from git URL fn extract_repo_name_from_url(&self, url: &str) -> Option { // Handle different URL formats - let clean_url = if url.ends_with(".git") { - &url[..url.len() - 4] - } else { - url - }; + let clean_url = url.strip_suffix(".git").unwrap_or(url); // Extract last part of path - clean_url.split('/').last().map(|s| s.to_string()) + clean_url.split('/').next_back().map(|s| s.to_string()) } /// Get default context configuration for project type diff --git a/src/config/service/claude_config.rs b/src/config/service/claude_config.rs index 47256a4..1df7c96 100644 --- a/src/config/service/claude_config.rs +++ b/src/config/service/claude_config.rs @@ -6,7 +6,7 @@ use anyhow::Result; pub fn write_claude_key(repo: &R, claude_api_key: &Args) -> Result<()> { if let Some(ref claude_api_key) = claude_api_key.claude_api_key { - config_service::write_config(repo, &ConfigKeys::ClaudeApiKey.to_key(), &claude_api_key) + config_service::write_config(repo, &ConfigKeys::ClaudeApiKey.to_key(), claude_api_key) } else { Ok(()) } diff --git a/src/config/service/config_service.rs b/src/config/service/config_service.rs index 9cc2bf6..f579299 100644 --- a/src/config/service/config_service.rs +++ b/src/config/service/config_service.rs @@ -5,10 +5,7 @@ use crate::config::repository::ConfigRepository; use anyhow::{anyhow, Result}; pub fn write_config(repo: &R, key: &str, value: &str) -> Result<()> { - let config = match repo.fetch_by_key(key) { - Ok(config) => Some(config), - Err(_) => None, - }; + let config = repo.fetch_by_key(key).ok(); let _ = match config { Some(c) => repo.update_config(c.id.unwrap_or_default(), key, value), diff --git a/src/config/service/open_ai_config.rs b/src/config/service/open_ai_config.rs index a9e46e8..9f11a54 100644 --- a/src/config/service/open_ai_config.rs +++ b/src/config/service/open_ai_config.rs @@ -6,7 +6,7 @@ use anyhow::Result; pub fn write_open_ai_key(repo: &R, chat_gpt_api_key: &Args) -> Result<()> { if let Some(ref chat_gpt_api_key) = chat_gpt_api_key.chat_gpt_api_key { - config_service::write_config(repo, &ConfigKeys::ChatGptApiKey.to_key(), &chat_gpt_api_key) + config_service::write_config(repo, &ConfigKeys::ChatGptApiKey.to_key(), chat_gpt_api_key) } else { Ok(()) } diff --git a/src/context/analyzer.rs b/src/context/analyzer.rs index 7b6d12f..2defb47 100644 --- a/src/context/analyzer.rs +++ b/src/context/analyzer.rs @@ -192,7 +192,7 @@ impl FileAnalyzer { }; // Normalize score to 0-1 range - let relevance_score = (base_score / 10.0_f32).min(1.0).max(0.0); + let relevance_score = (base_score / 10.0_f32).clamp(0.0, 1.0); Ok(FileScore { path: path.to_string_lossy().to_string(), @@ -207,7 +207,7 @@ impl FileAnalyzer { /// Determine the type of a file based on extension and name fn determine_file_type(&self, path: &Path) -> FileType { if let Some(extension) = path.extension().and_then(|ext| ext.to_str()) { - if let Some(&ref file_type) = self.extension_map.get(extension) { + if let Some(file_type) = self.extension_map.get(extension) { return file_type.clone(); } } @@ -311,8 +311,8 @@ impl FileAnalyzer { let ref_count = reference_counts.get(file_path).unwrap_or(&0); // High reference count indicates an important file - if *ref_count >= 3 { - if !file_score + if *ref_count >= 3 + && !file_score .importance_factors .contains(&ImportanceFactor::HighlyReferenced) { @@ -321,7 +321,6 @@ impl FileAnalyzer { .push(ImportanceFactor::HighlyReferenced); file_score.relevance_score = (file_score.relevance_score + 0.3).min(1.0); } - } // Files that others depend on but have few dependencies themselves (root files) if *ref_count >= 2 { @@ -329,8 +328,8 @@ impl FileAnalyzer { .get(file_path) .map(|deps| deps.len()) .unwrap_or(0); - if own_deps <= 1 { - if !file_score + if own_deps <= 1 + && !file_score .importance_factors .contains(&ImportanceFactor::DependencyRoot) { @@ -339,7 +338,6 @@ impl FileAnalyzer { .push(ImportanceFactor::DependencyRoot); file_score.relevance_score = (file_score.relevance_score + 0.2).min(1.0); } - } } } diff --git a/src/context/chunker.rs b/src/context/chunker.rs index fd26650..d33fba3 100644 --- a/src/context/chunker.rs +++ b/src/context/chunker.rs @@ -160,7 +160,7 @@ impl ContextChunker { "root".to_string() }; - modules.entry(module).or_insert_with(Vec::new).push(file); + modules.entry(module).or_default().push(file); } // Create chunks for each module diff --git a/src/context/config.rs b/src/context/config.rs index f91aed3..ca8756b 100644 --- a/src/context/config.rs +++ b/src/context/config.rs @@ -90,15 +90,15 @@ impl ContextConfig { /// Get project type from configuration pub fn get_project_type(&self) -> Option { self.project.as_ref().and_then(|p| { - p.project_type.as_ref().and_then(|t| match t.as_str() { - "rust" => Some(ProjectType::Rust), - "javascript" | "js" | "typescript" | "ts" => Some(ProjectType::JavaScript), - "python" | "py" => Some(ProjectType::Python), - "go" | "golang" => Some(ProjectType::Go), - "kotlin" | "kt" => Some(ProjectType::Kotlin), - "java" => Some(ProjectType::Java), - "git" => Some(ProjectType::Git), - _ => Some(ProjectType::Generic), + p.project_type.as_ref().map(|t| match t.as_str() { + "rust" => ProjectType::Rust, + "javascript" | "js" | "typescript" | "ts" => ProjectType::JavaScript, + "python" | "py" => ProjectType::Python, + "go" | "golang" => ProjectType::Go, + "kotlin" | "kt" => ProjectType::Kotlin, + "java" => ProjectType::Java, + "git" => ProjectType::Git, + _ => ProjectType::Generic, }) }) } diff --git a/src/context/detector.rs b/src/context/detector.rs index 0dbb5b4..8f6b23f 100644 --- a/src/context/detector.rs +++ b/src/context/detector.rs @@ -230,9 +230,9 @@ impl ProjectDetector for GoProjectDetector { path.join(dir) }; if dir_path.exists() { - dir_path.read_dir().map_or(false, |mut entries| { + dir_path.read_dir().is_ok_and(|mut entries| { entries.any(|entry| { - entry.map_or(false, |e| { + entry.is_ok_and(|e| { e.path().extension().and_then(|ext| ext.to_str()) == Some("go") }) }) @@ -263,7 +263,7 @@ impl ProjectDetector for GoProjectDetector { // Handle wildcard patterns like cmd/*/main.go if let Ok(entries) = path.join("cmd").read_dir() { for dir_entry in entries.flatten() { - if dir_entry.file_type().map_or(false, |ft| ft.is_dir()) { + if dir_entry.file_type().is_ok_and(|ft| ft.is_dir()) { let main_path = dir_entry.path().join("main.go"); if main_path.exists() { let relative_path = format!( @@ -549,7 +549,7 @@ impl JavaProjectDetector { if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) { if file_name.contains("Application") && file_name.ends_with(".java") { if let Ok(relative) = - path.strip_prefix(&std::env::current_dir().unwrap_or_default()) + path.strip_prefix(std::env::current_dir().unwrap_or_default()) { let relative_str = relative.to_string_lossy().to_string(); entry_points.push(relative_str.clone()); diff --git a/src/context/mod.rs b/src/context/mod.rs index 065276c..eaf8689 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -223,7 +223,7 @@ impl SmartContext { if path .file_name() .and_then(|name| name.to_str()) - .map_or(false, |name| name.starts_with('.')) + .is_some_and(|name| name.starts_with('.')) { // Allow if explicitly in include patterns if !self diff --git a/src/context/multi_session.rs b/src/context/multi_session.rs index 5646e12..9fe69e0 100644 --- a/src/context/multi_session.rs +++ b/src/context/multi_session.rs @@ -143,7 +143,7 @@ impl MultiSessionManager { let total_files: usize = self.chunks.iter().map(|c| c.files.len()).sum(); let total_tokens: usize = self.chunks.iter().map(|c| c.estimated_tokens).sum(); - summary.push_str(&format!("šŸ“Š **Statistics**\n")); + summary.push_str("šŸ“Š **Statistics**\n"); summary.push_str(&format!( " • Total chunks analyzed: {}\n", self.chunks.len() diff --git a/src/context/template_manager.rs b/src/context/template_manager.rs index fa18e38..a684729 100644 --- a/src/context/template_manager.rs +++ b/src/context/template_manager.rs @@ -180,19 +180,19 @@ impl TemplateManager { config_example.push_str(&format!("max_tokens = {}\n", max_tokens)); } - config_example.push_str(&format!("include = [\n")); + config_example.push_str("include = [\n"); for pattern in &template.include_patterns { config_example.push_str(&format!(" \"{}\",\n", pattern)); } config_example.push_str("]\n\n"); - config_example.push_str(&format!("exclude = [\n")); + config_example.push_str("exclude = [\n"); for pattern in &template.exclude_patterns { config_example.push_str(&format!(" \"{}\",\n", pattern)); } config_example.push_str("]\n\n"); - config_example.push_str(&format!("priority_patterns = [\n")); + config_example.push_str("priority_patterns = [\n"); for pattern in &template.priority_patterns { config_example.push_str(&format!(" \"{}\",\n", pattern)); } diff --git a/src/context/templates.rs b/src/context/templates.rs index 19a3bc0..12e485b 100644 --- a/src/context/templates.rs +++ b/src/context/templates.rs @@ -18,6 +18,7 @@ pub struct ContextTemplate { } impl ContextTemplate { + #[allow(clippy::too_many_arguments)] pub fn new( name: String, description: String, diff --git a/src/discovery.rs b/src/discovery.rs index 270a99f..fbead32 100644 --- a/src/discovery.rs +++ b/src/discovery.rs @@ -416,7 +416,7 @@ impl CommandDiscovery { // Check git status if let Ok(output) = std::process::Command::new("git") - .args(&["status", "--porcelain"]) + .args(["status", "--porcelain"]) .output() { if !output.stdout.is_empty() { diff --git a/src/git/diff.rs b/src/git/diff.rs index 9759b5d..79dfe82 100644 --- a/src/git/diff.rs +++ b/src/git/diff.rs @@ -534,14 +534,13 @@ impl DiffSummary { if let Some(path) = &file.new_path { if let Some(extension) = path.extension().and_then(|e| e.to_str()) { // Public API files that might indicate breaking changes - if matches!(extension, "rs" | "ts" | "js" | "py" | "go" | "java") { - if path.to_string_lossy().contains("lib") + if matches!(extension, "rs" | "ts" | "js" | "py" | "go" | "java") + && (path.to_string_lossy().contains("lib") || path.to_string_lossy().contains("api") - || path.to_string_lossy().contains("public") + || path.to_string_lossy().contains("public")) { return true; } - } } } } diff --git a/src/git/hooks.rs b/src/git/hooks.rs index 323c2d3..f57cfb3 100644 --- a/src/git/hooks.rs +++ b/src/git/hooks.rs @@ -57,7 +57,7 @@ impl HookManager { } // Backup existing hook - let backup_path = hook_path.with_extension(&format!("{}.backup", hook_name)); + let backup_path = hook_path.with_extension(format!("{}.backup", hook_name)); fs::copy(&hook_path, &backup_path).context("Failed to backup existing hook")?; println!( "{}", @@ -115,10 +115,10 @@ impl HookManager { fs::remove_file(&hook_path).context("Failed to remove hook")?; // Restore backup if exists - let backup_path = hook_path.with_extension(&format!("{}.backup", hook_name)); + let backup_path = hook_path.with_extension(format!("{}.backup", hook_name)); if backup_path.exists() { fs::rename(&backup_path, &hook_path).context("Failed to restore backup hook")?; - println!("{}", format!("šŸ“‹ Restored backup hook").green()); + println!("{}", "šŸ“‹ Restored backup hook".to_string().green()); } println!( @@ -140,7 +140,7 @@ impl HookManager { }; let backup_path = - hook_path.with_extension(&format!("{}.backup", self.hook_type_to_name(&hook_type))); + hook_path.with_extension(format!("{}.backup", self.hook_type_to_name(&hook_type))); let existing_hook = backup_path.exists(); Ok(HookStatus { @@ -293,8 +293,7 @@ exit 0 termai_path ), - HookType::CommitMsg => format!( - r#"#!/bin/bash + HookType::CommitMsg => r#"#!/bin/bash # TermAI Git Hook - Commit Message # This hook validates and can enhance commit messages @@ -313,8 +312,7 @@ else fi exit 0 -"# - ), +"#.to_string(), HookType::PrePush => format!( r#"#!/bin/bash @@ -340,8 +338,7 @@ exit 0 termai_path ), - HookType::PostCommit => format!( - r#"#!/bin/bash + HookType::PostCommit => r#"#!/bin/bash # TermAI Git Hook - Post-commit # This hook provides post-commit insights and suggestions @@ -360,8 +357,7 @@ echo " Message: $commit_msg" echo "šŸ’” Tip: Use 'termai branch-summary' to analyze your branch" exit 0 -"# - ), +"#.to_string(), }; Ok(script) diff --git a/src/git/mod.rs b/src/git/mod.rs index 94055c4..119048a 100644 --- a/src/git/mod.rs +++ b/src/git/mod.rs @@ -13,7 +13,6 @@ pub mod hooks; /// - Code review functionality /// - Hook management /// - Interactive workflows - #[allow(dead_code)] pub mod repository; #[allow(dead_code)] diff --git a/src/llm/common/model/role.rs b/src/llm/common/model/role.rs index fae72cb..57ec4e1 100644 --- a/src/llm/common/model/role.rs +++ b/src/llm/common/model/role.rs @@ -14,12 +14,15 @@ impl Role { _ => Role::User, } } +} - pub fn to_string(&self) -> String { - match self { - Role::System => "system".to_string(), - Role::User => "user".to_string(), - Role::Assistant => "assistant".to_string(), - } +impl std::fmt::Display for Role { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Role::System => "system", + Role::User => "user", + Role::Assistant => "assistant", + }; + write!(f, "{}", s) } } diff --git a/src/llm/openai/adapter/gpt5_adapter.rs b/src/llm/openai/adapter/gpt5_adapter.rs index 4f5c163..bd7fd3f 100644 --- a/src/llm/openai/adapter/gpt5_adapter.rs +++ b/src/llm/openai/adapter/gpt5_adapter.rs @@ -22,7 +22,6 @@ impl Gpt5Adapter { } /// Chat Completions API removed - migrated to Responses API - /// Call the new Responses API (preferred for GPT-5) /// Optimized for reasoning models with better caching and performance pub async fn responses( @@ -103,9 +102,9 @@ impl Gpt5Adapter { response.output.iter() .find_map(|output| match output { crate::llm::openai::model::responses_api::ResponseOutput::Message { content, .. } => { - content.iter().find_map(|item| match item { - crate::llm::openai::model::responses_api::ContentItem::OutputText { text, .. } => Some(text.clone()), - }) + content.iter().map(|item| match item { + crate::llm::openai::model::responses_api::ContentItem::OutputText { text, .. } => text.clone(), + }).next() } _ => None, }) diff --git a/src/llm/openai/config/gpt5_config.rs b/src/llm/openai/config/gpt5_config.rs index 1af5970..44cf594 100644 --- a/src/llm/openai/config/gpt5_config.rs +++ b/src/llm/openai/config/gpt5_config.rs @@ -129,8 +129,8 @@ impl Gpt5Config { pub fn describe(&self) -> String { format!( "GPT-5 Config: reasoning={}, verbosity={}, api={}, preambles={}, storage={}, zdr={}", - self.reasoning_effort.to_string(), - self.verbosity.to_string(), + self.reasoning_effort, + self.verbosity, if self.prefer_responses_api { "responses" } else { "chat" }, self.preambles.enabled, self.store_conversations, diff --git a/src/llm/openai/model/codex_api.rs b/src/llm/openai/model/codex_api.rs index 90635d7..a6967e0 100644 --- a/src/llm/openai/model/codex_api.rs +++ b/src/llm/openai/model/codex_api.rs @@ -163,8 +163,8 @@ impl CodexResponse { if let CodexOutput::Message { content, .. } = output { let texts: Vec = content .iter() - .filter_map(|item| match item { - CodexContentItem::OutputText { text, .. } => Some(text.clone()), + .map(|item| match item { + CodexContentItem::OutputText { text, .. } => text.clone(), }) .collect(); if !texts.is_empty() { diff --git a/src/llm/openai/model/custom_tools.rs b/src/llm/openai/model/custom_tools.rs index 53d8a38..b33796d 100644 --- a/src/llm/openai/model/custom_tools.rs +++ b/src/llm/openai/model/custom_tools.rs @@ -109,6 +109,7 @@ impl AllowedToolReference { /// Preamble configuration for tool calls #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Default)] pub struct PreambleConfig { /// Whether to enable preambles (explanations before tool calls) pub enabled: bool, @@ -117,14 +118,6 @@ pub struct PreambleConfig { pub instruction: Option, } -impl Default for PreambleConfig { - fn default() -> Self { - Self { - enabled: false, - instruction: None, - } - } -} #[allow(dead_code)] impl PreambleConfig { diff --git a/src/llm/openai/model/mod.rs b/src/llm/openai/model/mod.rs index 5640b03..17b9f2e 100644 --- a/src/llm/openai/model/mod.rs +++ b/src/llm/openai/model/mod.rs @@ -4,6 +4,7 @@ pub(crate) mod custom_tools; pub(crate) mod choice; pub(crate) mod completion_token_details; pub(crate) mod message_content; +#[allow(clippy::module_inception)] pub(crate) mod model; pub(crate) mod models_api; pub(crate) mod reasoning_effort; diff --git a/src/llm/openai/model/model.rs b/src/llm/openai/model/model.rs index 74adb4d..1f96e4e 100644 --- a/src/llm/openai/model/model.rs +++ b/src/llm/openai/model/model.rs @@ -46,49 +46,50 @@ pub enum Model { Davinci002, } -impl Model { - pub fn to_string(&self) -> String { - match self { - Model::Gpt53Codex => "gpt-5.3-codex".to_owned(), - Model::Gpt5 => "gpt-5.2".to_owned(), - Model::Gpt5Mini => "gpt-5-mini".to_owned(), - Model::Gpt5Nano => "gpt-5-nano".to_owned(), - Model::Gpt4o => "gpt-4o".to_owned(), - Model::Gpt4oMini => "gpt-4o-mini".to_owned(), - Model::Gpt4Turbo => "gpt-4-turbo".to_owned(), - Model::Gpt4 => "gpt-4".to_owned(), - Model::Gpt35Turbo => "gpt-3.5-turbo".to_owned(), - Model::DallE2 => "dall-e-2".to_owned(), - Model::DallE3 => "dall-e-3".to_owned(), - Model::Tts1 => "tts-1".to_owned(), - Model::Tts1Hd => "tts-1-hd".to_owned(), - Model::Whisper1 => "whisper-1".to_owned(), - Model::WhisperV2Large => "whisper-v2-large".to_owned(), - Model::TextEmbedding3Large => "text-embedding-3-large".to_owned(), - Model::TextEmbedding3Small => "text-embedding-3-small".to_owned(), - Model::TextEmbeddingAda002 => "text-embedding-ada-002".to_owned(), - Model::OmniModerationLatest => "omni-moderation-latest".to_owned(), - Model::TextModerationLatest => "text-moderation-latest".to_owned(), - Model::TextModerationStable => "text-moderation-stable".to_owned(), - Model::TextModeration007 => "text-moderation-007".to_owned(), - Model::O1Preview => "o1-preview".to_owned(), - Model::O1Mini => "o1-mini".to_owned(), - Model::O1 => "o1".to_owned(), - Model::O3Mini => "o3-mini".to_owned(), - Model::Gpt4oRealtimePreview => "gpt-4o-realtime-preview".to_owned(), - Model::Gpt4o20240806 => "gpt-4o-2024-08-06".to_owned(), - Model::Gpt4o20240513 => "gpt-4o-2024-05-13".to_owned(), - Model::Gpt4oMini20240718 => "gpt-4o-mini-2024-07-18".to_owned(), - Model::Gpt4Turbo20240409 => "gpt-4-turbo-2024-04-09".to_owned(), - Model::Gpt4TurboPreview => "gpt-4-turbo-preview".to_owned(), - Model::Gpt4Preview => "gpt-4-0125-preview".to_owned(), - Model::Gpt4_0613 => "gpt-4-0613".to_owned(), - Model::Gpt4_0314 => "gpt-4-0314".to_owned(), - Model::Gpt35Turbo0125 => "gpt-3.5-turbo-0125".to_owned(), - Model::Gpt35Turbo1106 => "gpt-3.5-turbo-1106".to_owned(), - Model::Gpt35TurboInstruct => "gpt-3.5-turbo-instruct".to_owned(), - Model::Babbage002 => "babbage-002".to_owned(), - Model::Davinci002 => "davinci-002".to_owned(), - } +impl std::fmt::Display for Model { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Model::Gpt53Codex => "gpt-5.3-codex", + Model::Gpt5 => "gpt-5.2", + Model::Gpt5Mini => "gpt-5-mini", + Model::Gpt5Nano => "gpt-5-nano", + Model::Gpt4o => "gpt-4o", + Model::Gpt4oMini => "gpt-4o-mini", + Model::Gpt4Turbo => "gpt-4-turbo", + Model::Gpt4 => "gpt-4", + Model::Gpt35Turbo => "gpt-3.5-turbo", + Model::DallE2 => "dall-e-2", + Model::DallE3 => "dall-e-3", + Model::Tts1 => "tts-1", + Model::Tts1Hd => "tts-1-hd", + Model::Whisper1 => "whisper-1", + Model::WhisperV2Large => "whisper-v2-large", + Model::TextEmbedding3Large => "text-embedding-3-large", + Model::TextEmbedding3Small => "text-embedding-3-small", + Model::TextEmbeddingAda002 => "text-embedding-ada-002", + Model::OmniModerationLatest => "omni-moderation-latest", + Model::TextModerationLatest => "text-moderation-latest", + Model::TextModerationStable => "text-moderation-stable", + Model::TextModeration007 => "text-moderation-007", + Model::O1Preview => "o1-preview", + Model::O1Mini => "o1-mini", + Model::O1 => "o1", + Model::O3Mini => "o3-mini", + Model::Gpt4oRealtimePreview => "gpt-4o-realtime-preview", + Model::Gpt4o20240806 => "gpt-4o-2024-08-06", + Model::Gpt4o20240513 => "gpt-4o-2024-05-13", + Model::Gpt4oMini20240718 => "gpt-4o-mini-2024-07-18", + Model::Gpt4Turbo20240409 => "gpt-4-turbo-2024-04-09", + Model::Gpt4TurboPreview => "gpt-4-turbo-preview", + Model::Gpt4Preview => "gpt-4-0125-preview", + Model::Gpt4_0613 => "gpt-4-0613", + Model::Gpt4_0314 => "gpt-4-0314", + Model::Gpt35Turbo0125 => "gpt-3.5-turbo-0125", + Model::Gpt35Turbo1106 => "gpt-3.5-turbo-1106", + Model::Gpt35TurboInstruct => "gpt-3.5-turbo-instruct", + Model::Babbage002 => "babbage-002", + Model::Davinci002 => "davinci-002", + }; + write!(f, "{}", s) } } diff --git a/src/llm/openai/model/verbosity.rs b/src/llm/openai/model/verbosity.rs index 5803825..a530562 100644 --- a/src/llm/openai/model/verbosity.rs +++ b/src/llm/openai/model/verbosity.rs @@ -4,20 +4,17 @@ use serde::{Serialize, Deserialize}; /// Determines how many output tokens are generated #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[serde(rename_all = "lowercase")] +#[derive(Default)] pub enum Verbosity { /// Concise answers, minimal commentary Low, /// Balanced explanations (default) + #[default] Medium, /// Thorough explanations and extensive details High, } -impl Default for Verbosity { - fn default() -> Self { - Verbosity::Medium - } -} #[allow(dead_code)] impl Verbosity { @@ -30,14 +27,6 @@ impl Verbosity { } } - pub fn to_string(&self) -> String { - match self { - Verbosity::Low => "low".to_string(), - Verbosity::Medium => "medium".to_string(), - Verbosity::High => "high".to_string(), - } - } - /// Returns a description of what this verbosity level does pub fn description(&self) -> &'static str { match self { @@ -46,4 +35,15 @@ impl Verbosity { Verbosity::High => "Thorough explanations and extensive details", } } +} + +impl std::fmt::Display for Verbosity { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Verbosity::Low => "low", + Verbosity::Medium => "medium", + Verbosity::High => "high", + }; + write!(f, "{}", s) + } } \ No newline at end of file diff --git a/src/llm/openai/service/chat.rs b/src/llm/openai/service/chat.rs index e3c03ea..f159f4b 100644 --- a/src/llm/openai/service/chat.rs +++ b/src/llm/openai/service/chat.rs @@ -268,8 +268,8 @@ async fn finish_without_tools(api_key: &str, session: &mut Session, model: &Mode fn extract_text_from_content(content: Vec) -> String { content .into_iter() - .filter_map(|item| match item { - ContentItem::OutputText { text, .. } => Some(text), + .map(|item| match item { + ContentItem::OutputText { text, .. } => text, }) .collect::>() .join("\n") diff --git a/src/llm/openai/service/codex.rs b/src/llm/openai/service/codex.rs index dad8fe2..89e1917 100644 --- a/src/llm/openai/service/codex.rs +++ b/src/llm/openai/service/codex.rs @@ -107,8 +107,8 @@ pub async fn chat(access_token: &str, session: &mut Session, model_param: Option fn extract_text_from_content(content: Vec) -> String { content .into_iter() - .filter_map(|item| match item { - CodexContentItem::OutputText { text, .. } => Some(text), + .map(|item| match item { + CodexContentItem::OutputText { text, .. } => text, }) .collect::>() .join("\n") diff --git a/src/llm/openai/tools/executor.rs b/src/llm/openai/tools/executor.rs index 5b4fb9e..4886217 100644 --- a/src/llm/openai/tools/executor.rs +++ b/src/llm/openai/tools/executor.rs @@ -85,7 +85,7 @@ impl ToolExecutor { } if !stderr.is_empty() { if !result.is_empty() { - result.push_str("\n"); + result.push('\n'); } result.push_str("[stderr]\n"); result.push_str(&stderr); diff --git a/src/main.rs b/src/main.rs index 914b0b9..c4add3b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -145,7 +145,6 @@ fn db_path() -> Result { } /// Enhanced error handlers for main initialization - fn enhance_database_path_error(error: anyhow::Error) -> anyhow::Error { let guidance = format!( "\n{}\n{}\n• {}\n• {}\n• {}", diff --git a/src/manpage.rs b/src/manpage.rs index 75a822e..89212f6 100644 --- a/src/manpage.rs +++ b/src/manpage.rs @@ -237,9 +237,9 @@ COPYRIGHT: ]; for candidate in &candidates { - let expanded = if candidate.starts_with("~/") { + let expanded = if let Some(rest) = candidate.strip_prefix("~/") { if let Some(home) = std::env::var_os("HOME") { - std::path::Path::new(&home).join(&candidate[2..]) + std::path::Path::new(&home).join(rest) } else { continue; } @@ -247,7 +247,7 @@ COPYRIGHT: std::path::PathBuf::from(candidate) }; - if expanded.parent().map_or(false, |p| p.exists()) { + if expanded.parent().is_some_and(|p| p.exists()) { return Some(expanded); } } diff --git a/src/output/export.rs b/src/output/export.rs index 22efc29..31e1e5d 100644 --- a/src/output/export.rs +++ b/src/output/export.rs @@ -3,7 +3,6 @@ use serde_json::Value; use std::fs; use std::path::Path; use comrak::{markdown_to_html, ComrakOptions}; -use chrono; use crate::llm::common::model::role::Role; use crate::session::model::session::Session; @@ -352,7 +351,7 @@ impl ConversationExporter { content.push_str(&format!(" - {}", chrono::Local::now().format("%Y-%m-%d %H:%M:%S"))); } - content.push_str("\n"); + content.push('\n'); // Convert markdown code blocks to plain text let plain_content = self.markdown_to_plain_text(&message.content); diff --git a/src/output/streaming.rs b/src/output/streaming.rs index 72ff0f0..11bae2a 100644 --- a/src/output/streaming.rs +++ b/src/output/streaming.rs @@ -111,6 +111,7 @@ impl StreamingRenderer { } /// Stream code block with enhanced formatting + #[allow(clippy::type_complexity)] pub async fn stream_code_block( &mut self, content: &str, @@ -376,8 +377,10 @@ async fn stream_markdown_content( i += 1; } - if first_content && role_prefix.is_some() { - print!("{}", role_prefix.unwrap()); + if first_content { + if let Some(prefix) = role_prefix { + print!("{}", prefix); + } first_content = false; } diff --git a/src/output/syntax.rs b/src/output/syntax.rs index 26d16a1..71a2fc0 100644 --- a/src/output/syntax.rs +++ b/src/output/syntax.rs @@ -152,7 +152,7 @@ impl SyntaxHighlighter { } // Try exact match - if let Some(syntax) = self.syntax_set.find_syntax_by_name(&name) { + if let Some(syntax) = self.syntax_set.find_syntax_by_name(name) { return Some(syntax); } @@ -282,12 +282,11 @@ impl SyntaxHighlighter { } // JSON pattern - if (code_sample.trim().starts_with('{') && code_sample.trim().ends_with('}')) || - (code_sample.trim().starts_with('[') && code_sample.trim().ends_with(']')) { - if code_sample.contains("\":") && code_sample.contains(",") { + if ((code_sample.trim().starts_with('{') && code_sample.trim().ends_with('}')) || + (code_sample.trim().starts_with('[') && code_sample.trim().ends_with(']'))) + && code_sample.contains("\":") && code_sample.contains(",") { return self.syntax_set.find_syntax_by_name("JSON"); } - } // YAML patterns if code_sample.contains("---") || @@ -397,11 +396,7 @@ impl SyntaxHighlighter { let non_empty_lines = lines.iter().filter(|line| !line.trim().is_empty()).count(); let comment_lines = self.count_comment_lines(&lines, language); - let estimated_lang = if let Some(detected) = self.detect_language(code, language) { - Some(detected.name.clone()) - } else { - None - }; + let estimated_lang = self.detect_language(code, language).map(|detected| detected.name.clone()); CodeAnalysis { total_lines, diff --git a/src/path/extract.rs b/src/path/extract.rs index 5e29989..5f311d7 100644 --- a/src/path/extract.rs +++ b/src/path/extract.rs @@ -127,12 +127,11 @@ pub async fn smart_extract_content_with_preview( std::io::Write::flush(&mut std::io::stdout()).unwrap(); let mut input = String::new(); - if std::io::stdin().read_line(&mut input).is_ok() { - if !input.trim().to_lowercase().starts_with('y') { + if std::io::stdin().read_line(&mut input).is_ok() + && !input.trim().to_lowercase().starts_with('y') { println!("Smart context selection cancelled. Using manual extraction fallback."); return extract_content(&Some(".".to_string()), &[], exclude); } - } } // Convert to Files format and return @@ -162,6 +161,7 @@ pub async fn smart_extract_content( /// Enhanced extract_content that can optionally use smart context discovery #[allow(dead_code)] +#[allow(clippy::too_many_arguments)] pub async fn extract_content_with_smart_fallback( dir: &Option, dirs: &[String], @@ -304,8 +304,8 @@ pub async fn smart_extract_with_chunking( std::io::Write::flush(&mut std::io::stdout()).unwrap(); let mut input = String::new(); - if std::io::stdin().read_line(&mut input).is_ok() { - if input.trim().to_lowercase().starts_with('n') { + if std::io::stdin().read_line(&mut input).is_ok() + && input.trim().to_lowercase().starts_with('n') { println!("Chunked analysis cancelled. Using regular smart context with truncation."); if let Ok(selected_scores) = smart_context.optimizer.optimize_files(&filtered_scores) @@ -317,7 +317,6 @@ pub async fn smart_extract_with_chunking( } } } - } } // Return the first chunk (usually Overview) to start the conversation @@ -344,11 +343,10 @@ pub async fn smart_extract_with_chunking( std::io::Write::flush(&mut std::io::stdout()).unwrap(); let mut input = String::new(); - if std::io::stdin().read_line(&mut input).is_ok() { - if !input.trim().to_lowercase().starts_with('y') { + if std::io::stdin().read_line(&mut input).is_ok() + && !input.trim().to_lowercase().starts_with('y') { return extract_content(&Some(".".to_string()), &[], exclude); } - } } if let Ok(files) = smart_context.scores_to_files(&selected_scores).await { diff --git a/src/preset/manager.rs b/src/preset/manager.rs index ad19883..daa069e 100644 --- a/src/preset/manager.rs +++ b/src/preset/manager.rs @@ -26,6 +26,7 @@ pub struct Preset { /// Configuration options for preset execution #[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Default)] pub struct PresetConfig { /// Preferred AI provider pub provider: Option, @@ -39,17 +40,6 @@ pub struct PresetConfig { pub session: Option, } -impl Default for PresetConfig { - fn default() -> Self { - Self { - provider: None, - max_tokens: None, - temperature: None, - smart_context: None, - session: None, - } - } -} /// Manager for preset operations pub struct PresetManager { @@ -127,7 +117,7 @@ impl PresetManager { let entry = entry?; let path = entry.path(); - if path.is_file() && path.extension().map_or(false, |ext| ext == "yaml" || ext == "yml") { + if path.is_file() && path.extension().is_some_and(|ext| ext == "yaml" || ext == "yml") { match self.load_preset_info(&path) { Ok(mut info) => { info.is_builtin = is_builtin; diff --git a/src/preset/mod.rs b/src/preset/mod.rs index 73b042b..b5d1cae 100644 --- a/src/preset/mod.rs +++ b/src/preset/mod.rs @@ -1,5 +1,4 @@ /// Template and preset system for reusable AI interactions - pub mod template; pub mod manager; pub mod variables; diff --git a/src/session/entity/smart_context_entity.rs b/src/session/entity/smart_context_entity.rs index 8e79f2d..243d7e8 100644 --- a/src/session/entity/smart_context_entity.rs +++ b/src/session/entity/smart_context_entity.rs @@ -23,6 +23,7 @@ pub struct SmartContextEntity { impl SmartContextEntity { #[allow(dead_code)] + #[allow(clippy::too_many_arguments)] pub fn new( id: String, session_id: String, diff --git a/src/session/model/message.rs b/src/session/model/message.rs index 5c22ff1..793dfd7 100644 --- a/src/session/model/message.rs +++ b/src/session/model/message.rs @@ -5,8 +5,10 @@ use crate::session::entity::message_entity::MessageEntity; /// Type of message - standard text or compacted history #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Default)] pub enum MessageType { /// Standard text message + #[default] Standard, /// Compacted conversation history from OpenAI Compaction { @@ -17,11 +19,6 @@ pub enum MessageType { }, } -impl Default for MessageType { - fn default() -> Self { - MessageType::Standard - } -} #[derive(Clone, Debug)] pub struct Message { @@ -128,14 +125,14 @@ impl Message { } #[allow(dead_code)] -pub fn contains_system_prompt(messages: &Vec) -> bool { +pub fn contains_system_prompt(messages: &[Message]) -> bool { messages.iter().any(|m| m.role == Role::System) } #[allow(dead_code)] pub fn messages_with_system_prompt( user_prompt: Option, - messages: &Vec, + messages: &[Message], ) -> Vec { let mut new_messages = Vec::with_capacity(messages.len() + 1); let system_prompt = user_prompt.unwrap_or_else(|| SYSTEM_PROMPT.to_string()); diff --git a/src/session/model/session.rs b/src/session/model/session.rs index f2db57f..1daa98a 100644 --- a/src/session/model/session.rs +++ b/src/session/model/session.rs @@ -58,8 +58,8 @@ impl Session { Self { id: self.id.clone(), name: self.name.clone(), - expires_at: self.expires_at.clone(), - current: self.current.clone(), + expires_at: self.expires_at, + current: self.current, messages: messages.to_vec(), temporary: self.temporary, redaction_mapping: self.redaction_mapping.clone(), diff --git a/src/session/model/smart_context.rs b/src/session/model/smart_context.rs index 7ae9f95..81a7673 100644 --- a/src/session/model/smart_context.rs +++ b/src/session/model/smart_context.rs @@ -22,6 +22,7 @@ pub struct SessionSmartContext { impl SessionSmartContext { /// Create a new SessionSmartContext from discovery parameters #[allow(dead_code)] + #[allow(clippy::too_many_arguments)] pub fn new( session_id: String, project_path: String, diff --git a/src/session/repository/smart_context_repository.rs b/src/session/repository/smart_context_repository.rs index 9a6664c..945b82d 100644 --- a/src/session/repository/smart_context_repository.rs +++ b/src/session/repository/smart_context_repository.rs @@ -193,6 +193,7 @@ impl SmartContextRepository for SmartContextRepositoryImpl { } /// Helper function to create a new SmartContextEntity with generated ID +#[allow(clippy::too_many_arguments)] pub fn create_smart_context_entity( session_id: String, project_path: String, diff --git a/src/session/service/sessions_service.rs b/src/session/service/sessions_service.rs index 66d7315..d11f6a2 100644 --- a/src/session/service/sessions_service.rs +++ b/src/session/service/sessions_service.rs @@ -12,7 +12,7 @@ pub fn fetch_all_sessions( let session_entities = session_repo.fetch_all_sessions().unwrap_or_else(|_| vec![]); let sessions = session_entities .iter() - .map(|s| Session::from(s)) + .map(Session::from) .collect::>(); println!("\n"); @@ -46,7 +46,7 @@ pub fn get_most_recent_session( // expires_at is updated every time the session is used, so it reflects the last usage time let mut sessions = session_entities .iter() - .map(|s| Session::from(s)) + .map(Session::from) .collect::>(); sessions.sort_by(|a, b| b.expires_at.cmp(&a.expires_at)); @@ -102,7 +102,7 @@ pub fn session_add_messages( let new_messages = session .messages .iter() - .filter(|message| message.id == "") + .filter(|message| message.id.is_empty()) .collect::>(); for message in new_messages { let message_with_id = message.copy_with_id(generate_uuid_v4().to_string()); @@ -125,10 +125,10 @@ fn session_with_messages( ) -> Session { let messages = message_repository .fetch_messages_for_session(&session.id) - .unwrap_or(Vec::new()) + .unwrap_or_default() .iter() - .map(|m| Message::from(m)) + .map(Message::from) .collect::>(); - let session = session.copy_with_messages(messages); - session + + session.copy_with_messages(messages) } diff --git a/src/session/service/smart_context_service.rs b/src/session/service/smart_context_service.rs index 34019ad..ae9d9b4 100644 --- a/src/session/service/smart_context_service.rs +++ b/src/session/service/smart_context_service.rs @@ -21,6 +21,7 @@ impl SmartContextService { } /// Discover smart context and associate it with a session + #[allow(clippy::too_many_arguments)] pub async fn discover_and_store_context( &self, session_id: String, @@ -39,7 +40,7 @@ impl SmartContextService { if let Ok(existing_context) = SessionSmartContext::from_entity(&existing_entity) { // Check if existing context is still valid if existing_context.is_valid_for_query( - query_hash.as_ref().map(|s| s.as_str()), + query_hash.as_deref(), None, // TODO: Add config hash support ) && existing_context.project_path == project_path.to_string_lossy() { @@ -169,7 +170,7 @@ impl SmartContextService { // Check query hash matches let query_hash = query.map(|q| self.hash_string(q)); Ok(context.is_valid_for_query( - query_hash.as_ref().map(|s| s.as_str()), + query_hash.as_deref(), None, // TODO: Add config hash )) } else { diff --git a/src/setup/wizard.rs b/src/setup/wizard.rs index c7b5315..882323e 100644 --- a/src/setup/wizard.rs +++ b/src/setup/wizard.rs @@ -125,7 +125,7 @@ impl SetupWizard { ); println!(); - let providers = vec![Provider::Claude, Provider::OpenAI, Provider::OpenAICodex, Provider::Both]; + let providers = [Provider::Claude, Provider::OpenAI, Provider::OpenAICodex, Provider::Both]; let selection = Select::with_theme(&self.theme) .with_prompt("Which AI provider would you like to use?") From 3d23265b2a4d8a6874f24caa2bdde3cefc2bd1ea Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Feb 2026 13:03:12 +0000 Subject: [PATCH 2/2] fix: convert misplaced doc comments to regular comments Change module-level and section-header /// doc comments to // regular comments where they don't document a specific item, preventing empty-line-after-doc-comment clippy warnings. Also inline remaining format!() calls in println!() macros. https://claude.ai/code/session_01J96NRV6o9dKTmr7igJmcaG --- src/branch/comparison.rs | 8 ++++---- src/branch/merge.rs | 8 ++++---- src/branch/mod.rs | 14 +++++++------- src/branch/service/branch_service.rs | 2 +- src/commands/commit.rs | 2 +- src/commands/mod.rs | 2 +- src/commands/preset.rs | 8 ++++---- src/commands/session.rs | 8 ++++---- src/git/mod.rs | 18 +++++++++--------- src/llm/openai/adapter/gpt5_adapter.rs | 2 +- src/main.rs | 2 +- src/preset/mod.rs | 2 +- 12 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/branch/comparison.rs b/src/branch/comparison.rs index bc7c0d1..1178c5e 100644 --- a/src/branch/comparison.rs +++ b/src/branch/comparison.rs @@ -1,7 +1,7 @@ -/// Branch comparison features for TermAI -/// -/// This module provides sophisticated comparison capabilities between conversation branches, -/// allowing users to analyze different approaches, solutions, and outcomes side-by-side. +// Branch comparison features for TermAI +// +// This module provides sophisticated comparison capabilities between conversation branches, +// allowing users to analyze different approaches, solutions, and outcomes side-by-side. #[allow(dead_code)] use crate::branch::entity::branch_entity::BranchEntity; use crate::branch::service::BranchService; diff --git a/src/branch/merge.rs b/src/branch/merge.rs index 74b3e25..93a092a 100644 --- a/src/branch/merge.rs +++ b/src/branch/merge.rs @@ -1,7 +1,7 @@ -/// Branch merging and integration module for TermAI -/// -/// This module provides sophisticated merging capabilities for conversation branches, -/// allowing users to consolidate insights, resolve conflicts, and maintain conversation flow. +// Branch merging and integration module for TermAI +// +// This module provides sophisticated merging capabilities for conversation branches, +// allowing users to consolidate insights, resolve conflicts, and maintain conversation flow. use crate::branch::entity::branch_entity::BranchEntity; use crate::branch::service::BranchService; use crate::branch::comparison::{BranchComparator, BranchComparison}; diff --git a/src/branch/mod.rs b/src/branch/mod.rs index db329ea..7ebca26 100644 --- a/src/branch/mod.rs +++ b/src/branch/mod.rs @@ -1,10 +1,10 @@ -/// Conversation branching module for TermAI -/// -/// This module provides tree-like conversation management, allowing users to: -/// - Branch conversations at any point to explore alternative paths -/// - Compare different approaches and solutions -/// - Merge successful branches back into main conversations -/// - Navigate complex problem-solving workflows efficiently +// Conversation branching module for TermAI +// +// This module provides tree-like conversation management, allowing users to: +// - Branch conversations at any point to explore alternative paths +// - Compare different approaches and solutions +// - Merge successful branches back into main conversations +// - Navigate complex problem-solving workflows efficiently #[allow(dead_code)] #[allow(unused_imports)] pub mod entity; diff --git a/src/branch/service/branch_service.rs b/src/branch/service/branch_service.rs index 2bcda2f..ec54c3a 100644 --- a/src/branch/service/branch_service.rs +++ b/src/branch/service/branch_service.rs @@ -146,7 +146,7 @@ impl BranchService { } } - /// Internal helper methods + // Internal helper methods fn create_branch_in_db(repo: &mut SqliteRepository, branch: &BranchEntity) -> Result<()> { repo.conn.execute( "INSERT INTO conversation_branches (id, session_id, parent_branch_id, branch_name, description, created_at, last_activity, status) diff --git a/src/commands/commit.rs b/src/commands/commit.rs index 9fad686..f863331 100644 --- a/src/commands/commit.rs +++ b/src/commands/commit.rs @@ -588,7 +588,7 @@ async fn generate_commit_message( match generate_ai_commit_message(diff_summary, args, repo).await { Ok(message) => Ok(message), Err(e) => { - println!("{}", format!("āš ļø AI generation failed: {}", e).yellow()); + println!("āš ļø AI generation failed: {}", e.to_string().yellow()); println!("{}", "šŸ“ Falling back to heuristic generation...".dimmed()); // Fallback to rule-based generation diff --git a/src/commands/mod.rs b/src/commands/mod.rs index edfd14e..065bef2 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -273,7 +273,7 @@ fn print_config(repo: &SqliteRepository) -> Result<()> { Ok(()) } -/// Enhanced error handlers that provide actionable guidance messages +// Enhanced error handlers that provide actionable guidance messages fn enhance_setup_error(error: anyhow::Error) -> anyhow::Error { let guidance = format!( "\n{}\n{}\n• {}\n• {}\n• {}", diff --git a/src/commands/preset.rs b/src/commands/preset.rs index 5e7ea16..721b78b 100644 --- a/src/commands/preset.rs +++ b/src/commands/preset.rs @@ -207,7 +207,7 @@ async fn handle_use_preset( git_staged: bool, variables: &[String], ) -> Result<()> { - println!("{}", format!("šŸ” Using preset: {}", name).bright_blue().bold()); + println!("šŸ” Using preset: {}", name.bright_blue().bold()); println!(); // Try to load preset (first check built-ins, then user presets) @@ -787,7 +787,7 @@ async fn handle_search_presets( _search_content: bool, category: Option<&str>, ) -> Result<()> { - println!("{}", format!("šŸ” Searching presets for: '{}'", query).bright_blue().bold()); + println!("šŸ” Searching presets for: '{}'", query.bright_blue().bold()); println!(); let results = manager.search_presets(query) @@ -1093,8 +1093,8 @@ fn format_files_for_template(files: &[Files]) -> String { result } -/// Helper functions for enhanced preset creation -/// Detect template variables from content using regex +// Helper functions for enhanced preset creation +// Detect template variables from content using regex fn detect_template_variables(content: &str) -> Vec { use regex::Regex; diff --git a/src/commands/session.rs b/src/commands/session.rs index fee50da..d8621b7 100644 --- a/src/commands/session.rs +++ b/src/commands/session.rs @@ -373,7 +373,7 @@ fn handle_tree_command( println!("{}", tree_output); } else { - println!("{}", format!("🌳 Branch Tree for '{}'", session_name).bright_green().bold()); + println!("🌳 Branch Tree for '{}'", session_name.bright_green().bold()); println!("{}", "═".repeat(30).white().dimmed()); println!(); @@ -437,7 +437,7 @@ fn handle_branches_command( .fetch_session_by_name(session_name) .context(format!("Session '{}' not found", session_name))?; - println!("{}", format!("šŸ“‹ Branches in '{}'", session_name).bright_green().bold()); + println!("šŸ“‹ Branches in '{}'", session_name.bright_green().bold()); println!("{}", "═".repeat(25).white().dimmed()); println!(); @@ -666,7 +666,7 @@ fn handle_search_command( .fetch_session_by_name(session_name) .context(format!("Session '{}' not found", session_name))?; - println!("{}", format!("šŸ” Search Results in '{}'", session_name).bright_green().bold()); + println!("šŸ” Search Results in '{}'", session_name.bright_green().bold()); println!("{}", "═".repeat(30).white().dimmed()); println!(); @@ -756,7 +756,7 @@ fn handle_stats_command( .fetch_session_by_name(session_name) .context(format!("Session '{}' not found", session_name))?; - println!("{}", format!("šŸ“Š Branch Statistics for '{}'", session_name).bright_green().bold()); + println!("šŸ“Š Branch Statistics for '{}'", session_name.bright_green().bold()); println!("{}", "═".repeat(35).white().dimmed()); println!(); diff --git a/src/git/mod.rs b/src/git/mod.rs index 119048a..561afd2 100644 --- a/src/git/mod.rs +++ b/src/git/mod.rs @@ -4,15 +4,15 @@ pub mod commit; pub mod diff; #[allow(dead_code)] pub mod hooks; -/// Git integration module for TermAI -/// -/// This module provides comprehensive Git integration capabilities including: -/// - Repository detection and operations -/// - Diff analysis and parsing -/// - Commit message generation -/// - Code review functionality -/// - Hook management -/// - Interactive workflows +// Git integration module for TermAI +// +// This module provides comprehensive Git integration capabilities including: +// - Repository detection and operations +// - Diff analysis and parsing +// - Commit message generation +// - Code review functionality +// - Hook management +// - Interactive workflows #[allow(dead_code)] pub mod repository; #[allow(dead_code)] diff --git a/src/llm/openai/adapter/gpt5_adapter.rs b/src/llm/openai/adapter/gpt5_adapter.rs index bd7fd3f..c6d6e2c 100644 --- a/src/llm/openai/adapter/gpt5_adapter.rs +++ b/src/llm/openai/adapter/gpt5_adapter.rs @@ -21,7 +21,7 @@ impl Gpt5Adapter { } } - /// Chat Completions API removed - migrated to Responses API + // Chat Completions API removed - migrated to Responses API /// Call the new Responses API (preferred for GPT-5) /// Optimized for reasoning models with better caching and performance pub async fn responses( diff --git a/src/main.rs b/src/main.rs index c4add3b..570aaed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -144,7 +144,7 @@ fn db_path() -> Result { Ok(default_dir.join("app.db")) } -/// Enhanced error handlers for main initialization +// Enhanced error handlers for main initialization fn enhance_database_path_error(error: anyhow::Error) -> anyhow::Error { let guidance = format!( "\n{}\n{}\n• {}\n• {}\n• {}", diff --git a/src/preset/mod.rs b/src/preset/mod.rs index b5d1cae..8a25d98 100644 --- a/src/preset/mod.rs +++ b/src/preset/mod.rs @@ -1,4 +1,4 @@ -/// Template and preset system for reusable AI interactions +// Template and preset system for reusable AI interactions pub mod template; pub mod manager; pub mod variables;