Skip to content

Commit cabd3de

Browse files
Allow ZEROCLAW_PROVIDER_URL env variable to override api_url (zeroclaw-labs#3414)
* Ignore JetBrains .idea folder * fix(ollama): support stringified JSON tool call arguments * providers: allow ZEROCLAW_PROVIDER_URL env var to override Ollama base URL Supports container deployments where Ollama runs on a Docker network host (e.g. http://ollama:11434) without requiring config.toml changes. Includes regression test ensuring the environment override works. * fix(clippy): replace Default::default() with ProviderRuntimeOptions::default() --------- Co-authored-by: Argenis <theonlyhennygod@gmail.com>
1 parent 87cf6b0 commit cabd3de

3 files changed

Lines changed: 52 additions & 6 deletions

File tree

β€Ž.gitignoreβ€Ž

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,6 @@ credentials.json
4141

4242
# Coverage artifacts
4343
lcov.info
44+
45+
# IDE's stuff
46+
.idea

β€Žsrc/providers/mod.rsβ€Ž

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,11 +1074,20 @@ fn create_provider_with_url_and_options(
10741074
"anthropic" => Ok(Box::new(anthropic::AnthropicProvider::new(key))),
10751075
"openai" => Ok(Box::new(openai::OpenAiProvider::with_base_url(api_url, key))),
10761076
// Ollama uses api_url for custom base URL (e.g. remote Ollama instance)
1077-
"ollama" => Ok(Box::new(ollama::OllamaProvider::new_with_reasoning(
1078-
api_url,
1079-
key,
1080-
options.reasoning_enabled,
1081-
))),
1077+
"ollama" => {
1078+
1079+
let env_url = std::env::var("ZEROCLAW_PROVIDER_URL").ok();
1080+
1081+
let api_url = env_url
1082+
.as_deref()
1083+
.or(api_url);
1084+
1085+
Ok(Box::new(ollama::OllamaProvider::new_with_reasoning(
1086+
api_url,
1087+
key,
1088+
options.reasoning_enabled,
1089+
)))
1090+
},
10821091
"gemini" | "google" | "google-gemini" => {
10831092
let state_dir = options
10841093
.zeroclaw_dir
@@ -3104,4 +3113,22 @@ mod tests {
31043113
assert_eq!(options.extra_headers.len(), 1);
31053114
assert_eq!(options.extra_headers.get("X-Title").unwrap(), "zeroclaw");
31063115
}
3116+
3117+
#[test]
3118+
fn env_provider_url_overrides_api_url() {
3119+
std::env::set_var("ZEROCLAW_PROVIDER_URL", "http://env-ollama:11434");
3120+
3121+
let options = ProviderRuntimeOptions::default();
3122+
3123+
let provider = create_provider_with_url_and_options(
3124+
"ollama",
3125+
Some("http://config-ollama:11434"),
3126+
None,
3127+
&options,
3128+
);
3129+
3130+
assert!(provider.is_ok());
3131+
3132+
std::env::remove_var("ZEROCLAW_PROVIDER_URL");
3133+
}
31073134
}

β€Žsrc/providers/ollama.rsβ€Ž

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,26 @@ struct OllamaToolCall {
8989
#[derive(Debug, Deserialize)]
9090
struct OllamaFunction {
9191
name: String,
92-
#[serde(default)]
92+
#[serde(default, deserialize_with = "deserialize_args")]
9393
arguments: serde_json::Value,
9494
}
9595

96+
// ─── serde Helpers ───────────────────────────────────────────────────────────
97+
fn deserialize_args<'de, D>(deserializer: D) -> Result<serde_json::Value, D::Error>
98+
where
99+
D: serde::Deserializer<'de>,
100+
{
101+
let value = serde_json::Value::deserialize(deserializer)?;
102+
103+
if let Some(s) = value.as_str() {
104+
match serde_json::from_str::<serde_json::Value>(s) {
105+
Ok(v) => Ok(v),
106+
Err(_) => Ok(serde_json::json!({})),
107+
}
108+
} else {
109+
Ok(value)
110+
}
111+
}
96112
// ─── Implementation ───────────────────────────────────────────────────────────
97113

98114
impl OllamaProvider {

0 commit comments

Comments
Β (0)