mirror of
https://github.com/RightNow-AI/openfang.git
synced 2026-08-14 00:47:51 +00:00
bug fixes
This commit is contained in:
Generated
+14
-14
@@ -3811,7 +3811,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-api"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
@@ -3851,7 +3851,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-channels"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"async-trait",
|
||||
@@ -3888,7 +3888,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-cli"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
@@ -3915,7 +3915,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-desktop"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"open",
|
||||
@@ -3941,7 +3941,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-extensions"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"argon2",
|
||||
@@ -3969,7 +3969,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-hands"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dashmap",
|
||||
@@ -3986,7 +3986,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-kernel"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -4024,7 +4024,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-memory"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -4043,7 +4043,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-migrate"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dirs 6.0.0",
|
||||
@@ -4062,7 +4062,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-runtime"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -4096,7 +4096,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-skills"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"hex",
|
||||
@@ -4119,7 +4119,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-types"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -4138,7 +4138,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "openfang-wire"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -8814,7 +8814,7 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
|
||||
@@ -844,7 +844,26 @@ pub async fn create_workflow(
|
||||
created_at: chrono::Utc::now(),
|
||||
};
|
||||
|
||||
let id = state.kernel.register_workflow(workflow).await;
|
||||
let id = state.kernel.register_workflow(workflow.clone()).await;
|
||||
|
||||
// Persist workflow to disk so it survives daemon restarts (#751)
|
||||
let wf_dir = state
|
||||
.kernel
|
||||
.config
|
||||
.workflows_dir
|
||||
.clone()
|
||||
.unwrap_or_else(|| state.kernel.config.home_dir.join("workflows"));
|
||||
if let Err(e) = std::fs::create_dir_all(&wf_dir) {
|
||||
tracing::warn!("Failed to create workflows dir: {e}");
|
||||
} else {
|
||||
let wf_path = wf_dir.join(format!("{}.json", id));
|
||||
if let Ok(json) = serde_json::to_string_pretty(&workflow) {
|
||||
if let Err(e) = std::fs::write(&wf_path, json) {
|
||||
tracing::warn!("Failed to persist workflow {id}: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
StatusCode::CREATED,
|
||||
Json(serde_json::json!({"workflow_id": id.to_string()})),
|
||||
@@ -9713,78 +9732,84 @@ pub async fn config_schema(State(state): State<Arc<AppState>>) -> impl IntoRespo
|
||||
.collect();
|
||||
drop(catalog);
|
||||
|
||||
// Helper: normalize field definitions to objects with {name, type, label}
|
||||
// so the frontend template can iterate and render inputs correctly.
|
||||
let f = |name: &str, ftype: &str, label: &str| -> serde_json::Value {
|
||||
serde_json::json!({"name": name, "type": ftype, "label": label})
|
||||
};
|
||||
|
||||
Json(serde_json::json!({
|
||||
"sections": {
|
||||
"general": {
|
||||
"root_level": true,
|
||||
"fields": {
|
||||
"api_listen": "string",
|
||||
"api_key": "string",
|
||||
"log_level": "string"
|
||||
}
|
||||
"fields": [
|
||||
f("api_listen", "string", "API Listen Address"),
|
||||
f("api_key", "string", "API Key"),
|
||||
f("log_level", "string", "Log Level")
|
||||
]
|
||||
},
|
||||
"default_model": {
|
||||
"hot_reloadable": true,
|
||||
"fields": {
|
||||
"provider": { "type": "select", "options": provider_options },
|
||||
"model": { "type": "select", "options": model_options },
|
||||
"api_key_env": "string",
|
||||
"base_url": "string"
|
||||
}
|
||||
"fields": [
|
||||
{ "name": "provider", "type": "select", "label": "Provider", "options": provider_options },
|
||||
{ "name": "model", "type": "select", "label": "Model", "options": model_options },
|
||||
f("api_key_env", "string", "API Key Env Var"),
|
||||
f("base_url", "string", "Base URL")
|
||||
]
|
||||
},
|
||||
"memory": {
|
||||
"fields": {
|
||||
"decay_rate": "number",
|
||||
"vector_dims": "number"
|
||||
}
|
||||
"fields": [
|
||||
f("decay_rate", "number", "Decay Rate"),
|
||||
f("vector_dims", "number", "Vector Dimensions")
|
||||
]
|
||||
},
|
||||
"web": {
|
||||
"fields": {
|
||||
"provider": "string",
|
||||
"timeout_secs": "number",
|
||||
"max_results": "number"
|
||||
}
|
||||
"fields": [
|
||||
f("provider", "string", "Search Provider"),
|
||||
f("timeout_secs", "number", "Timeout (seconds)"),
|
||||
f("max_results", "number", "Max Results")
|
||||
]
|
||||
},
|
||||
"browser": {
|
||||
"fields": {
|
||||
"headless": "boolean",
|
||||
"timeout_secs": "number",
|
||||
"executable_path": "string"
|
||||
}
|
||||
"fields": [
|
||||
f("headless", "boolean", "Headless Mode"),
|
||||
f("timeout_secs", "number", "Timeout (seconds)"),
|
||||
f("executable_path", "string", "Chrome/Chromium Path")
|
||||
]
|
||||
},
|
||||
"network": {
|
||||
"fields": {
|
||||
"enabled": "boolean",
|
||||
"listen_addr": "string",
|
||||
"shared_secret": "string"
|
||||
}
|
||||
"fields": [
|
||||
f("enabled", "boolean", "Enable OFP Network"),
|
||||
f("listen_addr", "string", "Listen Address"),
|
||||
f("shared_secret", "string", "Shared Secret")
|
||||
]
|
||||
},
|
||||
"extensions": {
|
||||
"fields": {
|
||||
"auto_connect": "boolean",
|
||||
"health_check_interval_secs": "number"
|
||||
}
|
||||
"fields": [
|
||||
f("auto_connect", "boolean", "Auto Connect"),
|
||||
f("health_check_interval_secs", "number", "Health Check Interval (s)")
|
||||
]
|
||||
},
|
||||
"vault": {
|
||||
"fields": {
|
||||
"path": "string"
|
||||
}
|
||||
"fields": [
|
||||
f("path", "string", "Vault Path")
|
||||
]
|
||||
},
|
||||
"a2a": {
|
||||
"fields": {
|
||||
"enabled": "boolean",
|
||||
"name": "string",
|
||||
"description": "string",
|
||||
"url": "string"
|
||||
}
|
||||
"fields": [
|
||||
f("enabled", "boolean", "Enable A2A"),
|
||||
f("name", "string", "Agent Name"),
|
||||
f("description", "string", "Description"),
|
||||
f("url", "string", "URL")
|
||||
]
|
||||
},
|
||||
"channels": {
|
||||
"fields": {
|
||||
"telegram": "object",
|
||||
"discord": "object",
|
||||
"slack": "object",
|
||||
"whatsapp": "object"
|
||||
}
|
||||
"fields": [
|
||||
f("telegram", "object", "Telegram"),
|
||||
f("discord", "object", "Discord"),
|
||||
f("slack", "object", "Slack"),
|
||||
f("whatsapp", "object", "WhatsApp")
|
||||
]
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -3449,7 +3449,7 @@ args = ["-y", "@modelcontextprotocol/server-filesystem", "/path"]</pre>
|
||||
<div class="card mb-4">
|
||||
<div class="card-header" style="text-transform:capitalize" x-text="section.replace(/_/g, ' ')"></div>
|
||||
<div class="detail-grid" style="margin-top:12px">
|
||||
<template x-for="field in fields" :key="section + '.' + field.name">
|
||||
<template x-for="field in (fields.fields || [])" :key="section + '.' + field.name">
|
||||
<div class="detail-row" style="align-items:center">
|
||||
<span class="detail-label" x-text="field.label || field.name"></span>
|
||||
<div style="display:flex;align-items:center;gap:8px;flex:1;min-width:0">
|
||||
|
||||
@@ -127,6 +127,13 @@ impl CredentialResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear a credential from the in-memory dotenv cache.
|
||||
/// Call this when a key is deleted via the dashboard so the resolver
|
||||
/// doesn't return a stale value from the boot-time snapshot.
|
||||
pub fn clear_dotenv_cache(&mut self, key: &str) {
|
||||
self.dotenv.remove(key);
|
||||
}
|
||||
|
||||
/// Remove a credential from the vault (if available).
|
||||
pub fn remove_from_vault(&mut self, key: &str) -> ExtensionResult<bool> {
|
||||
if let Some(ref mut vault) = self.vault {
|
||||
|
||||
@@ -4579,6 +4579,9 @@ impl OpenFangKernel {
|
||||
if let Err(e) = resolver.remove_from_vault(key) {
|
||||
debug!("Vault remove skipped for {key}: {e}");
|
||||
}
|
||||
// Also clear from the in-memory dotenv cache so the resolver
|
||||
// doesn't return a stale value from the boot-time snapshot (#736).
|
||||
resolver.clear_dotenv_cache(key);
|
||||
}
|
||||
|
||||
fn lookup_provider_url(&self, provider: &str) -> Option<String> {
|
||||
|
||||
Reference in New Issue
Block a user