#[cfg(feature = "ollama")]
use crate::config::{alias_conflict_notice, resolve_alias};
use crate::http_client::Auth;
#[derive(Debug)]
pub struct RemoteEndpoint {
pub url: Option<String>,
pub model: Option<String>,
pub auth: Auth,
}
impl RemoteEndpoint {
pub fn require(self, prefix: &str) -> Result<(String, String, Auth), String> {
let url = self.url.ok_or_else(|| {
format!(
"{prefix}=openai requires {prefix}_URL — the server's origin and port, \
no path (e.g. http://localhost:8020). There is no default: `openai` \
is a protocol, and only you know which server speaks it here."
)
})?;
let model = self.model.ok_or_else(|| {
format!(
"{prefix}=openai requires {prefix}_MODEL — the model identifier the server expects"
)
})?;
Ok((url, model, self.auth))
}
}
fn env_opt(name: &str) -> Option<String> {
std::env::var(name).ok()
}
pub fn role_auth(name: &str) -> Result<Auth, String> {
match env_opt(name) {
None => Ok(Auth::None),
Some(token) if token.trim().is_empty() => Err(format!(
"{name} is set but empty — unset it entirely to send no credential. An \
empty token would go out as `Authorization: Bearer `, which a server \
rejects as a bad credential rather than a missing one."
)),
Some(token) => Ok(Auth::Bearer(token)),
}
}
#[cfg(feature = "ollama")]
pub fn embedder_env_endpoint() -> Result<(RemoteEndpoint, Option<String>), String> {
let url = resolve_alias(
env_opt("VELESDB_MEMORY_EMBEDDER_URL").as_deref(),
env_opt("VELESDB_MEMORY_OLLAMA_URL").as_deref(),
);
let model = resolve_alias(
env_opt("VELESDB_MEMORY_EMBEDDER_MODEL").as_deref(),
env_opt("VELESDB_MEMORY_OLLAMA_MODEL").as_deref(),
);
let mut conflicts = Vec::new();
if url.conflicting {
conflicts.push(("VELESDB_MEMORY_EMBEDDER_URL", "VELESDB_MEMORY_OLLAMA_URL"));
}
if model.conflicting {
conflicts.push((
"VELESDB_MEMORY_EMBEDDER_MODEL",
"VELESDB_MEMORY_OLLAMA_MODEL",
));
}
let endpoint = RemoteEndpoint {
url: url.value,
model: model.value,
auth: role_auth("VELESDB_MEMORY_EMBEDDER_API_TOKEN")?,
};
Ok((endpoint, alias_conflict_notice(&conflicts)))
}
#[cfg(all(test, feature = "ollama"))]
#[path = "remote_endpoint_tests.rs"]
mod tests;