use anyhow::Result;
use clap::Args;
use octocode::config::Config;
use octocode::embedding::types::{parse_provider_model, EmbeddingProviderType};
#[derive(Args)]
pub struct ConfigArgs {
#[arg(long)]
pub model: Option<String>,
#[arg(long)]
pub code_embedding_model: Option<String>,
#[arg(long)]
pub text_embedding_model: Option<String>,
#[arg(long)]
pub chunk_size: Option<usize>,
#[arg(long)]
pub chunk_overlap: Option<usize>,
#[arg(long)]
pub max_results: Option<usize>,
#[arg(long)]
pub similarity_threshold: Option<f32>,
#[arg(long)]
pub graphrag_enabled: Option<bool>,
#[arg(long)]
pub show: bool,
#[arg(long)]
pub reset: bool,
}
pub fn execute(args: &ConfigArgs, mut config: Config) -> Result<()> {
if args.reset {
config = Config::default();
config.save()?;
println!("Configuration reset to defaults");
return Ok(());
}
if args.show {
println!("=== Octocode Configuration ===");
println!();
if let Ok(config_path) = Config::get_system_config_path() {
println!("π Configuration file: {}", config_path.display());
if config_path.exists() {
println!(" Status: β
Found");
} else {
println!(" Status: β οΈ Not found (using defaults)");
}
}
println!();
println!("π€ LLM Configuration:");
println!(" Model: {}", config.llm.model);
println!(" Temperature: {}", config.llm.temperature);
println!(" Max Tokens: {}", config.llm.max_tokens);
println!(" Timeout: {}s", config.llm.timeout);
println!("π Embedding Configuration:");
let active_provider = config.embedding.get_active_provider();
println!(" Active provider: {:?} (auto-detected)", active_provider);
println!(" Code model: {}", config.embedding.code_model);
println!(" Text model: {}", config.embedding.text_model);
match active_provider {
Ok(EmbeddingProviderType::Jina) => {
let api_key_status = if config
.embedding
.get_api_key(&EmbeddingProviderType::Jina)
.is_some()
{
"β
Set"
} else {
"β Not set"
};
println!(" Jina API key: {}", api_key_status);
}
Ok(EmbeddingProviderType::Voyage) => {
let api_key_status = if config
.embedding
.get_api_key(&EmbeddingProviderType::Voyage)
.is_some()
{
"β
Set"
} else {
"β Not set"
};
println!(" Voyage API key: {}", api_key_status);
}
Ok(EmbeddingProviderType::Google) => {
let api_key_status = if config
.embedding
.get_api_key(&EmbeddingProviderType::Google)
.is_some()
{
"β
Set"
} else {
"β Not set"
};
println!(" Google API key: {}", api_key_status);
}
_ => {
println!(" API key: Not required");
}
}
println!();
println!("π Indexing Configuration:");
println!(" Chunk size: {} characters", config.index.chunk_size);
println!(
" Chunk overlap: {} characters",
config.index.chunk_overlap
);
println!(
" Batch size: {} texts",
config.index.embeddings_batch_size
);
println!(
" GraphRAG: {}",
if config.graphrag.enabled {
"β
Enabled"
} else {
"β Disabled"
}
);
println!(
" LLM processing: {}",
if config.graphrag.use_llm {
"β
Enabled"
} else {
"β Disabled"
}
);
println!();
println!("π Search Configuration:");
println!(" Max results: {}", config.search.max_results);
println!(
" Similarity threshold: {:.2}",
config.search.similarity_threshold
);
println!(" Output format: {}", config.search.output_format);
println!(" Max files: {}", config.search.max_files);
println!(" Context lines: {}", config.search.context_lines);
println!(
" Block max chars: {}",
config.search.search_block_max_characters
);
println!();
println!("πΎ Storage Locations:");
if let Ok(storage_dir) = octocode::storage::get_system_storage_dir() {
println!(" System storage: {}", storage_dir.display());
println!(" FastEmbed cache: {}/fastembed/", storage_dir.display());
println!(
" SentenceTransformer cache: {}/sentencetransformer/",
storage_dir.display()
);
}
if let Ok(current_dir) = std::env::current_dir() {
if let Ok(db_path) = octocode::storage::get_project_database_path(¤t_dir) {
println!(" Project database: {}", db_path.display());
if db_path.exists() {
println!(" Database status: β
Found");
} else {
println!(" Database status: β Not indexed (run 'octocode index')");
}
}
}
if config.graphrag.enabled {
println!();
println!("πΈοΈ GraphRAG Configuration:");
println!(
" Description model: {}",
config.graphrag.llm.description_model
);
println!(
" Relationship model: {}",
config.graphrag.llm.relationship_model
);
}
return Ok(());
}
let mut updated = false;
if let Some(model) = &args.model {
config.llm.model = model.clone();
println!("Model set to: {}", model);
updated = true;
}
if let Some(code_model) = &args.code_embedding_model {
let (provider, _) = parse_provider_model(code_model)?;
config.embedding.code_model = code_model.clone();
println!(
"Code embedding model set to: {} (provider: {:?})",
code_model, provider
);
updated = true;
}
if let Some(text_model) = &args.text_embedding_model {
let (provider, _) = parse_provider_model(text_model)?;
config.embedding.text_model = text_model.clone();
println!(
"Text embedding model set to: {} (provider: {:?})",
text_model, provider
);
updated = true;
}
if let Some(chunk_size) = args.chunk_size {
config.index.chunk_size = chunk_size;
println!("Chunk size set to: {}", chunk_size);
updated = true;
}
if let Some(chunk_overlap) = args.chunk_overlap {
config.index.chunk_overlap = chunk_overlap;
println!("Chunk overlap set to: {}", chunk_overlap);
updated = true;
}
if let Some(max_results) = args.max_results {
config.search.max_results = max_results;
println!("Max results set to: {}", max_results);
updated = true;
}
if let Some(similarity_threshold) = args.similarity_threshold {
config.search.similarity_threshold = similarity_threshold;
println!("Similarity threshold set to: {}", similarity_threshold);
updated = true;
}
if let Some(graphrag_enabled) = args.graphrag_enabled {
config.graphrag.enabled = graphrag_enabled;
println!(
"GraphRAG {}",
if graphrag_enabled {
"enabled"
} else {
"disabled"
}
);
updated = true;
}
if updated {
config.save()?;
println!("Configuration updated successfully!");
} else {
println!("No configuration changes made. Use --show to see current settings.");
println!();
println!("Example usage:");
println!(" # Set SentenceTransformer models (provider is auto-detected):");
println!(" octocode config --code-embedding-model 'huggingface:microsoft/codebert-base'");
println!(" octocode config --text-embedding-model 'huggingface:sentence-transformers/all-mpnet-base-v2'");
println!();
println!(" # Use other providers:");
println!(" octocode config --code-embedding-model 'fastembed:all-MiniLM-L6-v2'");
println!(" octocode config --code-embedding-model 'jinaai:jina-embeddings-v2-base-code'");
println!();
println!("Popular SentenceTransformer models:");
println!(" Code models: microsoft/codebert-base, microsoft/unixcoder-base");
println!(" Text models: sentence-transformers/all-mpnet-base-v2, BAAI/bge-base-en-v1.5");
}
Ok(())
}