use serde::{Deserialize, Serialize};
pub const LLM_MAX_CONCURRENT: usize = 16;
pub const EMBED_BATCH_SIZE: usize = 20;
pub const SEARCH_INDEX_DIR: &str = ".search";
pub const SEARCH_DEFAULT_ENGINE: SearchEngineType = SearchEngineType::Hybrid;
pub const SEARCH_DEFAULT_TOP_K: usize = 10;
pub const SEARCH_RRF_K: f64 = 60.0;
pub const IMPACT_MAX_DEPTH: usize = 3;
pub const OUTPUT_DIR: &str = ".code-repo-wiki";
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct WikiConfig {
#[serde(default)]
pub wiki: WikiSection,
#[serde(default)]
pub llm: LlmSection,
#[serde(default)]
pub embed: EmbedSection,
#[serde(skip)]
pub output_dir: Option<std::path::PathBuf>,
}
impl WikiConfig {
pub fn output_dir(&self) -> &std::path::Path {
match &self.output_dir {
Some(p) => p,
None => std::path::Path::new(crate::config::schema::OUTPUT_DIR),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WikiSection {
#[serde(default = "default_language")]
pub language: String,
#[serde(default)]
pub guide: WikiGuideSection,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct WikiGuideSection {
#[serde(default)]
pub pages: Vec<String>,
#[serde(default)]
pub priority: Vec<String>,
#[serde(default)]
pub notes: Vec<String>,
}
fn default_language() -> String {
"zh".to_string()
}
impl Default for WikiSection {
fn default() -> Self {
Self {
language: "zh".to_string(),
guide: WikiGuideSection::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LlmSection {
#[serde(default = "default_llm_provider")]
pub provider: LlmProviderType,
#[serde(default = "default_llm_model")]
pub model: String,
#[serde(default = "default_llm_base_url")]
pub base_url: Option<String>,
#[serde(default)]
pub api_key: Option<String>,
#[serde(default = "default_llm_api_key_env")]
pub api_key_env: String,
}
fn default_llm_model() -> String {
"deepseek-v4-flash".to_string()
}
fn default_llm_provider() -> LlmProviderType {
LlmProviderType::OpenAiCompatible
}
fn default_llm_base_url() -> Option<String> {
Some("https://opencode.ai/zen/go/v1".to_string())
}
fn default_llm_api_key_env() -> String {
"OPENCODEGO2_API_KEY".to_string()
}
impl Default for LlmSection {
fn default() -> Self {
Self {
provider: LlmProviderType::OpenAiCompatible,
model: "deepseek-v4-flash".to_string(),
base_url: Some("https://opencode.ai/zen/go/v1".to_string()),
api_key: None,
api_key_env: "OPENCODEGO2_API_KEY".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum LlmProviderType {
#[serde(rename = "openai")]
OpenAI,
#[serde(rename = "openai-compatible")]
OpenAiCompatible,
#[serde(rename = "anthropic")]
Anthropic,
#[serde(rename = "mock")]
Mock,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmbedSection {
#[serde(default = "default_embed_model")]
pub model: String,
#[serde(default = "default_embed_base_url")]
pub base_url: Option<String>,
#[serde(default)]
pub api_key: Option<String>,
#[serde(default = "default_embed_api_key_env")]
pub api_key_env: String,
}
fn default_embed_model() -> String {
"qwen3.7-text-embedding".to_string()
}
fn default_embed_base_url() -> Option<String> {
Some(
"https://llm-q0265e4he9m0qs23.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"
.to_string(),
)
}
fn default_embed_api_key_env() -> String {
"BAILIAN_API_KEY".to_string()
}
impl Default for EmbedSection {
fn default() -> Self {
Self {
model: "qwen3.7-text-embedding".to_string(),
base_url: Some(
"https://llm-q0265e4he9m0qs23.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"
.to_string(),
),
api_key: None,
api_key_env: "BAILIAN_API_KEY".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum SearchEngineType {
#[serde(rename = "text")]
Text,
#[serde(rename = "semantic")]
Semantic,
#[serde(rename = "hybrid")]
Hybrid,
}