feat(ollama): add explicit Ollama mode config, cloud endpoint storage, and scope‑availability caching with status annotations.
This commit is contained in:
@@ -16,7 +16,14 @@ use std::time::Duration;
|
||||
pub const DEFAULT_CONFIG_PATH: &str = "~/.config/owlen/config.toml";
|
||||
|
||||
/// Current schema version written to `config.toml`.
|
||||
pub const CONFIG_SCHEMA_VERSION: &str = "1.4.0";
|
||||
pub const CONFIG_SCHEMA_VERSION: &str = "1.5.0";
|
||||
|
||||
/// Provider config key for forcing Ollama provider mode.
|
||||
pub const OLLAMA_MODE_KEY: &str = "ollama_mode";
|
||||
/// Extra config key storing the preferred Ollama Cloud endpoint.
|
||||
pub const OLLAMA_CLOUD_ENDPOINT_KEY: &str = "cloud_endpoint";
|
||||
/// Canonical Ollama Cloud base URL.
|
||||
pub const OLLAMA_CLOUD_BASE_URL: &str = "https://ollama.com";
|
||||
|
||||
/// Core configuration shared by all OWLEN clients
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -574,6 +581,23 @@ impl Config {
|
||||
self.merge_legacy_ollama_provider(legacy_cloud);
|
||||
}
|
||||
|
||||
if let Some(ollama) = self.providers.get_mut("ollama") {
|
||||
let previous_mode = ollama
|
||||
.extra
|
||||
.get(OLLAMA_MODE_KEY)
|
||||
.and_then(|value| value.as_str())
|
||||
.map(|value| value.to_ascii_lowercase());
|
||||
ensure_ollama_mode_extra(ollama);
|
||||
if previous_mode.as_deref().unwrap_or("auto") == "auto"
|
||||
&& is_cloud_base_url(ollama.base_url.as_ref())
|
||||
{
|
||||
ollama.extra.insert(
|
||||
OLLAMA_MODE_KEY.to_string(),
|
||||
serde_json::Value::String("cloud".to_string()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.schema_version = CONFIG_SCHEMA_VERSION.to_string();
|
||||
}
|
||||
|
||||
@@ -594,9 +618,12 @@ impl Config {
|
||||
if target.extra.is_empty() && !legacy_cloud.extra.is_empty() {
|
||||
target.extra = legacy_cloud.extra;
|
||||
}
|
||||
ensure_ollama_mode_extra(target);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(legacy_cloud);
|
||||
let mut inserted = legacy_cloud;
|
||||
ensure_ollama_mode_extra(&mut inserted);
|
||||
entry.insert(inserted);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -669,12 +696,47 @@ impl Config {
|
||||
}
|
||||
|
||||
fn default_ollama_provider_config() -> ProviderConfig {
|
||||
ProviderConfig {
|
||||
let mut config = ProviderConfig {
|
||||
provider_type: "ollama".to_string(),
|
||||
base_url: Some("http://localhost:11434".to_string()),
|
||||
api_key: None,
|
||||
extra: HashMap::new(),
|
||||
};
|
||||
ensure_ollama_mode_extra(&mut config);
|
||||
config
|
||||
}
|
||||
|
||||
fn ensure_ollama_mode_extra(provider: &mut ProviderConfig) {
|
||||
if provider.provider_type != "ollama" {
|
||||
return;
|
||||
}
|
||||
|
||||
let entry = provider
|
||||
.extra
|
||||
.entry(OLLAMA_MODE_KEY.to_string())
|
||||
.or_insert_with(|| serde_json::Value::String("auto".to_string()));
|
||||
|
||||
if let Some(value) = entry.as_str() {
|
||||
let normalized = value.trim().to_ascii_lowercase();
|
||||
if matches!(normalized.as_str(), "auto" | "local" | "cloud") {
|
||||
if normalized != value {
|
||||
*entry = serde_json::Value::String(normalized);
|
||||
}
|
||||
} else {
|
||||
*entry = serde_json::Value::String("auto".to_string());
|
||||
}
|
||||
} else {
|
||||
*entry = serde_json::Value::String("auto".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
fn is_cloud_base_url(base_url: Option<&String>) -> bool {
|
||||
base_url
|
||||
.map(|url| {
|
||||
let trimmed = url.trim_end_matches('/');
|
||||
trimmed == OLLAMA_CLOUD_BASE_URL || trimmed.starts_with("https://ollama.com/")
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn validate_mcp_server_entry(server: &McpServerConfig, scope: McpConfigScope) -> Result<()> {
|
||||
@@ -1603,9 +1665,11 @@ pub fn ensure_provider_config<'a>(
|
||||
}
|
||||
|
||||
match config.providers.entry(provider_name.to_string()) {
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
Entry::Occupied(mut entry) => {
|
||||
ensure_ollama_mode_extra(entry.get_mut());
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
let default = match provider_name {
|
||||
let mut default = match provider_name {
|
||||
"ollama" => default_ollama_provider_config(),
|
||||
other => ProviderConfig {
|
||||
provider_type: other.to_string(),
|
||||
@@ -1614,9 +1678,15 @@ pub fn ensure_provider_config<'a>(
|
||||
extra: HashMap::new(),
|
||||
},
|
||||
};
|
||||
entry.insert(default)
|
||||
ensure_ollama_mode_extra(&mut default);
|
||||
entry.insert(default);
|
||||
}
|
||||
}
|
||||
|
||||
config
|
||||
.providers
|
||||
.get(provider_name)
|
||||
.expect("provider entry must exist")
|
||||
}
|
||||
|
||||
/// Calculate absolute timeout for session data based on configuration
|
||||
@@ -1723,6 +1793,14 @@ mod tests {
|
||||
fn default_config_contains_local_provider() {
|
||||
let config = Config::default();
|
||||
assert!(config.providers.contains_key("ollama"));
|
||||
let provider = config.providers.get("ollama").unwrap();
|
||||
assert_eq!(
|
||||
provider
|
||||
.extra
|
||||
.get(OLLAMA_MODE_KEY)
|
||||
.and_then(|value| value.as_str()),
|
||||
Some("auto")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1732,6 +1810,13 @@ mod tests {
|
||||
let cloud = ensure_provider_config(&mut config, "ollama-cloud");
|
||||
assert_eq!(cloud.provider_type, "ollama");
|
||||
assert_eq!(cloud.base_url.as_deref(), Some("http://localhost:11434"));
|
||||
assert_eq!(
|
||||
cloud
|
||||
.extra
|
||||
.get(OLLAMA_MODE_KEY)
|
||||
.and_then(|value| value.as_str()),
|
||||
Some("auto")
|
||||
);
|
||||
assert!(config.providers.contains_key("ollama"));
|
||||
assert!(!config.providers.contains_key("ollama-cloud"));
|
||||
}
|
||||
@@ -1758,6 +1843,33 @@ mod tests {
|
||||
assert_eq!(cloud.provider_type, "ollama");
|
||||
assert_eq!(cloud.base_url.as_deref(), Some("https://api.ollama.com"));
|
||||
assert_eq!(cloud.api_key.as_deref(), Some("secret"));
|
||||
assert_eq!(
|
||||
cloud
|
||||
.extra
|
||||
.get(OLLAMA_MODE_KEY)
|
||||
.and_then(|value| value.as_str()),
|
||||
Some("auto")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn migration_sets_cloud_mode_for_cloud_base() {
|
||||
let mut config = Config::default();
|
||||
if let Some(ollama) = config.providers.get_mut("ollama") {
|
||||
ollama.base_url = Some(OLLAMA_CLOUD_BASE_URL.to_string());
|
||||
ollama.extra.remove(OLLAMA_MODE_KEY);
|
||||
}
|
||||
|
||||
config.apply_schema_migrations("1.4.0");
|
||||
|
||||
let provider = config.providers.get("ollama").expect("ollama provider");
|
||||
assert_eq!(
|
||||
provider
|
||||
.extra
|
||||
.get(OLLAMA_MODE_KEY)
|
||||
.and_then(|value| value.as_str()),
|
||||
Some("cloud")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user