#![allow(dead_code)]
use anyhow::{Context, Result, anyhow};
use rust_memex::EmbeddingConfig;
use serde::Deserialize;
use std::path::PathBuf;
const CONFIG_SEARCH_PATHS: &[&str] = &[
"~/.rmcp-servers/rust-memex/config.toml",
"~/.config/rust-memex/config.toml",
];
#[derive(Debug, Deserialize)]
struct FileConfigShim {
#[serde(default)]
db_path: Option<String>,
#[serde(default)]
embeddings: Option<EmbeddingConfig>,
}
#[derive(Debug, Clone)]
pub struct E2eConfig {
pub source_path: PathBuf,
pub db_path: Option<String>,
pub embeddings: EmbeddingConfig,
}
pub fn load_e2e_config() -> Result<E2eConfig> {
let path = resolve_config_path().ok_or_else(|| {
anyhow!(
"e2e tests need a real rust-memex config.toml. Set RUST_MEMEX_CONFIG \
or place one at ~/.rmcp-servers/rust-memex/config.toml. Searched: \
RUST_MEMEX_CONFIG env, {:?}",
CONFIG_SEARCH_PATHS
)
})?;
let contents = std::fs::read_to_string(&path)
.with_context(|| format!("Failed to read e2e config at {}", path.display()))?;
let shim: FileConfigShim = toml::from_str(&contents)
.with_context(|| format!("Failed to parse e2e config at {}", path.display()))?;
let embeddings = shim.embeddings.ok_or_else(|| {
anyhow!(
"Config at {} has no [embeddings] section — e2e tests need a real \
provider cascade.",
path.display()
)
})?;
if embeddings.providers.is_empty() {
return Err(anyhow!(
"Config at {} declares [embeddings] without any providers — \
e2e tests need at least one [[embeddings.providers]].",
path.display()
));
}
Ok(E2eConfig {
source_path: path,
db_path: shim.db_path,
embeddings,
})
}
fn resolve_config_path() -> Option<PathBuf> {
if let Ok(p) = std::env::var("RUST_MEMEX_CONFIG") {
let pb = expand_tilde(&p);
if pb.exists() {
return Some(pb);
}
}
for raw in CONFIG_SEARCH_PATHS {
let pb = expand_tilde(raw);
if pb.exists() {
return Some(pb);
}
}
None
}
fn expand_tilde(s: &str) -> PathBuf {
if let Some(rest) = s.strip_prefix("~/")
&& let Ok(home) = std::env::var("HOME")
{
return PathBuf::from(home).join(rest);
}
PathBuf::from(s)
}