1use serde::{Deserialize, Serialize};
2use std::path::Path;
3
4#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5#[serde(rename_all = "lowercase")]
6pub enum EmbedBackend {
7 #[default]
8 Fastembed,
9 OpenAI,
10 Ollama,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, Default)]
14#[serde(rename_all = "lowercase")]
15pub enum StoreBackend {
16 #[default]
17 Usearch,
18 Qdrant,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, Default)]
22pub struct EmbedConfig {
23 #[serde(default)]
24 pub backend: EmbedBackend,
25 pub model: Option<String>,
27 pub url: Option<String>,
29 pub api_key: Option<String>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, Default)]
34pub struct StoreConfig {
35 #[serde(default)]
36 pub backend: StoreBackend,
37 pub url: Option<String>,
39 pub collection: Option<String>,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize, Default)]
44pub struct SemtreeConfig {
45 #[serde(default)]
46 pub embed: EmbedConfig,
47 #[serde(default)]
48 pub store: StoreConfig,
49 #[serde(default = "default_index_dir")]
51 pub index_dir: String,
52}
53
54fn default_index_dir() -> String {
55 ".semtree".to_string()
56}
57
58impl SemtreeConfig {
59 pub fn load(dir: &Path) -> Self {
61 let path = dir.join(".semtree.toml");
62 if let Ok(raw) = std::fs::read_to_string(&path) {
63 toml::from_str(&raw).unwrap_or_else(|e| {
64 eprintln!("Warning: invalid .semtree.toml: {e}");
65 Self::default()
66 })
67 } else {
68 Self::default()
69 }
70 }
71
72 pub fn save(&self, dir: &Path) -> std::io::Result<()> {
73 let path = dir.join(".semtree.toml");
74 let raw = toml::to_string_pretty(self).expect("serializable");
75 std::fs::write(path, raw)
76 }
77}