diff --git a/agents.md b/agents.md index 94a5d46..ed9b933 100644 --- a/agents.md +++ b/agents.md @@ -1,5 +1,4 @@ # Agents Upgrade Plan -- refactor: simplify provider/session coupling so compute_web_search_settings shares normalization utilities - docs: clarify cloud vs local env configuration (api key precedence, insecure toggle) in configuration guide - ci: add targeted regression job for ollama providers covering chat, streaming, and tool execution paths diff --git a/crates/owlen-core/src/providers/ollama.rs b/crates/owlen-core/src/providers/ollama.rs index 71acde9..e7fdf69 100644 --- a/crates/owlen-core/src/providers/ollama.rs +++ b/crates/owlen-core/src/providers/ollama.rs @@ -2025,6 +2025,10 @@ fn map_reqwest_error(action: &str, err: reqwest::Error) -> Error { } } +pub(crate) fn normalize_cloud_base_url(input: Option<&str>) -> std::result::Result { + normalize_base_url(input, OllamaMode::Cloud) +} + fn normalize_base_url( input: Option<&str>, mode_hint: OllamaMode, diff --git a/crates/owlen-core/src/session.rs b/crates/owlen-core/src/session.rs index d324d69..86a0de3 100644 --- a/crates/owlen-core/src/session.rs +++ b/crates/owlen-core/src/session.rs @@ -19,6 +19,7 @@ use crate::mode::Mode; use crate::model::{DetailedModelInfo, ModelManager}; use crate::oauth::{DeviceAuthorization, DevicePollState, OAuthClient}; use crate::providers::OllamaProvider; +use crate::providers::ollama::normalize_cloud_base_url; use crate::storage::{SessionMeta, StorageManager}; use crate::tools::{WEB_SEARCH_TOOL_NAME, canonical_tool_name, tool_name_matches}; use crate::types::{ @@ -187,11 +188,17 @@ fn compute_web_search_settings( return Ok(None); } - let base_url = provider_config + let raw_base_url = provider_config .base_url .as_deref() - .filter(|value| !value.trim().is_empty()) - .unwrap_or(OLLAMA_CLOUD_BASE_URL); + .filter(|value| !value.trim().is_empty()); + let normalized_base_url = normalize_cloud_base_url(raw_base_url).map_err(|err| { + let display_base = raw_base_url.unwrap_or(OLLAMA_CLOUD_BASE_URL); + Error::Config(format!( + "Invalid Ollama Cloud base_url '{}': {err}", + display_base + )) + })?; let endpoint = provider_config .extra @@ -199,7 +206,7 @@ fn compute_web_search_settings( .and_then(|value| value.as_str()) .unwrap_or("/api/web_search"); - let endpoint_url = build_search_url(base_url, endpoint)?; + let endpoint_url = build_search_url(&normalized_base_url, endpoint)?; let api_key = resolve_web_search_api_key(provider_config) .or_else(|| env_var_non_empty(OLLAMA_API_KEY_ENV)) diff --git a/crates/owlen-core/tests/ollama_wiremock.rs b/crates/owlen-core/tests/ollama_wiremock.rs index bdaeff6..d456385 100644 --- a/crates/owlen-core/tests/ollama_wiremock.rs +++ b/crates/owlen-core/tests/ollama_wiremock.rs @@ -373,7 +373,7 @@ async fn cloud_tool_call_flows_through_web_search() { #[tokio::test(flavor = "multi_thread")] async fn cloud_tool_call_accepts_v1_base_url() { - run_cloud_tool_flow("/v1", Some("/web/search"), "/v1/web/search").await; + run_cloud_tool_flow("/v1", Some("/web/search"), "/web/search").await; } #[tokio::test(flavor = "multi_thread")]