fix(config): align ollama cloud defaults with upstream
This commit is contained in:
@@ -7,7 +7,8 @@ use clap::Subcommand;
|
||||
use owlen_core::LlmProvider;
|
||||
use owlen_core::ProviderConfig;
|
||||
use owlen_core::config::{
|
||||
self as core_config, Config, OLLAMA_CLOUD_API_KEY_ENV, OLLAMA_CLOUD_BASE_URL,
|
||||
self as core_config, Config, LEGACY_OLLAMA_CLOUD_API_KEY_ENV,
|
||||
LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV, OLLAMA_API_KEY_ENV, OLLAMA_CLOUD_BASE_URL,
|
||||
OLLAMA_CLOUD_ENDPOINT_KEY, OLLAMA_MODE_KEY,
|
||||
};
|
||||
use owlen_core::credentials::{ApiCredentials, CredentialManager, OLLAMA_CLOUD_CREDENTIAL_ID};
|
||||
@@ -272,8 +273,15 @@ fn configure_cloud_endpoint(entry: &mut ProviderConfig, endpoint: &str, force: b
|
||||
Value::String(normalized.clone()),
|
||||
);
|
||||
|
||||
if entry.api_key_env.is_none() {
|
||||
entry.api_key_env = Some(OLLAMA_CLOUD_API_KEY_ENV.to_string());
|
||||
let should_update_env = match entry.api_key_env.as_deref() {
|
||||
None => true,
|
||||
Some(value) => {
|
||||
value.eq_ignore_ascii_case(LEGACY_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
|| value.eq_ignore_ascii_case(LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
}
|
||||
};
|
||||
if should_update_env {
|
||||
entry.api_key_env = Some(OLLAMA_API_KEY_ENV.to_string());
|
||||
}
|
||||
|
||||
if force
|
||||
|
||||
@@ -23,15 +23,15 @@ 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://api.ollama.com";
|
||||
pub const OLLAMA_CLOUD_BASE_URL: &str = "https://ollama.com";
|
||||
/// Legacy Ollama Cloud base URL (accepted for backward compatibility).
|
||||
pub const LEGACY_OLLAMA_CLOUD_BASE_URL: &str = "https://ollama.com";
|
||||
pub const LEGACY_OLLAMA_CLOUD_BASE_URL: &str = "https://api.ollama.com";
|
||||
/// Preferred environment variable used for Ollama Cloud authentication.
|
||||
pub const OWLEN_OLLAMA_CLOUD_API_KEY_ENV: &str = "OWLEN_OLLAMA_CLOUD_API_KEY";
|
||||
pub const OLLAMA_API_KEY_ENV: &str = "OLLAMA_API_KEY";
|
||||
/// Legacy environment variable accepted for backward compatibility.
|
||||
pub const LEGACY_OLLEN_OLLAMA_CLOUD_API_KEY_ENV: &str = "OLLEN_OLLAMA_CLOUD_API_KEY";
|
||||
/// Legacy environment variable still accepted for Ollama Cloud authentication.
|
||||
pub const OLLAMA_CLOUD_API_KEY_ENV: &str = "OLLAMA_CLOUD_API_KEY";
|
||||
pub const LEGACY_OLLAMA_CLOUD_API_KEY_ENV: &str = "OLLAMA_CLOUD_API_KEY";
|
||||
/// Legacy environment variable used by earlier Owlen releases.
|
||||
pub const LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV: &str = "OWLEN_OLLAMA_CLOUD_API_KEY";
|
||||
/// Default base URL for local Ollama daemons.
|
||||
pub const OLLAMA_LOCAL_BASE_URL: &str = "http://localhost:11434";
|
||||
/// Default OpenAI API base URL.
|
||||
@@ -645,6 +645,49 @@ impl Config {
|
||||
}
|
||||
|
||||
self.providers = migrated;
|
||||
|
||||
// If the legacy local provider was configured with the hosted base URL, promote the
|
||||
// settings to the cloud provider for backward compatibility.
|
||||
let enable_cloud_from_local = self
|
||||
.providers
|
||||
.get("ollama_local")
|
||||
.and_then(|cfg| cfg.base_url.as_ref())
|
||||
.map(|base| is_cloud_base_url(Some(base)))
|
||||
.unwrap_or(false);
|
||||
|
||||
if enable_cloud_from_local {
|
||||
let mut local_api_key = None;
|
||||
let mut local_api_key_env = None;
|
||||
if let Some(local) = self.providers.get_mut("ollama_local") {
|
||||
local_api_key = local.api_key.take();
|
||||
local_api_key_env = local.api_key_env.take();
|
||||
local.enabled = false;
|
||||
}
|
||||
|
||||
if let Some(cloud) = self.providers.get_mut("ollama_cloud") {
|
||||
if cloud.api_key.is_none() {
|
||||
cloud.api_key = local_api_key;
|
||||
}
|
||||
if cloud.api_key_env.is_none() {
|
||||
cloud.api_key_env = local_api_key_env;
|
||||
}
|
||||
|
||||
if cloud.base_url.is_none() {
|
||||
cloud.base_url = Some(OLLAMA_CLOUD_BASE_URL.to_string());
|
||||
}
|
||||
let update_api_key_env = match cloud.api_key_env.as_deref() {
|
||||
None => true,
|
||||
Some(value) => {
|
||||
value.eq_ignore_ascii_case(LEGACY_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
|| value.eq_ignore_ascii_case(LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
}
|
||||
};
|
||||
if update_api_key_env {
|
||||
cloud.api_key_env = Some(OLLAMA_API_KEY_ENV.to_string());
|
||||
}
|
||||
cloud.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_legacy_ollama_provider(
|
||||
@@ -687,13 +730,15 @@ impl Config {
|
||||
if cloud.base_url.is_none() {
|
||||
cloud.base_url = Some(OLLAMA_CLOUD_BASE_URL.to_string());
|
||||
}
|
||||
if cloud.api_key_env.is_none()
|
||||
|| cloud
|
||||
.api_key_env
|
||||
.as_deref()
|
||||
.is_some_and(|value| value == LEGACY_OLLEN_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
{
|
||||
cloud.api_key_env = Some(OWLEN_OLLAMA_CLOUD_API_KEY_ENV.to_string());
|
||||
let update_api_key_env = match cloud.api_key_env.as_deref() {
|
||||
None => true,
|
||||
Some(value) => {
|
||||
value.eq_ignore_ascii_case(LEGACY_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
|| value.eq_ignore_ascii_case(LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
}
|
||||
};
|
||||
if update_api_key_env {
|
||||
cloud.api_key_env = Some(OLLAMA_API_KEY_ENV.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -841,7 +886,7 @@ fn default_ollama_cloud_config() -> ProviderConfig {
|
||||
provider_type: canonical_provider_type("ollama_cloud"),
|
||||
base_url: Some(OLLAMA_CLOUD_BASE_URL.to_string()),
|
||||
api_key: None,
|
||||
api_key_env: Some(OWLEN_OLLAMA_CLOUD_API_KEY_ENV.to_string()),
|
||||
api_key_env: Some(OLLAMA_API_KEY_ENV.to_string()),
|
||||
extra,
|
||||
}
|
||||
}
|
||||
@@ -2013,7 +2058,7 @@ mod tests {
|
||||
.get("ollama_cloud")
|
||||
.expect("default cloud provider");
|
||||
assert!(!cloud.enabled);
|
||||
assert_eq!(cloud.api_key_env.as_deref(), Some(OLLAMA_CLOUD_API_KEY_ENV));
|
||||
assert_eq!(cloud.api_key_env.as_deref(), Some(OLLAMA_API_KEY_ENV));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2023,7 +2068,7 @@ mod tests {
|
||||
let cloud = ensure_provider_config(&mut config, "ollama-cloud");
|
||||
assert_eq!(cloud.provider_type, "ollama_cloud");
|
||||
assert_eq!(cloud.base_url.as_deref(), Some(OLLAMA_CLOUD_BASE_URL));
|
||||
assert_eq!(cloud.api_key_env.as_deref(), Some(OLLAMA_CLOUD_API_KEY_ENV));
|
||||
assert_eq!(cloud.api_key_env.as_deref(), Some(OLLAMA_API_KEY_ENV));
|
||||
assert!(config.providers.contains_key("ollama_cloud"));
|
||||
assert!(!config.providers.contains_key("ollama-cloud"));
|
||||
}
|
||||
@@ -2072,7 +2117,7 @@ mod tests {
|
||||
.expect("cloud provider created");
|
||||
assert!(cloud.enabled);
|
||||
assert_eq!(cloud.base_url.as_deref(), Some(OLLAMA_CLOUD_BASE_URL));
|
||||
assert_eq!(cloud.api_key_env.as_deref(), Some(OLLAMA_CLOUD_API_KEY_ENV));
|
||||
assert_eq!(cloud.api_key_env.as_deref(), Some(OLLAMA_API_KEY_ENV));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
//! Ollama provider built on top of the `ollama-rs` crate.
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
convert::TryFrom,
|
||||
env,
|
||||
net::{SocketAddr, TcpStream},
|
||||
pin::Pin,
|
||||
process::Command,
|
||||
sync::Arc,
|
||||
sync::{Arc, OnceLock},
|
||||
time::{Duration, Instant, SystemTime},
|
||||
};
|
||||
|
||||
@@ -29,7 +30,7 @@ use serde_json::{Map as JsonMap, Value, json};
|
||||
use tokio::{sync::RwLock, time::sleep};
|
||||
|
||||
#[cfg(test)]
|
||||
use std::sync::{Mutex, MutexGuard, OnceLock};
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
#[cfg(test)]
|
||||
use tokio_test::block_on;
|
||||
use uuid::Uuid;
|
||||
@@ -37,8 +38,8 @@ use uuid::Uuid;
|
||||
use crate::{
|
||||
Error, Result,
|
||||
config::{
|
||||
GeneralSettings, LEGACY_OLLEN_OLLAMA_CLOUD_API_KEY_ENV, OLLAMA_CLOUD_BASE_URL,
|
||||
OLLAMA_CLOUD_ENDPOINT_KEY, OLLAMA_MODE_KEY, OWLEN_OLLAMA_CLOUD_API_KEY_ENV,
|
||||
GeneralSettings, LEGACY_OLLAMA_CLOUD_API_KEY_ENV, LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV,
|
||||
OLLAMA_API_KEY_ENV, OLLAMA_CLOUD_BASE_URL, OLLAMA_CLOUD_ENDPOINT_KEY, OLLAMA_MODE_KEY,
|
||||
},
|
||||
llm::{LlmProvider, ProviderConfig},
|
||||
mcp::McpToolDescriptor,
|
||||
@@ -57,6 +58,17 @@ const LOCAL_TAGS_TIMEOUT_STEPS_MS: [u64; 3] = [400, 800, 1_600];
|
||||
const LOCAL_TAGS_RETRY_DELAYS_MS: [u64; 2] = [150, 300];
|
||||
const HEALTHCHECK_TIMEOUT_MS: u64 = 1_000;
|
||||
|
||||
static LEGACY_CLOUD_ENV_WARNING: OnceLock<()> = OnceLock::new();
|
||||
|
||||
fn warn_legacy_cloud_env(var_name: &str) {
|
||||
if LEGACY_CLOUD_ENV_WARNING.set(()).is_ok() {
|
||||
warn!(
|
||||
"Using legacy Ollama Cloud API key environment variable `{var_name}`. \
|
||||
Prefer configuring OLLAMA_API_KEY; legacy names remain supported but may be removed."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
enum OllamaMode {
|
||||
Local,
|
||||
@@ -390,10 +402,15 @@ impl OllamaProvider {
|
||||
|
||||
let mut api_key = resolve_api_key(config.api_key.clone())
|
||||
.or_else(|| resolve_api_key_env_hint(config.api_key_env.as_deref()))
|
||||
.or_else(|| env_var_non_empty(OWLEN_OLLAMA_CLOUD_API_KEY_ENV))
|
||||
.or_else(|| env_var_non_empty(LEGACY_OLLEN_OLLAMA_CLOUD_API_KEY_ENV))
|
||||
.or_else(|| env_var_non_empty("OLLAMA_API_KEY"))
|
||||
.or_else(|| env_var_non_empty("OLLAMA_CLOUD_API_KEY"));
|
||||
.or_else(|| env_var_non_empty(OLLAMA_API_KEY_ENV))
|
||||
.or_else(|| {
|
||||
warn_legacy_cloud_env(LEGACY_OLLAMA_CLOUD_API_KEY_ENV);
|
||||
env_var_non_empty(LEGACY_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
})
|
||||
.or_else(|| {
|
||||
warn_legacy_cloud_env(LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV);
|
||||
env_var_non_empty(LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
});
|
||||
let api_key_present = api_key.is_some();
|
||||
|
||||
let configured_mode = configured_mode_from_extra(config);
|
||||
@@ -429,7 +446,7 @@ impl OllamaProvider {
|
||||
if matches!(variant, ProviderVariant::Cloud) {
|
||||
if !api_key_present {
|
||||
return Err(Error::Config(
|
||||
"Ollama Cloud API key not configured. Set providers.ollama_cloud.api_key or OLLAMA_CLOUD_API_KEY."
|
||||
"Ollama Cloud API key not configured. Set providers.ollama_cloud.api_key or export OLLAMA_API_KEY (legacy: OLLAMA_CLOUD_API_KEY / OWLEN_OLLAMA_CLOUD_API_KEY)."
|
||||
.into(),
|
||||
));
|
||||
}
|
||||
@@ -1247,12 +1264,20 @@ impl OllamaProvider {
|
||||
|
||||
let description = build_model_description(scope_tag, detail.as_ref());
|
||||
|
||||
let context_window = detail.as_ref().and_then(|info| {
|
||||
pick_first_u64(
|
||||
&info.model_info,
|
||||
&["context_length", "num_ctx", "max_context"],
|
||||
)
|
||||
.and_then(|raw| u32::try_from(raw).ok())
|
||||
});
|
||||
|
||||
ModelInfo {
|
||||
id: name.clone(),
|
||||
name,
|
||||
description: Some(description),
|
||||
provider: self.provider_name.clone(),
|
||||
context_window: None,
|
||||
context_window,
|
||||
capabilities,
|
||||
supports_tools: false,
|
||||
}
|
||||
@@ -1771,10 +1796,18 @@ fn env_var_non_empty(name: &str) -> Option<String> {
|
||||
}
|
||||
|
||||
fn resolve_api_key_env_hint(env_var: Option<&str>) -> Option<String> {
|
||||
env_var
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.and_then(env_var_non_empty)
|
||||
let var = env_var?.trim();
|
||||
if var.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if var.eq_ignore_ascii_case(LEGACY_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
|| var.eq_ignore_ascii_case(LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
{
|
||||
warn_legacy_cloud_env(var);
|
||||
}
|
||||
|
||||
env_var_non_empty(var)
|
||||
}
|
||||
|
||||
fn resolve_api_key(configured: Option<String>) -> Option<String> {
|
||||
@@ -1838,6 +1871,15 @@ fn normalize_base_url(
|
||||
return Err("Ollama base URLs must not include additional path segments".to_string());
|
||||
}
|
||||
|
||||
if mode_hint == OllamaMode::Cloud {
|
||||
if let Some(host) = url.host_str() {
|
||||
if host.eq_ignore_ascii_case("api.ollama.com") {
|
||||
url.set_host(Some("ollama.com"))
|
||||
.map_err(|err| format!("Failed to normalise Ollama Cloud host: {err}"))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
url.set_query(None);
|
||||
url.set_fragment(None);
|
||||
|
||||
@@ -1900,6 +1942,7 @@ fn build_client_for_base(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use serde_json::{Map as JsonMap, Value};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
@@ -1930,6 +1973,12 @@ mod tests {
|
||||
assert_eq!(url, "https://ollama.com");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_base_url_canonicalises_api_hostname() {
|
||||
let url = normalize_base_url(Some("https://api.ollama.com"), OllamaMode::Cloud).unwrap();
|
||||
assert_eq!(url, "https://ollama.com");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_base_url_rejects_cloud_without_https() {
|
||||
let err = normalize_base_url(Some("http://ollama.com"), OllamaMode::Cloud).unwrap_err();
|
||||
@@ -2088,6 +2137,34 @@ mod tests {
|
||||
assert_eq!(models[0].name, "llama3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn convert_model_propagates_context_window_from_details() {
|
||||
let provider = OllamaProvider::new("http://localhost:11434").expect("provider constructed");
|
||||
let local = LocalModel {
|
||||
name: "gemma3n:e4b".into(),
|
||||
modified_at: "2024-01-01T00:00:00Z".into(),
|
||||
size: 0,
|
||||
};
|
||||
|
||||
let mut meta = JsonMap::new();
|
||||
meta.insert(
|
||||
"context_length".into(),
|
||||
Value::Number(serde_json::Number::from(32_768)),
|
||||
);
|
||||
|
||||
let detail = OllamaModelInfo {
|
||||
license: String::new(),
|
||||
modelfile: String::new(),
|
||||
parameters: String::new(),
|
||||
template: String::new(),
|
||||
model_info: meta,
|
||||
capabilities: vec![],
|
||||
};
|
||||
|
||||
let info = provider.convert_model(OllamaMode::Local, local, Some(detail));
|
||||
assert_eq!(info.context_window, Some(32_768));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fetch_scope_tags_with_retry_retries_on_timeout_then_succeeds() {
|
||||
let provider = OllamaProvider::new("http://localhost:11434").expect("provider constructed");
|
||||
|
||||
@@ -18,3 +18,4 @@ serde_json = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-stream = { workspace = true }
|
||||
reqwest = { package = "reqwest", version = "0.11", features = ["json", "stream"] }
|
||||
log = { workspace = true }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::{env, time::Duration};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use log::warn;
|
||||
use owlen_core::{
|
||||
Error as CoreError, Result as CoreResult,
|
||||
config::OLLAMA_CLOUD_BASE_URL,
|
||||
@@ -13,7 +14,9 @@ use serde_json::{Number, Value};
|
||||
|
||||
use super::OllamaClient;
|
||||
|
||||
const API_KEY_ENV: &str = "OLLAMA_CLOUD_API_KEY";
|
||||
const API_KEY_ENV: &str = "OLLAMA_API_KEY";
|
||||
const LEGACY_API_KEY_ENV: &str = "OLLAMA_CLOUD_API_KEY";
|
||||
const LEGACY_OWLEN_API_KEY_ENV: &str = "OWLEN_OLLAMA_CLOUD_API_KEY";
|
||||
|
||||
/// ModelProvider implementation for the hosted Ollama Cloud service.
|
||||
pub struct OllamaCloudProvider {
|
||||
@@ -22,7 +25,7 @@ pub struct OllamaCloudProvider {
|
||||
|
||||
impl OllamaCloudProvider {
|
||||
/// Construct a new cloud provider. An API key must be supplied either
|
||||
/// directly or via the `OLLAMA_CLOUD_API_KEY` environment variable.
|
||||
/// directly or via the `OLLAMA_API_KEY` environment variable.
|
||||
pub fn new(
|
||||
base_url: Option<String>,
|
||||
api_key: Option<String>,
|
||||
@@ -95,14 +98,34 @@ fn resolve_api_key(api_key: Option<String>) -> CoreResult<(String, &'static str)
|
||||
let key_from_env = env::var(API_KEY_ENV)
|
||||
.ok()
|
||||
.map(|value| value.trim().to_string())
|
||||
.filter(|value| !value.is_empty());
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(|value| (value, API_KEY_ENV))
|
||||
.or_else(|| {
|
||||
env::var(LEGACY_API_KEY_ENV)
|
||||
.ok()
|
||||
.map(|value| value.trim().to_string())
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(|value| (value, LEGACY_API_KEY_ENV))
|
||||
})
|
||||
.or_else(|| {
|
||||
env::var(LEGACY_OWLEN_API_KEY_ENV)
|
||||
.ok()
|
||||
.map(|value| value.trim().to_string())
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(|value| (value, LEGACY_OWLEN_API_KEY_ENV))
|
||||
});
|
||||
|
||||
if let Some(key) = key_from_env {
|
||||
if let Some((key, source_env)) = key_from_env {
|
||||
if source_env != API_KEY_ENV {
|
||||
warn!(
|
||||
"Using legacy Ollama Cloud API key environment variable `{source_env}`. Prefer OLLAMA_API_KEY."
|
||||
);
|
||||
}
|
||||
return Ok((key, "env"));
|
||||
}
|
||||
|
||||
Err(CoreError::Config(
|
||||
"Ollama Cloud API key not configured. Set OLLAMA_CLOUD_API_KEY or configure an API key."
|
||||
"Ollama Cloud API key not configured. Set OLLAMA_API_KEY (legacy: OLLAMA_CLOUD_API_KEY / OWLEN_OLLAMA_CLOUD_API_KEY) or configure an API key."
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -63,7 +63,8 @@ use crate::ui::format_tool_output;
|
||||
use crate::widgets::model_picker::FilterMode;
|
||||
use crate::{commands, highlight};
|
||||
use owlen_core::config::{
|
||||
OLLAMA_CLOUD_API_KEY_ENV, OLLAMA_CLOUD_BASE_URL, OLLAMA_CLOUD_ENDPOINT_KEY, OLLAMA_MODE_KEY,
|
||||
LEGACY_OLLAMA_CLOUD_API_KEY_ENV, LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV, OLLAMA_API_KEY_ENV,
|
||||
OLLAMA_CLOUD_BASE_URL, OLLAMA_CLOUD_ENDPOINT_KEY, OLLAMA_MODE_KEY,
|
||||
};
|
||||
use owlen_core::credentials::{ApiCredentials, OLLAMA_CLOUD_CREDENTIAL_ID};
|
||||
// Agent executor moved to separate binary `owlen-agent`. The TUI no longer directly
|
||||
@@ -9745,8 +9746,15 @@ impl ChatApp {
|
||||
let existing = entry.api_key.clone();
|
||||
entry.enabled = true;
|
||||
entry.provider_type = "ollama_cloud".to_string();
|
||||
if entry.api_key_env.is_none() {
|
||||
entry.api_key_env = Some(OLLAMA_CLOUD_API_KEY_ENV.to_string());
|
||||
let should_update_env = match entry.api_key_env.as_deref() {
|
||||
None => true,
|
||||
Some(value) => {
|
||||
value.eq_ignore_ascii_case(LEGACY_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
|| value.eq_ignore_ascii_case(LEGACY_OWLEN_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
}
|
||||
};
|
||||
if should_update_env {
|
||||
entry.api_key_env = Some(OLLAMA_API_KEY_ENV.to_string());
|
||||
}
|
||||
let requested = options
|
||||
.endpoint
|
||||
|
||||
Reference in New Issue
Block a user