Skip to content

Commit e421594

Browse files
authored
Merge branch 'RightNow-AI:main' into build/armv7
2 parents 8b925d8 + 618e837 commit e421594

File tree

9 files changed

+272
-65
lines changed

9 files changed

+272
-65
lines changed

Cargo.lock

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ members = [
1818
]
1919

2020
[workspace.package]
21-
version = "0.5.1"
21+
version = "0.5.5"
2222
edition = "2021"
2323
license = "Apache-2.0 OR MIT"
2424
repository = "https://github.com/RightNow-AI/openfang"

crates/openfang-desktop/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "OpenFang",
4-
"version": "0.1.0",
4+
"version": "0.5.5",
55
"identifier": "ai.openfang.desktop",
66
"build": {},
77
"app": {

crates/openfang-kernel/src/kernel.rs

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -877,40 +877,77 @@ impl OpenFangKernel {
877877
None
878878
}
879879
}
880-
} else if std::env::var("OPENAI_API_KEY").is_ok() {
881-
let model = if configured_model == "all-MiniLM-L6-v2" {
882-
default_embedding_model_for_provider("openai")
883-
} else {
884-
configured_model.as_str()
885-
};
886-
let openai_url = config.provider_urls.get("openai").map(|s| s.as_str());
887-
match create_embedding_driver("openai", model, "OPENAI_API_KEY", openai_url) {
888-
Ok(d) => {
889-
info!(model = %model, "Embedding driver auto-detected: OpenAI");
890-
Some(Arc::from(d))
891-
}
892-
Err(e) => {
893-
warn!(error = %e, "OpenAI embedding auto-detect failed");
894-
None
895-
}
896-
}
897880
} else {
898-
// Try Ollama (local, no key needed)
899-
let model = if configured_model == "all-MiniLM-L6-v2" {
900-
default_embedding_model_for_provider("ollama")
881+
// Auto-detect embedding provider by checking API key env vars in
882+
// priority order. First match wins.
883+
const API_KEY_PROVIDERS: &[(&str, &str)] = &[
884+
("OPENAI_API_KEY", "openai"),
885+
("GROQ_API_KEY", "groq"),
886+
("MISTRAL_API_KEY", "mistral"),
887+
("TOGETHER_API_KEY", "together"),
888+
("FIREWORKS_API_KEY", "fireworks"),
889+
("COHERE_API_KEY", "cohere"),
890+
];
891+
892+
let detected_from_key = API_KEY_PROVIDERS
893+
.iter()
894+
.find(|(env_var, _)| std::env::var(env_var).is_ok())
895+
.and_then(|(env_var, provider)| {
896+
let model = if configured_model == "all-MiniLM-L6-v2" {
897+
default_embedding_model_for_provider(provider)
898+
} else {
899+
configured_model.as_str()
900+
};
901+
let custom_url = config.provider_urls.get(*provider).map(|s| s.as_str());
902+
match create_embedding_driver(provider, model, env_var, custom_url) {
903+
Ok(d) => {
904+
info!(provider = %provider, model = %model, "Embedding driver auto-detected via {}", env_var);
905+
Some(Arc::from(d))
906+
}
907+
Err(e) => {
908+
warn!(provider = %provider, error = %e, "Embedding auto-detect failed for {}", provider);
909+
None
910+
}
911+
}
912+
});
913+
914+
if detected_from_key.is_some() {
915+
detected_from_key
901916
} else {
902-
configured_model.as_str()
903-
};
904-
let ollama_url = config.provider_urls.get("ollama").map(|s| s.as_str());
905-
match create_embedding_driver("ollama", model, "", ollama_url) {
906-
Ok(d) => {
907-
info!(model = %model, "Embedding driver auto-detected: Ollama (local)");
908-
Some(Arc::from(d))
917+
// No API key found — try local providers in order:
918+
// Ollama, vLLM, LM Studio (no key needed).
919+
const LOCAL_PROVIDERS: &[&str] = &["ollama", "vllm", "lmstudio"];
920+
921+
let mut local_result = None;
922+
for provider in LOCAL_PROVIDERS {
923+
let model = if configured_model == "all-MiniLM-L6-v2" {
924+
default_embedding_model_for_provider(provider)
925+
} else {
926+
configured_model.as_str()
927+
};
928+
let custom_url = config.provider_urls.get(*provider).map(|s| s.as_str());
929+
match create_embedding_driver(provider, model, "", custom_url) {
930+
Ok(d) => {
931+
info!(provider = %provider, model = %model, "Embedding driver auto-detected: {} (local)", provider);
932+
local_result = Some(Arc::from(d));
933+
break;
934+
}
935+
Err(e) => {
936+
debug!(provider = %provider, error = %e, "Local embedding provider {} not available", provider);
937+
}
938+
}
909939
}
910-
Err(e) => {
911-
debug!("No embedding driver available (Ollama probe failed: {e}) — using text search fallback");
912-
None
940+
941+
if local_result.is_none() {
942+
warn!(
943+
"No embedding provider available. Memory recall will use text search only. \
944+
Configure [memory] embedding_provider in config.toml or set an API key \
945+
(OPENAI_API_KEY, GROQ_API_KEY, MISTRAL_API_KEY, TOGETHER_API_KEY, \
946+
FIREWORKS_API_KEY, COHERE_API_KEY)."
947+
);
913948
}
949+
950+
local_result
914951
}
915952
}
916953
};
@@ -5663,7 +5700,10 @@ fn apply_budget_defaults(
56635700
fn default_embedding_model_for_provider(provider: &str) -> &'static str {
56645701
match provider {
56655702
"openai" => "text-embedding-3-small",
5703+
"groq" => "nomic-embed-text",
56665704
"mistral" => "mistral-embed",
5705+
"together" => "togethercomputer/m2-bert-80M-8k-retrieval",
5706+
"fireworks" => "nomic-ai/nomic-embed-text-v1.5",
56675707
"cohere" => "embed-english-v3.0",
56685708
// Local providers use nomic-embed-text as a good default
56695709
"ollama" | "vllm" | "lmstudio" => "nomic-embed-text",

crates/openfang-runtime/src/browser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ pub async fn tool_browser_navigate(
877877
agent_id: &str,
878878
) -> Result<String, String> {
879879
let url = input["url"].as_str().ok_or("Missing 'url' parameter")?;
880-
crate::web_fetch::check_ssrf(url)?;
880+
crate::web_fetch::check_ssrf(url, &[])?;
881881

882882
let resp = mgr
883883
.send_command(

crates/openfang-runtime/src/model_catalog.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,8 @@ impl ModelCatalog {
372372
display_name: display,
373373
provider: provider.to_string(),
374374
tier: ModelTier::Local,
375-
context_window: 32_768,
376-
max_output_tokens: 4_096,
375+
context_window: 131_072,
376+
max_output_tokens: 16_384,
377377
input_cost_per_m: 0.0,
378378
output_cost_per_m: 0.0,
379379
supports_tools: true,

crates/openfang-runtime/src/tool_runner.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2477,7 +2477,7 @@ async fn tool_a2a_discover(input: &serde_json::Value) -> Result<String, String>
24772477
let url = input["url"].as_str().ok_or("Missing 'url' parameter")?;
24782478

24792479
// SSRF protection: block private/metadata IPs
2480-
if crate::web_fetch::check_ssrf(url).is_err() {
2480+
if crate::web_fetch::check_ssrf(url, &[]).is_err() {
24812481
return Err("SSRF blocked: URL resolves to a private or metadata address".to_string());
24822482
}
24832483

@@ -2500,7 +2500,7 @@ async fn tool_a2a_send(
25002500
// Resolve agent URL: either directly provided or looked up by name
25012501
let url = if let Some(url) = input["agent_url"].as_str() {
25022502
// SSRF protection
2503-
if crate::web_fetch::check_ssrf(url).is_err() {
2503+
if crate::web_fetch::check_ssrf(url, &[]).is_err() {
25042504
return Err("SSRF blocked: URL resolves to a private or metadata address".to_string());
25052505
}
25062506
url.to_string()

0 commit comments

Comments
 (0)