mirror of
https://github.com/RightNow-AI/openfang.git
synced 2026-07-30 06:32:17 +00:00
issue fixes
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.3.10"
|
||||
version = "0.3.11"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
repository = "https://github.com/RightNow-AI/openfang"
|
||||
|
||||
@@ -3067,7 +3067,7 @@ args = ["-y", "@modelcontextprotocol/server-filesystem", "/path"]</pre>
|
||||
</div>
|
||||
<div class="table-wrap" x-show="filteredModels.length">
|
||||
<table>
|
||||
<thead><tr><th>Model</th><th>Provider</th><th>Tier</th><th>Context</th><th>Input Cost</th><th>Output Cost</th><th>Status</th></tr></thead>
|
||||
<thead><tr><th>Model</th><th>Provider</th><th>Tier</th><th>Context</th><th>Input Cost</th><th>Output Cost</th><th>Status</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
<template x-for="m in filteredModels" :key="m.id">
|
||||
<tr>
|
||||
@@ -3078,6 +3078,7 @@ args = ["-y", "@modelcontextprotocol/server-filesystem", "/path"]</pre>
|
||||
<td class="text-xs" x-text="formatCost(m.input_cost_per_m)"></td>
|
||||
<td class="text-xs" x-text="formatCost(m.output_cost_per_m)"></td>
|
||||
<td><span class="badge" :class="m.available ? 'badge-success' : 'badge-muted'" x-text="m.available ? 'Available' : 'Needs Key'"></span></td>
|
||||
<td><button x-show="m.tier === 'custom'" class="btn btn-ghost btn-sm" @click="deleteCustomModel(m.id)" title="Delete custom model" style="padding:2px 6px;font-size:11px;color:var(--text-muted)">✕</button></td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
|
||||
@@ -258,6 +258,17 @@ function settingsPage() {
|
||||
}
|
||||
},
|
||||
|
||||
async deleteCustomModel(modelId) {
|
||||
if (!confirm('Delete custom model "' + modelId + '"?')) return;
|
||||
try {
|
||||
await OpenFangAPI.del('/api/models/custom/' + encodeURIComponent(modelId));
|
||||
OpenFangToast.success('Model deleted');
|
||||
await this.loadModels();
|
||||
} catch(e) {
|
||||
OpenFangToast.error('Failed to delete: ' + (e.message || 'Unknown error'));
|
||||
}
|
||||
},
|
||||
|
||||
async loadConfigSchema() {
|
||||
try {
|
||||
var results = await Promise.all([
|
||||
|
||||
@@ -1306,8 +1306,14 @@ fn detect_best_provider() -> (&'static str, &'static str, &'static str) {
|
||||
ui::success("Detected Gemini (GOOGLE_API_KEY)");
|
||||
return ("gemini", "GOOGLE_API_KEY", "gemini-2.5-flash");
|
||||
}
|
||||
// Check if Ollama is running locally (no API key needed)
|
||||
if check_ollama_available() {
|
||||
ui::success("Detected Ollama running locally (no API key needed)");
|
||||
return ("ollama", "OLLAMA_API_KEY", "llama3.2");
|
||||
}
|
||||
ui::hint("No LLM provider API keys found");
|
||||
ui::hint("Groq offers a free tier: https://console.groq.com");
|
||||
ui::hint("Or install Ollama for local models: https://ollama.com");
|
||||
("groq", "GROQ_API_KEY", "llama-3.3-70b-versatile")
|
||||
}
|
||||
|
||||
@@ -1333,6 +1339,15 @@ fn provider_list() -> Vec<(&'static str, &'static str, &'static str, &'static st
|
||||
]
|
||||
}
|
||||
|
||||
/// Quick probe to check if Ollama is running on localhost.
|
||||
fn check_ollama_available() -> bool {
|
||||
std::net::TcpStream::connect_timeout(
|
||||
&std::net::SocketAddr::from(([127, 0, 0, 1], 11434)),
|
||||
std::time::Duration::from_millis(500),
|
||||
)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
/// Write config.toml if it doesn't already exist.
|
||||
fn write_config_if_missing(
|
||||
openfang_dir: &std::path::Path,
|
||||
|
||||
@@ -50,7 +50,8 @@ impl LlmDriver for StubDriver {
|
||||
async fn complete(&self, _request: CompletionRequest) -> Result<CompletionResponse, LlmError> {
|
||||
Err(LlmError::MissingApiKey(
|
||||
"No LLM provider configured. Set an API key (e.g. GROQ_API_KEY) and restart, \
|
||||
or configure a provider via the dashboard."
|
||||
configure a provider via the dashboard, \
|
||||
or use Ollama for local models (no API key needed)."
|
||||
.to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user