use secrecy::SecretString;
pub const EMBEDDING_CONTEXT: usize = 128;
#[non_exhaustive]
#[derive(Clone, Debug)]
pub struct Config {
pub base_url: String,
pub model: String,
pub db_path: String,
pub api_key: Option<SecretString>,
}
impl Config {
pub fn new(
base_url: String,
model: String,
db_path: String,
api_key: Option<SecretString>,
) -> Self {
Config {
base_url,
model,
db_path,
api_key,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use secrecy::ExposeSecret;
#[test]
fn test_config_debug_redacts_api_key() {
let config_with_key = Config::new(
"http://localhost:9000".to_string(),
"test-model".to_string(),
"./test.db".to_string(),
Some(SecretString::from("super-secret-api-key-12345")),
);
let debug_output = format!("{:?}", config_with_key);
assert!(debug_output.contains("[REDACTED]"));
assert!(!debug_output.contains("super-secret-api-key-12345"));
assert!(debug_output.contains("http://localhost:9000"));
assert!(debug_output.contains("test-model"));
assert!(debug_output.contains("./test.db"));
}
#[test]
fn test_config_debug_without_api_key() {
let config_without_key = Config::new(
"http://localhost:9000".to_string(),
"test-model".to_string(),
"./test.db".to_string(),
None,
);
let debug_output = format!("{:?}", config_without_key);
assert!(!debug_output.contains("[REDACTED]"));
assert!(debug_output.contains("None"));
assert!(debug_output.contains("http://localhost:9000"));
assert!(debug_output.contains("test-model"));
assert!(debug_output.contains("./test.db"));
}
#[test]
fn test_config_clone() {
let original = Config::new(
"http://localhost:9000".to_string(),
"test-model".to_string(),
"./test.db".to_string(),
Some(SecretString::from("api-key")),
);
let cloned = original.clone();
assert_eq!(original.base_url, cloned.base_url);
assert_eq!(original.model, cloned.model);
assert_eq!(original.db_path, cloned.db_path);
assert_eq!(
original.api_key.as_ref().map(|s| s.expose_secret()),
cloned.api_key.as_ref().map(|s| s.expose_secret())
);
}
}