use anyhow::{Context, Result};
use tracing::{debug, info};
use crate::llm::{build_prompt, parse_suggestions, OllamaClient};
use crate::setup::load_config;
pub mod context;
pub mod search;
pub use context::{scan_directory_context, DirectoryContext, ProjectType};
pub use search::{load_manpage_content, search_tools, SearchMatch};
pub use crate::llm::{CommandSuggestion, RiskLevel};
const MAX_SEARCH_RESULTS: usize = 3;
pub async fn process_query(query: &str) -> Result<Vec<CommandSuggestion>> {
info!(query = %query, "Processing query");
let matches = search_tools(query, MAX_SEARCH_RESULTS)
.await
.context("Failed to search for tools")?;
if matches.is_empty() {
anyhow::bail!(
"No matching tools found for query: '{query}'. \
Try running 'ulm setup' to build the index."
);
}
debug!(
count = matches.len(),
top_tool = %matches[0].tool_name,
top_score = matches[0].score,
"Found matching tools"
);
let top_tool = &matches[0].tool_name;
let manpage_content =
load_manpage_content(top_tool).context("Failed to load manpage content")?;
debug!(
tool = %top_tool,
content_len = manpage_content.len(),
"Loaded manpage content"
);
let context = scan_directory_context().context("Failed to scan directory context")?;
debug!(
project_type = context.project_type.as_ref().map_or("None", |p| p.as_str()),
cwd = %context.cwd.display(),
"Scanned directory context"
);
let prompt = build_prompt(query, &manpage_content, &context);
debug!(prompt_len = prompt.len(), "Built prompt");
let config = load_config().context("Failed to load config")?;
let llm_model = config.llm_model();
let client = OllamaClient::with_config(
config.ollama_url(),
config.generate_timeout_secs(),
config.embedding_timeout_secs(),
)
.context("Failed to create Ollama client")?;
info!(model = %llm_model, "Calling Ollama for response generation");
let response = client
.generate(llm_model, &prompt, true)
.await
.context("Failed to generate LLM response")?;
debug!(response_len = response.len(), "Received LLM response");
let suggestions = parse_suggestions(&response).context("Failed to parse LLM response")?;
info!(suggestions = suggestions.len(), "Query processing complete");
Ok(suggestions)
}