chore: apply clippy fixes and fix invalid YAML test
- Replace redundant closures with function references - Use next_back() instead of last() for DoubleEndedIterator - Fix test_parse_index_response_invalid to use actually invalid YAML (previous test string was valid YAML - a plain string with braces) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1847700c09
commit
87e0066c36
16 changed files with 34 additions and 45 deletions
|
|
@ -1663,7 +1663,7 @@ fn handle_index_command_blocking(command: IndexCommands) -> Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let llm = OllamaLlm::new(&llm_config);
|
let llm = OllamaLlm::new(&llm_config);
|
||||||
if let Err(_) = llm.start() {
|
if llm.start().is_err() {
|
||||||
// Silently skip if Ollama not available (pre-commit hook shouldn't block)
|
// Silently skip if Ollama not available (pre-commit hook shouldn't block)
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ impl DaemonDb {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let sessions = stmt
|
let sessions = stmt
|
||||||
.query_map([], |row| Self::row_to_session(row))?
|
.query_map([], Self::row_to_session)?
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(sessions)
|
Ok(sessions)
|
||||||
|
|
@ -295,7 +295,7 @@ impl DaemonDb {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let sessions = stmt
|
let sessions = stmt
|
||||||
.query_map([realm], |row| Self::row_to_session(row))?
|
.query_map([realm], Self::row_to_session)?
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(sessions)
|
Ok(sessions)
|
||||||
|
|
@ -312,7 +312,7 @@ impl DaemonDb {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let session = stmt
|
let session = stmt
|
||||||
.query_row([id], |row| Self::row_to_session(row))
|
.query_row([id], Self::row_to_session)
|
||||||
.optional()?;
|
.optional()?;
|
||||||
|
|
||||||
Ok(session)
|
Ok(session)
|
||||||
|
|
@ -392,7 +392,7 @@ impl DaemonDb {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let notifications = stmt
|
let notifications = stmt
|
||||||
.query_map([], |row| Self::row_to_notification(row))?
|
.query_map([], Self::row_to_notification)?
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(notifications)
|
Ok(notifications)
|
||||||
|
|
@ -413,7 +413,7 @@ impl DaemonDb {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let notifications = stmt
|
let notifications = stmt
|
||||||
.query_map([realm], |row| Self::row_to_notification(row))?
|
.query_map([realm], Self::row_to_notification)?
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(notifications)
|
Ok(notifications)
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ impl BlueConfig {
|
||||||
pub fn save(&self, blue_dir: &std::path::Path) -> Result<(), std::io::Error> {
|
pub fn save(&self, blue_dir: &std::path::Path) -> Result<(), std::io::Error> {
|
||||||
let config_path = blue_dir.join("config.yaml");
|
let config_path = blue_dir.join("config.yaml");
|
||||||
let content = serde_yaml::to_string(self)
|
let content = serde_yaml::to_string(self)
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
.map_err(|e| std::io::Error::other(e))?;
|
||||||
std::fs::write(&config_path, content)
|
std::fs::write(&config_path, content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ impl<P: LlmProvider> Indexer<P> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let completion = self.provider.complete(&prompt, &options)
|
let completion = self.provider.complete(&prompt, &options)
|
||||||
.map_err(|e| IndexerError::LlmError(e))?;
|
.map_err(IndexerError::LlmError)?;
|
||||||
|
|
||||||
// Parse YAML response
|
// Parse YAML response
|
||||||
let parsed = parse_index_response(&completion.text);
|
let parsed = parse_index_response(&completion.text);
|
||||||
|
|
@ -433,7 +433,8 @@ symbols: []"#;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_index_response_invalid() {
|
fn test_parse_index_response_invalid() {
|
||||||
let response = "this is not valid yaml { broken }";
|
// Use actually invalid YAML (unclosed bracket)
|
||||||
|
let response = "key: [unclosed bracket";
|
||||||
let parsed = parse_index_response(response);
|
let parsed = parse_index_response(response);
|
||||||
assert!(parsed.error.is_some());
|
assert!(parsed.error.is_some());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,10 @@ pub trait LlmProvider: Send + Sync {
|
||||||
|
|
||||||
/// LLM backend selection
|
/// LLM backend selection
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[derive(Default)]
|
||||||
pub enum LlmBackendChoice {
|
pub enum LlmBackendChoice {
|
||||||
/// Auto-detect best backend (CUDA > MPS > CPU)
|
/// Auto-detect best backend (CUDA > MPS > CPU)
|
||||||
|
#[default]
|
||||||
Auto,
|
Auto,
|
||||||
/// Force CUDA (NVIDIA GPU)
|
/// Force CUDA (NVIDIA GPU)
|
||||||
Cuda,
|
Cuda,
|
||||||
|
|
@ -117,11 +119,6 @@ pub enum LlmBackendChoice {
|
||||||
Cpu,
|
Cpu,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LlmBackendChoice {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Auto
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// LLM configuration
|
/// LLM configuration
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ impl ImportBinding {
|
||||||
/// Check if this import satisfies a given version
|
/// Check if this import satisfies a given version
|
||||||
pub fn satisfies(&self, version: &str) -> Result<bool, RealmError> {
|
pub fn satisfies(&self, version: &str) -> Result<bool, RealmError> {
|
||||||
let req = semver::VersionReq::parse(&self.version)
|
let req = semver::VersionReq::parse(&self.version)
|
||||||
.map_err(|e| RealmError::InvalidVersion(e))?;
|
.map_err(RealmError::InvalidVersion)?;
|
||||||
let ver = semver::Version::parse(version)?;
|
let ver = semver::Version::parse(version)?;
|
||||||
Ok(req.matches(&ver))
|
Ok(req.matches(&ver))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -289,14 +289,14 @@ fn extract_project_name(path: &Path) -> Option<String> {
|
||||||
fn extract_repo_name_from_url(url: &str) -> Option<String> {
|
fn extract_repo_name_from_url(url: &str) -> Option<String> {
|
||||||
// Handle SSH URLs: git@host:org/repo.git
|
// Handle SSH URLs: git@host:org/repo.git
|
||||||
if url.contains(':') && !url.contains("://") {
|
if url.contains(':') && !url.contains("://") {
|
||||||
let after_colon = url.split(':').last()?;
|
let after_colon = url.split(':').next_back()?;
|
||||||
let name = after_colon.trim_end_matches(".git");
|
let name = after_colon.trim_end_matches(".git");
|
||||||
return name.split('/').last().map(|s| s.to_string());
|
return name.split('/').next_back().map(|s| s.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle HTTPS URLs: https://host/org/repo.git
|
// Handle HTTPS URLs: https://host/org/repo.git
|
||||||
let name = url.trim_end_matches(".git");
|
let name = url.trim_end_matches(".git");
|
||||||
name.split('/').last().map(|s| s.to_string())
|
name.split('/').next_back().map(|s| s.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List git worktrees for a repository
|
/// List git worktrees for a repository
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ fn load_adr_summaries(state: &ProjectState) -> Result<Vec<AdrSummary>, ServerErr
|
||||||
|
|
||||||
for entry in entries.flatten() {
|
for entry in entries.flatten() {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.extension().map_or(false, |e| e == "md") {
|
if path.extension().is_some_and(|e| e == "md") {
|
||||||
if let Ok(content) = fs::read_to_string(&path) {
|
if let Ok(content) = fs::read_to_string(&path) {
|
||||||
if let Some(summary) = parse_adr_file(&path, &content) {
|
if let Some(summary) = parse_adr_file(&path, &content) {
|
||||||
summaries.push(summary);
|
summaries.push(summary);
|
||||||
|
|
|
||||||
|
|
@ -220,22 +220,20 @@ pub fn handle_delete(
|
||||||
let stem_str = stem.to_string_lossy();
|
let stem_str = stem.to_string_lossy();
|
||||||
for suffix in &[".plan.md", ".dialogue.md", ".draft.md"] {
|
for suffix in &[".plan.md", ".dialogue.md", ".draft.md"] {
|
||||||
let companion = parent.join(format!("{}{}", stem_str, suffix));
|
let companion = parent.join(format!("{}{}", stem_str, suffix));
|
||||||
if companion.exists() {
|
if companion.exists()
|
||||||
if fs::remove_file(&companion).is_ok() {
|
&& fs::remove_file(&companion).is_ok() {
|
||||||
files_deleted.push(companion.display().to_string());
|
files_deleted.push(companion.display().to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Delete primary file
|
// Delete primary file
|
||||||
if base_path.exists() {
|
if base_path.exists()
|
||||||
if fs::remove_file(base_path).is_ok() {
|
&& fs::remove_file(base_path).is_ok() {
|
||||||
files_deleted.push(file_path.clone());
|
files_deleted.push(file_path.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Soft or permanent delete
|
// Soft or permanent delete
|
||||||
if permanent {
|
if permanent {
|
||||||
|
|
|
||||||
|
|
@ -580,7 +580,7 @@ fn generate_dialogue_markdown(
|
||||||
md.push_str("| Round | Topic | Outcome |\n");
|
md.push_str("| Round | Topic | Outcome |\n");
|
||||||
md.push_str("|-------|-------|--------|\n");
|
md.push_str("|-------|-------|--------|\n");
|
||||||
md.push_str("| 1 | [Topic] | [Outcome] |\n");
|
md.push_str("| 1 | [Topic] | [Outcome] |\n");
|
||||||
md.push_str("\n");
|
md.push('\n');
|
||||||
|
|
||||||
// Lessons learned
|
// Lessons learned
|
||||||
md.push_str("## Lessons Learned\n\n");
|
md.push_str("## Lessons Learned\n\n");
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ pub fn handle_detect(args: &Value, repo_path: &Path) -> Result<Value, ServerErro
|
||||||
let path = args
|
let path = args
|
||||||
.get("cwd")
|
.get("cwd")
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.map(|s| std::path::PathBuf::from(s))
|
.map(std::path::PathBuf::from)
|
||||||
.unwrap_or_else(|| repo_path.to_path_buf());
|
.unwrap_or_else(|| repo_path.to_path_buf());
|
||||||
|
|
||||||
let (dependencies, env_files, iac_detected, docker_detected, mock_config) =
|
let (dependencies, env_files, iac_detected, docker_detected, mock_config) =
|
||||||
|
|
@ -63,13 +63,13 @@ pub fn handle_mock(args: &Value, repo_path: &Path) -> Result<Value, ServerError>
|
||||||
let scan_path = args
|
let scan_path = args
|
||||||
.get("cwd")
|
.get("cwd")
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.map(|s| std::path::PathBuf::from(s))
|
.map(std::path::PathBuf::from)
|
||||||
.unwrap_or_else(|| repo_path.to_path_buf());
|
.unwrap_or_else(|| repo_path.to_path_buf());
|
||||||
|
|
||||||
let worktree_path = args
|
let worktree_path = args
|
||||||
.get("worktree_path")
|
.get("worktree_path")
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.map(|s| std::path::PathBuf::from(s))
|
.map(std::path::PathBuf::from)
|
||||||
.unwrap_or_else(|| scan_path.clone());
|
.unwrap_or_else(|| scan_path.clone());
|
||||||
|
|
||||||
let agent_id = args
|
let agent_id = args
|
||||||
|
|
|
||||||
|
|
@ -362,8 +362,8 @@ fn run_python_checks(path: &Path, fix: bool, check_type: &str) -> Vec<LintResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if check_type == "all" || check_type == "lint" {
|
if (check_type == "all" || check_type == "lint")
|
||||||
if use_ruff {
|
&& use_ruff {
|
||||||
let args: Vec<&str> = if fix {
|
let args: Vec<&str> = if fix {
|
||||||
vec!["check", "--fix", "."]
|
vec!["check", "--fix", "."]
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -379,7 +379,6 @@ fn run_python_checks(path: &Path, fix: bool, check_type: &str) -> Vec<LintResult
|
||||||
"ruff check --fix .",
|
"ruff check --fix .",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -398,7 +398,7 @@ fn generate_postmortem_markdown(
|
||||||
md.push_str("| Time | Event |\n");
|
md.push_str("| Time | Event |\n");
|
||||||
md.push_str("|------|-------|\n");
|
md.push_str("|------|-------|\n");
|
||||||
md.push_str("| HH:MM | [Event] |\n");
|
md.push_str("| HH:MM | [Event] |\n");
|
||||||
md.push_str("\n");
|
md.push('\n');
|
||||||
|
|
||||||
// Root Cause
|
// Root Cause
|
||||||
md.push_str("## Root Cause\n\n");
|
md.push_str("## Root Cause\n\n");
|
||||||
|
|
@ -418,7 +418,7 @@ fn generate_postmortem_markdown(
|
||||||
} else {
|
} else {
|
||||||
md.push_str("- [Impact 1]\n");
|
md.push_str("- [Impact 1]\n");
|
||||||
}
|
}
|
||||||
md.push_str("\n");
|
md.push('\n');
|
||||||
|
|
||||||
// What Went Well
|
// What Went Well
|
||||||
md.push_str("## What Went Well\n\n");
|
md.push_str("## What Went Well\n\n");
|
||||||
|
|
@ -433,7 +433,7 @@ fn generate_postmortem_markdown(
|
||||||
md.push_str("| Item | Owner | Due | Status | RFC |\n");
|
md.push_str("| Item | Owner | Due | Status | RFC |\n");
|
||||||
md.push_str("|------|-------|-----|--------|-----|\n");
|
md.push_str("|------|-------|-----|--------|-----|\n");
|
||||||
md.push_str("| [Action 1] | [Name] | [Date] | Open | |\n");
|
md.push_str("| [Action 1] | [Name] | [Date] | Open | |\n");
|
||||||
md.push_str("\n");
|
md.push('\n');
|
||||||
|
|
||||||
// Lessons Learned
|
// Lessons Learned
|
||||||
md.push_str("## Lessons Learned\n\n");
|
md.push_str("## Lessons Learned\n\n");
|
||||||
|
|
|
||||||
|
|
@ -394,15 +394,14 @@ pub fn handle_lookup(state: &ProjectState, args: &Value) -> Result<Value, Server
|
||||||
// Calculate best match score for this runbook
|
// Calculate best match score for this runbook
|
||||||
for action in &actions {
|
for action in &actions {
|
||||||
let score = calculate_match_score(&action_query, action);
|
let score = calculate_match_score(&action_query, action);
|
||||||
if score > 0 {
|
if score > 0
|
||||||
if best_match.as_ref().map_or(true, |(_, _, s)| score > *s) {
|
&& best_match.as_ref().is_none_or(|(_, _, s)| score > *s) {
|
||||||
best_match = Some((runbook.clone(), actions.clone(), score));
|
best_match = Some((runbook.clone(), actions.clone(), score));
|
||||||
break; // This runbook matches, move to next
|
break; // This runbook matches, move to next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
match best_match {
|
match best_match {
|
||||||
Some((runbook, actions, _score)) => {
|
Some((runbook, actions, _score)) => {
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ pub fn handle_create(state: &ProjectState, args: &Value) -> Result<Value, Server
|
||||||
"setup_script": setup_script,
|
"setup_script": setup_script,
|
||||||
"message": blue_core::voice::success(
|
"message": blue_core::voice::success(
|
||||||
&format!("Created worktree for '{}'", title),
|
&format!("Created worktree for '{}'", title),
|
||||||
Some(&hint.trim())
|
Some(hint.trim())
|
||||||
),
|
),
|
||||||
"next_action": {
|
"next_action": {
|
||||||
"tool": if setup_script.is_some() || install_command.is_some() {
|
"tool": if setup_script.is_some() || install_command.is_some() {
|
||||||
|
|
|
||||||
|
|
@ -246,12 +246,7 @@ impl EmbeddedOllama {
|
||||||
/// Find a free port starting from the given port
|
/// Find a free port starting from the given port
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn find_free_port(start: u16) -> Option<u16> {
|
fn find_free_port(start: u16) -> Option<u16> {
|
||||||
for port in start..start + 100 {
|
(start..start + 100).find(|&port| !Self::port_in_use(port))
|
||||||
if !Self::port_in_use(port) {
|
|
||||||
return Some(port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get path to bundled Ollama binary
|
/// Get path to bundled Ollama binary
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue