diff --git a/crates/openfang-api/src/channel_bridge.rs b/crates/openfang-api/src/channel_bridge.rs index b72180670..1b28ba2d0 100644 --- a/crates/openfang-api/src/channel_bridge.rs +++ b/crates/openfang-api/src/channel_bridge.rs @@ -1065,7 +1065,9 @@ pub async fn start_channel_bridge_with_config( // WhatsApp — supports Cloud API mode (access token) or Web/QR mode (gateway URL) if let Some(ref wa_config) = config.whatsapp { let cloud_token = read_token(&wa_config.access_token_env, "WhatsApp"); - let gateway_url = std::env::var(&wa_config.gateway_url_env).ok().filter(|u| !u.is_empty()); + let gateway_url = std::env::var(&wa_config.gateway_url_env) + .ok() + .filter(|u| !u.is_empty()); if cloud_token.is_some() || gateway_url.is_some() { let token = cloud_token.unwrap_or_default(); diff --git a/crates/openfang-api/src/routes.rs b/crates/openfang-api/src/routes.rs index 89353f39d..7c29f22b0 100644 --- a/crates/openfang-api/src/routes.rs +++ b/crates/openfang-api/src/routes.rs @@ -126,15 +126,13 @@ pub async fn list_agents(State(state): State>) -> impl IntoRespons .into_iter() .map(|e| { // Resolve "default" provider/model to actual kernel defaults - let provider = if e.manifest.model.provider.is_empty() - || e.manifest.model.provider == "default" - { - dm.provider.as_str() - } else { - e.manifest.model.provider.as_str() - }; - let model = if e.manifest.model.model.is_empty() - || e.manifest.model.model == "default" + let provider = + if e.manifest.model.provider.is_empty() || e.manifest.model.provider == "default" { + dm.provider.as_str() + } else { + e.manifest.model.provider.as_str() + }; + let model = if e.manifest.model.model.is_empty() || e.manifest.model.model == "default" { dm.model.as_str() } else { @@ -1870,9 +1868,7 @@ fn build_field_json( val.clone() }; field["value"] = display_val; - if !val.is_null() - && val.as_str().map(|s| !s.is_empty()).unwrap_or(true) - { + if !val.is_null() && val.as_str().map(|s| !s.is_empty()).unwrap_or(true) { field["has_value"] = serde_json::Value::Bool(true); } } @@ -1892,46 +1888,166 @@ fn channel_config_values( name: &str, ) -> Option { match name { - "telegram" => config.telegram.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "discord" => config.discord.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "slack" => config.slack.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "whatsapp" => config.whatsapp.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "signal" => config.signal.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "matrix" => config.matrix.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "email" => config.email.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "teams" => config.teams.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "mattermost" => config.mattermost.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "irc" => config.irc.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "google_chat" => config.google_chat.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "twitch" => config.twitch.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "rocketchat" => config.rocketchat.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "zulip" => config.zulip.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "xmpp" => config.xmpp.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "line" => config.line.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "viber" => config.viber.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "messenger" => config.messenger.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "reddit" => config.reddit.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "mastodon" => config.mastodon.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "bluesky" => config.bluesky.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "feishu" => config.feishu.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "revolt" => config.revolt.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "nextcloud" => config.nextcloud.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "guilded" => config.guilded.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "keybase" => config.keybase.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "threema" => config.threema.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "nostr" => config.nostr.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "webex" => config.webex.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "pumble" => config.pumble.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "flock" => config.flock.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "twist" => config.twist.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "mumble" => config.mumble.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "dingtalk" => config.dingtalk.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "discourse" => config.discourse.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "gitter" => config.gitter.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "ntfy" => config.ntfy.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "gotify" => config.gotify.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "webhook" => config.webhook.as_ref().and_then(|c| serde_json::to_value(c).ok()), - "linkedin" => config.linkedin.as_ref().and_then(|c| serde_json::to_value(c).ok()), + "telegram" => config + .telegram + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "discord" => config + .discord + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "slack" => config + .slack + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "whatsapp" => config + .whatsapp + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "signal" => config + .signal + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "matrix" => config + .matrix + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "email" => config + .email + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "teams" => config + .teams + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "mattermost" => config + .mattermost + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "irc" => config + .irc + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "google_chat" => config + .google_chat + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "twitch" => config + .twitch + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "rocketchat" => config + .rocketchat + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "zulip" => config + .zulip + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "xmpp" => config + .xmpp + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "line" => config + .line + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "viber" => config + .viber + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "messenger" => config + .messenger + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "reddit" => config + .reddit + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "mastodon" => config + .mastodon + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "bluesky" => config + .bluesky + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "feishu" => config + .feishu + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "revolt" => config + .revolt + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "nextcloud" => config + .nextcloud + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "guilded" => config + .guilded + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "keybase" => config + .keybase + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "threema" => config + .threema + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "nostr" => config + .nostr + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "webex" => config + .webex + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "pumble" => config + .pumble + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "flock" => config + .flock + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "twist" => config + .twist + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "mumble" => config + .mumble + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "dingtalk" => config + .dingtalk + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "discourse" => config + .discourse + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "gitter" => config + .gitter + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "ntfy" => config + .ntfy + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "gotify" => config + .gotify + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "webhook" => config + .webhook + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), + "linkedin" => config + .linkedin + .as_ref() + .and_then(|c| serde_json::to_value(c).ok()), _ => None, } } @@ -2053,7 +2169,10 @@ pub async fn configure_channel( ); } else { // Config field — collect for TOML write with type info - config_fields.insert(field_def.key.to_string(), (value.to_string(), field_def.field_type)); + config_fields.insert( + field_def.key.to_string(), + (value.to_string(), field_def.field_type), + ); } } @@ -3057,7 +3176,9 @@ pub async fn clawhub_search( "items": items, "next_cursor": null, }); - state.clawhub_cache.insert(cache_key, (Instant::now(), resp.clone())); + state + .clawhub_cache + .insert(cache_key, (Instant::now(), resp.clone())); (StatusCode::OK, Json(resp)) } Err(e) => { @@ -3071,9 +3192,7 @@ pub async fn clawhub_search( }; ( status, - Json( - serde_json::json!({"items": [], "next_cursor": null, "error": msg}), - ), + Json(serde_json::json!({"items": [], "next_cursor": null, "error": msg})), ) } } @@ -3126,7 +3245,9 @@ pub async fn clawhub_browse( "items": items, "next_cursor": results.next_cursor, }); - state.clawhub_cache.insert(cache_key, (Instant::now(), resp.clone())); + state + .clawhub_cache + .insert(cache_key, (Instant::now(), resp.clone())); (StatusCode::OK, Json(resp)) } Err(e) => { @@ -3139,9 +3260,7 @@ pub async fn clawhub_browse( }; ( status, - Json( - serde_json::json!({"items": [], "next_cursor": null, "error": msg}), - ), + Json(serde_json::json!({"items": [], "next_cursor": null, "error": msg})), ) } } @@ -3308,7 +3427,10 @@ pub async fn clawhub_install( StatusCode::FORBIDDEN } else if msg.contains("429") || msg.contains("rate limit") { StatusCode::TOO_MANY_REQUESTS - } else if msg.contains("Network error") || msg.contains("returned 4") || msg.contains("returned 5") { + } else if msg.contains("Network error") + || msg.contains("returned 4") + || msg.contains("returned 5") + { StatusCode::BAD_GATEWAY } else { StatusCode::INTERNAL_SERVER_ERROR @@ -3807,7 +3929,12 @@ pub async fn activate_hand( // If the hand agent has a non-reactive schedule (autonomous hands), // start its background loop so it begins running immediately. if let Some(agent_id) = instance.agent_id { - let entry = state.kernel.registry.list().into_iter().find(|e| e.id == agent_id); + let entry = state + .kernel + .registry + .list() + .into_iter() + .find(|e| e.id == agent_id); if let Some(entry) = entry { if !matches!( entry.manifest.schedule, @@ -3963,7 +4090,9 @@ pub async fn update_hand_settings( }, None => ( StatusCode::NOT_FOUND, - Json(serde_json::json!({"error": format!("No active instance for hand: {hand_id}. Activate the hand first.")})), + Json( + serde_json::json!({"error": format!("No active instance for hand: {hand_id}. Activate the hand first.")}), + ), ), } } @@ -4090,7 +4219,10 @@ pub async fn hand_instance_browser( content = data["content"].as_str().unwrap_or("").to_string(); // Truncate content to avoid huge payloads (UTF-8 safe) if content.len() > 2000 { - content = format!("{}... (truncated)", openfang_types::truncate_str(&content, 2000)); + content = format!( + "{}... (truncated)", + openfang_types::truncate_str(&content, 2000) + ); } } } @@ -4746,7 +4878,9 @@ pub async fn update_agent_budget( if hourly.is_none() && daily.is_none() && monthly.is_none() { return ( StatusCode::BAD_REQUEST, - Json(serde_json::json!({"error": "Provide at least one of: max_cost_per_hour_usd, max_cost_per_day_usd, max_cost_per_month_usd"})), + Json( + serde_json::json!({"error": "Provide at least one of: max_cost_per_hour_usd, max_cost_per_day_usd, max_cost_per_month_usd"}), + ), ); } @@ -5465,7 +5599,9 @@ pub async fn add_custom_model( if !catalog.add_custom_model(entry) { return ( StatusCode::CONFLICT, - Json(serde_json::json!({"error": format!("Model '{}' already exists for provider '{}'", id, provider)})), + Json( + serde_json::json!({"error": format!("Model '{}' already exists for provider '{}'", id, provider)}), + ), ); } @@ -6250,10 +6386,7 @@ pub async fn set_agent_tools( .kernel .set_agent_tool_filters(agent_id, allowlist, blocklist) { - Ok(()) => ( - StatusCode::OK, - Json(serde_json::json!({"status": "ok"})), - ), + Ok(()) => (StatusCode::OK, Json(serde_json::json!({"status": "ok"}))), Err(e) => ( StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({"error": format!("{e}")})), @@ -6463,10 +6596,7 @@ pub async fn set_provider_key( .map(|p| p.api_key_env.clone()) .unwrap_or_else(|| { // Custom provider — derive env var: MY_PROVIDER → MY_PROVIDER_API_KEY - format!( - "{}_API_KEY", - name.to_uppercase().replace('-', "_") - ) + format!("{}_API_KEY", name.to_uppercase().replace('-', "_")) }) }; @@ -6695,8 +6825,7 @@ pub async fn set_provider_url( } // Probe reachability at the new URL - let probe = - openfang_runtime::provider_health::probe_provider(&name, &base_url).await; + let probe = openfang_runtime::provider_health::probe_provider(&name, &base_url).await; // Merge discovered models into catalog if !probe.discovered_models.is_empty() { @@ -7591,7 +7720,11 @@ pub async fn run_schedule( ); let kernel_handle: Arc = state.kernel.clone() as Arc; - match state.kernel.send_message_with_handle(target_agent, &run_message, Some(kernel_handle)).await { + match state + .kernel + .send_message_with_handle(target_agent, &run_message, Some(kernel_handle)) + .await + { Ok(result) => ( StatusCode::OK, Json(serde_json::json!({ @@ -7745,7 +7878,9 @@ pub async fn patch_agent_config( if name.len() > MAX_NAME_LEN { return ( StatusCode::PAYLOAD_TOO_LARGE, - Json(serde_json::json!({"error": format!("Name exceeds max length ({MAX_NAME_LEN} chars)")})), + Json( + serde_json::json!({"error": format!("Name exceeds max length ({MAX_NAME_LEN} chars)")}), + ), ); } } @@ -7753,7 +7888,9 @@ pub async fn patch_agent_config( if desc.len() > MAX_DESC_LEN { return ( StatusCode::PAYLOAD_TOO_LARGE, - Json(serde_json::json!({"error": format!("Description exceeds max length ({MAX_DESC_LEN} chars)")})), + Json( + serde_json::json!({"error": format!("Description exceeds max length ({MAX_DESC_LEN} chars)")}), + ), ); } } @@ -7761,7 +7898,9 @@ pub async fn patch_agent_config( if prompt.len() > MAX_PROMPT_LEN { return ( StatusCode::PAYLOAD_TOO_LARGE, - Json(serde_json::json!({"error": format!("System prompt exceeds max length ({MAX_PROMPT_LEN} chars)")})), + Json( + serde_json::json!({"error": format!("System prompt exceeds max length ({MAX_PROMPT_LEN} chars)")}), + ), ); } } @@ -8753,12 +8892,18 @@ pub async fn config_reload(State(state): State>) -> impl IntoRespo // --------------------------------------------------------------------------- /// GET /api/config/schema — Return a simplified JSON description of the config structure. -pub async fn config_schema( - State(state): State>, -) -> impl IntoResponse { +pub async fn config_schema(State(state): State>) -> impl IntoResponse { // Build provider/model options from model catalog for dropdowns - let catalog = state.kernel.model_catalog.read().unwrap_or_else(|e| e.into_inner()); - let provider_options: Vec = catalog.list_providers().iter().map(|p| p.id.clone()).collect(); + let catalog = state + .kernel + .model_catalog + .read() + .unwrap_or_else(|e| e.into_inner()); + let provider_options: Vec = catalog + .list_providers() + .iter() + .map(|p| p.id.clone()) + .collect(); let model_options: Vec = catalog .list_models() .iter() @@ -9611,8 +9756,7 @@ pub async fn copilot_oauth_start() -> impl IntoResponse { CopilotFlowState { device_code: resp.device_code, interval: resp.interval, - expires_at: Instant::now() - + std::time::Duration::from_secs(resp.expires_in), + expires_at: Instant::now() + std::time::Duration::from_secs(resp.expires_in), }, ); @@ -9676,7 +9820,9 @@ pub async fn copilot_oauth_poll( if let Err(e) = write_secret_env(&secrets_path, "GITHUB_TOKEN", &access_token) { return ( StatusCode::INTERNAL_SERVER_ERROR, - Json(serde_json::json!({"status": "error", "error": format!("Failed to save token: {e}")})), + Json( + serde_json::json!({"status": "error", "error": format!("Failed to save token: {e}")}), + ), ); } @@ -9880,15 +10026,30 @@ fn audit_to_comms_event( // Format detail: "tokens_in=X, tokens_out=Y" → readable summary let detail = if entry.detail.starts_with("tokens_in=") { let parts: Vec<&str> = entry.detail.split(", ").collect(); - let in_tok = parts.first().and_then(|p| p.strip_prefix("tokens_in=")).unwrap_or("?"); - let out_tok = parts.get(1).and_then(|p| p.strip_prefix("tokens_out=")).unwrap_or("?"); + let in_tok = parts + .first() + .and_then(|p| p.strip_prefix("tokens_in=")) + .unwrap_or("?"); + let out_tok = parts + .get(1) + .and_then(|p| p.strip_prefix("tokens_out=")) + .unwrap_or("?"); if entry.outcome == "ok" { format!("{} in / {} out tokens", in_tok, out_tok) } else { - format!("{} in / {} out — {}", in_tok, out_tok, openfang_types::truncate_str(&entry.outcome, 80)) + format!( + "{} in / {} out — {}", + in_tok, + out_tok, + openfang_types::truncate_str(&entry.outcome, 80) + ) } } else if entry.outcome != "ok" { - format!("{} — {}", openfang_types::truncate_str(&entry.detail, 80), openfang_types::truncate_str(&entry.outcome, 80)) + format!( + "{} — {}", + openfang_types::truncate_str(&entry.detail, 80), + openfang_types::truncate_str(&entry.outcome, 80) + ) } else { openfang_types::truncate_str(&entry.detail, 200).to_string() }; @@ -9896,12 +10057,18 @@ fn audit_to_comms_event( } "AgentSpawn" => ( CommsEventKind::AgentSpawned, - format!("Agent spawned: {}", openfang_types::truncate_str(&entry.detail, 100)), + format!( + "Agent spawned: {}", + openfang_types::truncate_str(&entry.detail, 100) + ), "", ), "AgentKill" => ( CommsEventKind::AgentTerminated, - format!("Agent killed: {}", openfang_types::truncate_str(&entry.detail, 100)), + format!( + "Agent killed: {}", + openfang_types::truncate_str(&entry.detail, 100) + ), "", ), _ => return None, @@ -9913,8 +10080,16 @@ fn audit_to_comms_event( kind, source_id: entry.agent_id.clone(), source_name: resolve_name(&entry.agent_id), - target_id: if target_label.is_empty() { String::new() } else { target_label.to_string() }, - target_name: if target_label.is_empty() { String::new() } else { target_label.to_string() }, + target_id: if target_label.is_empty() { + String::new() + } else { + target_label.to_string() + }, + target_name: if target_label.is_empty() { + String::new() + } else { + target_label.to_string() + }, detail, }) } @@ -9965,9 +10140,7 @@ pub async fn comms_events( /// GET /api/comms/events/stream — SSE stream of inter-agent communication events. /// /// Polls the audit log every 500ms for new inter-agent events. -pub async fn comms_events_stream( - State(state): State>, -) -> axum::response::Response { +pub async fn comms_events_stream(State(state): State>) -> axum::response::Response { use axum::response::sse::{Event, KeepAlive, Sse}; let (tx, rx) = tokio::sync::mpsc::channel::< diff --git a/crates/openfang-api/src/server.rs b/crates/openfang-api/src/server.rs index 11393184d..35c0d97cf 100644 --- a/crates/openfang-api/src/server.rs +++ b/crates/openfang-api/src/server.rs @@ -354,8 +354,7 @@ pub async fn build_router( ) .route( "/api/hands/{hand_id}/settings", - axum::routing::get(routes::get_hand_settings) - .put(routes::update_hand_settings), + axum::routing::get(routes::get_hand_settings).put(routes::update_hand_settings), ) .route( "/api/hands/instances/{id}/pause", @@ -412,14 +411,8 @@ pub async fn build_router( "/api/comms/events/stream", axum::routing::get(routes::comms_events_stream), ) - .route( - "/api/comms/send", - axum::routing::post(routes::comms_send), - ) - .route( - "/api/comms/task", - axum::routing::post(routes::comms_task), - ) + .route("/api/comms/send", axum::routing::post(routes::comms_send)) + .route("/api/comms/task", axum::routing::post(routes::comms_task)) // Tools endpoint .route("/api/tools", axum::routing::get(routes::list_tools)) // Config endpoints @@ -464,8 +457,7 @@ pub async fn build_router( ) .route( "/api/budget/agents/{id}", - axum::routing::get(routes::agent_budget_status) - .put(routes::update_agent_budget), + axum::routing::get(routes::agent_budget_status).put(routes::update_agent_budget), ) // Session endpoints .route("/api/sessions", axum::routing::get(routes::list_sessions)) @@ -787,8 +779,7 @@ pub async fn run_daemon( socket.set_nonblocking(true)?; socket.bind(&addr.into())?; socket.listen(1024)?; - let listener = - tokio::net::TcpListener::from_std(std::net::TcpListener::from(socket))?; + let listener = tokio::net::TcpListener::from_std(std::net::TcpListener::from(socket))?; // Run server with graceful shutdown. // SECURITY: `into_make_service_with_connect_info` injects the peer @@ -919,11 +910,8 @@ fn is_daemon_responding(addr: &str) -> bool { .or_else(|| addr.strip_prefix("https://")) .unwrap_or(addr); if let Ok(sock_addr) = addr_only.parse::() { - std::net::TcpStream::connect_timeout( - &sock_addr, - std::time::Duration::from_millis(500), - ) - .is_ok() + std::net::TcpStream::connect_timeout(&sock_addr, std::time::Duration::from_millis(500)) + .is_ok() } else { // Fallback: try connecting to hostname std::net::TcpStream::connect(addr_only) diff --git a/crates/openfang-api/src/ws.rs b/crates/openfang-api/src/ws.rs index 19ff864f2..3a8ae6ffa 100644 --- a/crates/openfang-api/src/ws.rs +++ b/crates/openfang-api/src/ws.rs @@ -801,7 +801,10 @@ async fn handle_command( match state.kernel.set_agent_model(agent_id, args) { Ok(()) => { let msg = if let Some(entry) = state.kernel.registry.get(agent_id) { - format!("Model switched to: {} (provider: {})", entry.manifest.model.model, entry.manifest.model.provider) + format!( + "Model switched to: {} (provider: {})", + entry.manifest.model.model, entry.manifest.model.provider + ) } else { format!("Model switched to: {args}") }; @@ -1121,11 +1124,13 @@ fn classify_streaming_error(err: &openfang_kernel::error::KernelError) -> String if inner.contains("localhost:11434") || inner.contains("ollama") { "Model not found on Ollama. Run `ollama pull ` to download it, then try again. Use /model to see options.".to_string() } else { - "Model unavailable. Use /model to see options or check your provider configuration.".to_string() + "Model unavailable. Use /model to see options or check your provider configuration." + .to_string() } } llm_errors::LlmErrorCategory::Format => { - "LLM request failed. Check your API key and model configuration in Settings.".to_string() + "LLM request failed. Check your API key and model configuration in Settings." + .to_string() } _ => classified.sanitized_message, } diff --git a/crates/openfang-channels/src/bridge.rs b/crates/openfang-channels/src/bridge.rs index efb9ca525..a74d0df7c 100644 --- a/crates/openfang-channels/src/bridge.rs +++ b/crates/openfang-channels/src/bridge.rs @@ -408,7 +408,9 @@ async fn dispatch_message( } GroupPolicy::MentionOnly => { // Only allow messages where the bot was @mentioned or commands. - let was_mentioned = message.metadata.get("was_mentioned") + let was_mentioned = message + .metadata + .get("was_mentioned") .and_then(|v| v.as_bool()) .unwrap_or(false); let is_command = matches!(&message.content, ChannelContent::Command { .. }); diff --git a/crates/openfang-channels/src/discord.rs b/crates/openfang-channels/src/discord.rs index 993bb490b..5586249a0 100644 --- a/crates/openfang-channels/src/discord.rs +++ b/crates/openfang-channels/src/discord.rs @@ -314,9 +314,13 @@ impl ChannelAdapter for DiscordAdapter { } "MESSAGE_CREATE" | "MESSAGE_UPDATE" => { - if let Some(msg) = - parse_discord_message(d, &bot_user_id, &allowed_guilds, &allowed_users) - .await + if let Some(msg) = parse_discord_message( + d, + &bot_user_id, + &allowed_guilds, + &allowed_users, + ) + .await { debug!( "Discord {event_name} from {}: {:?}", @@ -512,8 +516,8 @@ async fn parse_discord_message( .map(|arr| arr.iter().any(|m| m["id"].as_str() == Some(bid.as_str()))) .unwrap_or(false); // Also check content for <@bot_id> or <@!bot_id> patterns - let mentioned_in_content = - content_text.contains(&format!("<@{bid}>")) || content_text.contains(&format!("<@!{bid}>")); + let mentioned_in_content = content_text.contains(&format!("<@{bid}>")) + || content_text.contains(&format!("<@!{bid}>")); mentioned_in_array || mentioned_in_content } else { false @@ -736,7 +740,8 @@ mod tests { }); // Not in allowed users - let msg = parse_discord_message(&d, &bot_id, &[], &["user111".into(), "user222".into()]).await; + let msg = + parse_discord_message(&d, &bot_id, &[], &["user111".into(), "user222".into()]).await; assert!(msg.is_none()); // In allowed users @@ -769,7 +774,10 @@ mod tests { let msg = parse_discord_message(&d, &bot_id, &[], &[]).await.unwrap(); assert!(msg.is_group); - assert_eq!(msg.metadata.get("was_mentioned").and_then(|v| v.as_bool()), Some(true)); + assert_eq!( + msg.metadata.get("was_mentioned").and_then(|v| v.as_bool()), + Some(true) + ); // Message without mention in group let d2 = serde_json::json!({ @@ -811,7 +819,12 @@ mod tests { #[test] fn test_discord_adapter_creation() { - let adapter = DiscordAdapter::new("test-token".to_string(), vec!["123".to_string(), "456".to_string()], vec![], 37376); + let adapter = DiscordAdapter::new( + "test-token".to_string(), + vec!["123".to_string(), "456".to_string()], + vec![], + 37376, + ); assert_eq!(adapter.name(), "discord"); assert_eq!(adapter.channel_type(), ChannelType::Discord); } diff --git a/crates/openfang-channels/src/email.rs b/crates/openfang-channels/src/email.rs index 7d7ae2d4d..f9ffe7072 100644 --- a/crates/openfang-channels/src/email.rs +++ b/crates/openfang-channels/src/email.rs @@ -124,8 +124,7 @@ impl EmailAdapter { async fn build_smtp_transport( &self, ) -> Result, Box> { - let creds = - Credentials::new(self.username.clone(), self.password.as_str().to_string()); + let creds = Credentials::new(self.username.clone(), self.password.as_str().to_string()); let transport = if self.smtp_port == 465 { // Implicit TLS (port 465) @@ -200,8 +199,8 @@ fn fetch_unseen_emails( .build() .map_err(|e| format!("TLS connector error: {e}"))?; - let client = imap::connect((host, port), host, &tls) - .map_err(|e| format!("IMAP connect failed: {e}"))?; + let client = + imap::connect((host, port), host, &tls).map_err(|e| format!("IMAP connect failed: {e}"))?; let mut session = client .login(username, password) @@ -362,8 +361,7 @@ impl ChannelAdapter for EmailAdapter { } // Extract target agent from subject brackets (stored in metadata for router) - let _target_agent = - EmailAdapter::extract_agent_from_subject(&subject); + let _target_agent = EmailAdapter::extract_agent_from_subject(&subject); let clean_subject = EmailAdapter::strip_agent_tag(&subject); // Build the message body: prepend subject context diff --git a/crates/openfang-channels/src/telegram.rs b/crates/openfang-channels/src/telegram.rs index 6c3b4b88b..3301ba115 100644 --- a/crates/openfang-channels/src/telegram.rs +++ b/crates/openfang-channels/src/telegram.rs @@ -540,7 +540,17 @@ pub fn calculate_backoff(current: Duration) -> Duration { /// Everything else (e.g. ``, ``) gets escaped to `<...>`. fn sanitize_telegram_html(text: &str) -> String { const ALLOWED: &[&str] = &[ - "b", "i", "u", "s", "em", "strong", "a", "code", "pre", "blockquote", "tg-spoiler", + "b", + "i", + "u", + "s", + "em", + "strong", + "a", + "code", + "pre", + "blockquote", + "tg-spoiler", "tg-emoji", ]; diff --git a/crates/openfang-channels/src/whatsapp.rs b/crates/openfang-channels/src/whatsapp.rs index 82ad5840d..9f45fcd46 100644 --- a/crates/openfang-channels/src/whatsapp.rs +++ b/crates/openfang-channels/src/whatsapp.rs @@ -222,11 +222,9 @@ impl ChannelAdapter for WhatsAppAdapter { if let Some(ref gw) = self.gateway_url { let text = match &content { ChannelContent::Text(t) => t.clone(), - ChannelContent::Image { caption, .. } => { - caption - .clone() - .unwrap_or_else(|| "(Image — not supported in Web mode)".to_string()) - } + ChannelContent::Image { caption, .. } => caption + .clone() + .unwrap_or_else(|| "(Image — not supported in Web mode)".to_string()), ChannelContent::File { filename, .. } => { format!("(File: {filename} — not supported in Web mode)") } diff --git a/crates/openfang-cli/src/bundled_agents.rs b/crates/openfang-cli/src/bundled_agents.rs index d1e036c9b..0194859b1 100644 --- a/crates/openfang-cli/src/bundled_agents.rs +++ b/crates/openfang-cli/src/bundled_agents.rs @@ -7,34 +7,112 @@ /// Returns all bundled agent templates as `(name, toml_content)` pairs. pub fn bundled_agents() -> Vec<(&'static str, &'static str)> { vec![ - ("analyst", include_str!("../../../agents/analyst/agent.toml")), - ("architect", include_str!("../../../agents/architect/agent.toml")), - ("assistant", include_str!("../../../agents/assistant/agent.toml")), + ( + "analyst", + include_str!("../../../agents/analyst/agent.toml"), + ), + ( + "architect", + include_str!("../../../agents/architect/agent.toml"), + ), + ( + "assistant", + include_str!("../../../agents/assistant/agent.toml"), + ), ("coder", include_str!("../../../agents/coder/agent.toml")), - ("code-reviewer", include_str!("../../../agents/code-reviewer/agent.toml")), - ("customer-support", include_str!("../../../agents/customer-support/agent.toml")), - ("data-scientist", include_str!("../../../agents/data-scientist/agent.toml")), - ("debugger", include_str!("../../../agents/debugger/agent.toml")), - ("devops-lead", include_str!("../../../agents/devops-lead/agent.toml")), - ("doc-writer", include_str!("../../../agents/doc-writer/agent.toml")), - ("email-assistant", include_str!("../../../agents/email-assistant/agent.toml")), - ("health-tracker", include_str!("../../../agents/health-tracker/agent.toml")), - ("hello-world", include_str!("../../../agents/hello-world/agent.toml")), - ("home-automation", include_str!("../../../agents/home-automation/agent.toml")), - ("legal-assistant", include_str!("../../../agents/legal-assistant/agent.toml")), - ("meeting-assistant", include_str!("../../../agents/meeting-assistant/agent.toml")), + ( + "code-reviewer", + include_str!("../../../agents/code-reviewer/agent.toml"), + ), + ( + "customer-support", + include_str!("../../../agents/customer-support/agent.toml"), + ), + ( + "data-scientist", + include_str!("../../../agents/data-scientist/agent.toml"), + ), + ( + "debugger", + include_str!("../../../agents/debugger/agent.toml"), + ), + ( + "devops-lead", + include_str!("../../../agents/devops-lead/agent.toml"), + ), + ( + "doc-writer", + include_str!("../../../agents/doc-writer/agent.toml"), + ), + ( + "email-assistant", + include_str!("../../../agents/email-assistant/agent.toml"), + ), + ( + "health-tracker", + include_str!("../../../agents/health-tracker/agent.toml"), + ), + ( + "hello-world", + include_str!("../../../agents/hello-world/agent.toml"), + ), + ( + "home-automation", + include_str!("../../../agents/home-automation/agent.toml"), + ), + ( + "legal-assistant", + include_str!("../../../agents/legal-assistant/agent.toml"), + ), + ( + "meeting-assistant", + include_str!("../../../agents/meeting-assistant/agent.toml"), + ), ("ops", include_str!("../../../agents/ops/agent.toml")), - ("orchestrator", include_str!("../../../agents/orchestrator/agent.toml")), - ("personal-finance", include_str!("../../../agents/personal-finance/agent.toml")), - ("planner", include_str!("../../../agents/planner/agent.toml")), - ("recruiter", include_str!("../../../agents/recruiter/agent.toml")), - ("researcher", include_str!("../../../agents/researcher/agent.toml")), - ("sales-assistant", include_str!("../../../agents/sales-assistant/agent.toml")), - ("security-auditor", include_str!("../../../agents/security-auditor/agent.toml")), - ("social-media", include_str!("../../../agents/social-media/agent.toml")), - ("test-engineer", include_str!("../../../agents/test-engineer/agent.toml")), - ("translator", include_str!("../../../agents/translator/agent.toml")), - ("travel-planner", include_str!("../../../agents/travel-planner/agent.toml")), + ( + "orchestrator", + include_str!("../../../agents/orchestrator/agent.toml"), + ), + ( + "personal-finance", + include_str!("../../../agents/personal-finance/agent.toml"), + ), + ( + "planner", + include_str!("../../../agents/planner/agent.toml"), + ), + ( + "recruiter", + include_str!("../../../agents/recruiter/agent.toml"), + ), + ( + "researcher", + include_str!("../../../agents/researcher/agent.toml"), + ), + ( + "sales-assistant", + include_str!("../../../agents/sales-assistant/agent.toml"), + ), + ( + "security-auditor", + include_str!("../../../agents/security-auditor/agent.toml"), + ), + ( + "social-media", + include_str!("../../../agents/social-media/agent.toml"), + ), + ( + "test-engineer", + include_str!("../../../agents/test-engineer/agent.toml"), + ), + ( + "translator", + include_str!("../../../agents/translator/agent.toml"), + ), + ( + "travel-planner", + include_str!("../../../agents/travel-planner/agent.toml"), + ), ("tutor", include_str!("../../../agents/tutor/agent.toml")), ("writer", include_str!("../../../agents/writer/agent.toml")), ] diff --git a/crates/openfang-cli/src/main.rs b/crates/openfang-cli/src/main.rs index 967eb3c75..c47517055 100644 --- a/crates/openfang-cli/src/main.rs +++ b/crates/openfang-cli/src/main.rs @@ -1021,7 +1021,10 @@ fn main() { SystemCommands::Version { json } => cmd_system_version(json), }, Some(Commands::Reset { confirm }) => cmd_reset(confirm), - Some(Commands::Uninstall { confirm, keep_config }) => cmd_uninstall(confirm, keep_config), + Some(Commands::Uninstall { + confirm, + keep_config, + }) => cmd_uninstall(confirm, keep_config), } } @@ -2019,18 +2022,14 @@ fn cmd_doctor(json: bool, repair: bool) { ui::check_ok(".env file (permissions fixed to 0600)"); } repaired = true; - } else { - if !json { - ui::check_warn(&format!( - ".env file has loose permissions ({:o}), should be 0600", - mode - )); - } - } - } else { - if !json { - ui::check_ok(".env file"); + } else if !json { + ui::check_warn(&format!( + ".env file has loose permissions ({:o}), should be 0600", + mode + )); } + } else if !json { + ui::check_ok(".env file"); } } #[cfg(not(unix))] @@ -2157,7 +2156,9 @@ decay_rate = 0.05 if !json { ui::check_ok(&format!("Port {api_listen} is available")); } - checks.push(serde_json::json!({"check": "port", "status": "ok", "address": api_listen})); + checks.push( + serde_json::json!({"check": "port", "status": "ok", "address": api_listen}), + ); } Err(_) => { if !json { @@ -3932,7 +3933,10 @@ fn cmd_hand_install(path: &str) { body["name"].as_str().unwrap_or("?"), body["id"].as_str().unwrap_or("?"), ); - println!("Use `openfang hand activate {}` to start it.", body["id"].as_str().unwrap_or("?")); + println!( + "Use `openfang hand activate {}` to start it.", + body["id"].as_str().unwrap_or("?") + ); } fn cmd_hand_list() { @@ -3957,10 +3961,7 @@ fn cmd_hand_list() { println!("No hands available."); return; } - println!( - "{:<14} {:<20} {:<10} DESCRIPTION", - "ID", "NAME", "CATEGORY" - ); + println!("{:<14} {:<20} {:<10} DESCRIPTION", "ID", "NAME", "CATEGORY"); println!("{}", "-".repeat(72)); for h in arr { println!( @@ -3968,7 +3969,12 @@ fn cmd_hand_list() { h["id"].as_str().unwrap_or("?"), h["name"].as_str().unwrap_or("?"), h["category"].as_str().unwrap_or("?"), - h["description"].as_str().unwrap_or("").chars().take(40).collect::(), + h["description"] + .as_str() + .unwrap_or("") + .chars() + .take(40) + .collect::(), ); } println!("\nUse `openfang hand activate ` to activate a hand."); @@ -3990,10 +3996,7 @@ fn cmd_hand_active() { println!("No active hands."); return; } - println!( - "{:<38} {:<14} {:<10} AGENT", - "INSTANCE", "HAND", "STATUS" - ); + println!("{:<38} {:<14} {:<10} AGENT", "INSTANCE", "HAND", "STATUS"); println!("{}", "-".repeat(72)); for i in &arr { println!( @@ -4081,10 +4084,7 @@ fn cmd_hand_info(id: &str) { let client = daemon_client(); let body = daemon_json(client.get(format!("{base}/api/hands/{id}")).send()); if body.get("error").is_some() { - eprintln!( - "Hand not found: {}", - body["error"].as_str().unwrap_or(id) - ); + eprintln!("Hand not found: {}", body["error"].as_str().unwrap_or(id)); std::process::exit(1); } println!( @@ -5403,7 +5403,15 @@ fn cmd_cron_create(agent: &str, spec: &str, prompt: &str, explicit_name: Option< .filter(|c| c.is_alphanumeric() || *c == '-' || *c == '_') .take(64) .collect(); - format!("{}-{}", agent, if short_prompt.is_empty() { "job" } else { &short_prompt }) + format!( + "{}-{}", + agent, + if short_prompt.is_empty() { + "job" + } else { + &short_prompt + } + ) }; let body = daemon_json( @@ -6157,10 +6165,7 @@ fn cmd_uninstall(confirm: bool, keep_config: bool) { } else { match std::fs::remove_dir_all(&openfang_dir) { Ok(()) => ui::success(&format!("Removed {}", openfang_dir.display())), - Err(e) => ui::error(&format!( - "Failed to remove {}: {e}", - openfang_dir.display() - )), + Err(e) => ui::error(&format!("Failed to remove {}: {e}", openfang_dir.display())), } } } @@ -6169,10 +6174,7 @@ fn cmd_uninstall(confirm: bool, keep_config: bool) { if cargo_bin.exists() && exe_path.as_ref().is_none_or(|e| *e != cargo_bin) { match std::fs::remove_file(&cargo_bin) { Ok(()) => ui::success(&format!("Removed {}", cargo_bin.display())), - Err(e) => ui::error(&format!( - "Failed to remove {}: {e}", - cargo_bin.display() - )), + Err(e) => ui::error(&format!("Failed to remove {}: {e}", cargo_bin.display())), } } @@ -6412,7 +6414,10 @@ fn remove_self_binary(exe_path: &std::path::Path) { .creation_flags(CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS) .spawn(); - ui::success(&format!("Removed {} (deferred cleanup)", exe_path.display())); + ui::success(&format!( + "Removed {} (deferred cleanup)", + exe_path.display() + )); } } diff --git a/crates/openfang-cli/src/tui/chat_runner.rs b/crates/openfang-cli/src/tui/chat_runner.rs index c2ca8fede..9ad032f11 100644 --- a/crates/openfang-cli/src/tui/chat_runner.rs +++ b/crates/openfang-cli/src/tui/chat_runner.rs @@ -394,10 +394,7 @@ impl StandaloneChat { .as_str() .unwrap_or("") .to_string(), - provider: m["provider"] - .as_str() - .unwrap_or("") - .to_string(), + provider: m["provider"].as_str().unwrap_or("").to_string(), tier: m["tier"].as_str().unwrap_or("Balanced").to_string(), }) .collect() @@ -459,16 +456,13 @@ impl StandaloneChat { .send() { if let Ok(body) = resp.json::() { - let provider = - body["model_provider"].as_str().unwrap_or("?"); + let provider = body["model_provider"].as_str().unwrap_or("?"); let model = body["model_name"].as_str().unwrap_or("?"); self.chat.model_label = format!("{provider}/{model}"); } } - self.chat.push_message( - Role::System, - format!("Switched to {model_id}"), - ); + self.chat + .push_message(Role::System, format!("Switched to {model_id}")); } _ => { self.chat.push_message( @@ -506,16 +500,12 @@ impl StandaloneChat { .unwrap_or_else(|| "?".to_string()) }); self.chat.model_label = format!("{prov_label}/{model_id}"); - self.chat.push_message( - Role::System, - format!("Switched to {model_id}"), - ); + self.chat + .push_message(Role::System, format!("Switched to {model_id}")); } Err(e) => { - self.chat.push_message( - Role::System, - format!("Switch failed: {e}"), - ); + self.chat + .push_message(Role::System, format!("Switch failed: {e}")); } } } diff --git a/crates/openfang-cli/src/tui/mod.rs b/crates/openfang-cli/src/tui/mod.rs index 907c0aed6..dce704345 100644 --- a/crates/openfang-cli/src/tui/mod.rs +++ b/crates/openfang-cli/src/tui/mod.rs @@ -516,8 +516,7 @@ impl App { } AppEvent::CommsEventsLoaded(events) => { self.comms.events = events; - if !self.comms.events.is_empty() - && self.comms.event_list_state.selected().is_none() + if !self.comms.events.is_empty() && self.comms.event_list_state.selected().is_none() { self.comms.event_list_state.select(Some(0)); } @@ -1869,14 +1868,8 @@ impl App { .as_str() .unwrap_or("") .to_string(), - provider: m["provider"] - .as_str() - .unwrap_or("") - .to_string(), - tier: m["tier"] - .as_str() - .unwrap_or("Balanced") - .to_string(), + provider: m["provider"].as_str().unwrap_or("").to_string(), + tier: m["tier"].as_str().unwrap_or("Balanced").to_string(), }) .collect() }) @@ -1935,8 +1928,7 @@ impl App { .send() { if let Ok(body) = resp.json::() { - let provider = - body["model_provider"].as_str().unwrap_or("?"); + let provider = body["model_provider"].as_str().unwrap_or("?"); let model = body["model_name"].as_str().unwrap_or("?"); self.chat.model_label = format!("{provider}/{model}"); } @@ -1988,10 +1980,8 @@ impl App { ); } Err(e) => { - self.chat.push_message( - chat::Role::System, - format!("Switch failed: {e}"), - ); + self.chat + .push_message(chat::Role::System, format!("Switch failed: {e}")); } } } diff --git a/crates/openfang-cli/src/tui/screens/agents.rs b/crates/openfang-cli/src/tui/screens/agents.rs index 26ecb3469..9121dc938 100644 --- a/crates/openfang-cli/src/tui/screens/agents.rs +++ b/crates/openfang-cli/src/tui/screens/agents.rs @@ -1524,6 +1524,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/audit.rs b/crates/openfang-cli/src/tui/screens/audit.rs index 2fd3d2fe5..f7aa45379 100644 --- a/crates/openfang-cli/src/tui/screens/audit.rs +++ b/crates/openfang-cli/src/tui/screens/audit.rs @@ -341,6 +341,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/chat.rs b/crates/openfang-cli/src/tui/screens/chat.rs index 96fe994e1..681d8b385 100644 --- a/crates/openfang-cli/src/tui/screens/chat.rs +++ b/crates/openfang-cli/src/tui/screens/chat.rs @@ -483,8 +483,7 @@ fn draw_model_picker(f: &mut Frame, area: Rect, state: &ChatState) { return; // Too small to show picker } let popup_w = area.width.clamp(30, 54); - let popup_h = (filtered.len() as u16 + 4) - .clamp(5, area.height.saturating_sub(2)); + let popup_h = (filtered.len() as u16 + 4).clamp(5, area.height.saturating_sub(2)); let x = area.x + (area.width.saturating_sub(popup_w)) / 2; let y = area.y + (area.height.saturating_sub(popup_h)) / 2; let popup_area = Rect::new(x, y, popup_w, popup_h); @@ -548,7 +547,12 @@ fn draw_model_picker(f: &mut Frame, area: Rect, state: &ChatState) { let mut lines: Vec = Vec::new(); let max_name = (chunks[1].width as usize).saturating_sub(14); - for (i, entry) in filtered.iter().enumerate().skip(scroll_start).take(visible_h) { + for (i, entry) in filtered + .iter() + .enumerate() + .skip(scroll_start) + .take(visible_h) + { let selected = i == state.model_picker_idx; let indicator = if selected { "\u{25b6} " } else { " " }; @@ -882,6 +886,9 @@ fn truncate_line(s: &str, max_len: usize) -> String { if s.len() <= max_len { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max_len.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max_len.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/comms.rs b/crates/openfang-cli/src/tui/screens/comms.rs index 40ffc8e5d..b0a5b84b2 100644 --- a/crates/openfang-cli/src/tui/screens/comms.rs +++ b/crates/openfang-cli/src/tui/screens/comms.rs @@ -158,11 +158,7 @@ impl CommsState { KeyCode::Up | KeyCode::Char('k') => { if self.focus == CommsFocus::EventList && !self.events.is_empty() { let i = self.event_list_state.selected().unwrap_or(0); - let next = if i == 0 { - self.events.len() - 1 - } else { - i - 1 - }; + let next = if i == 0 { self.events.len() - 1 } else { i - 1 }; self.event_list_state.select(Some(next)); } } @@ -339,12 +335,12 @@ pub fn draw(f: &mut Frame, area: Rect, state: &mut CommsState) { f.render_widget(block, area); let chunks = Layout::vertical([ - Constraint::Length(2), // header - Constraint::Length(1), // separator + Constraint::Length(2), // header + Constraint::Length(1), // separator Constraint::Percentage(35), // topology - Constraint::Length(1), // separator - Constraint::Min(4), // event list - Constraint::Length(1), // hints + Constraint::Length(1), // separator + Constraint::Min(4), // event list + Constraint::Length(1), // hints ]) .split(inner); @@ -441,10 +437,7 @@ fn draw_topology(f: &mut Frame, area: Rect, state: &CommsState) { if state.nodes.is_empty() { f.render_widget( - Paragraph::new(Span::styled( - " No agents running.", - theme::dim_style(), - )), + Paragraph::new(Span::styled(" No agents running.", theme::dim_style())), area, ); return; @@ -491,7 +484,10 @@ fn draw_topology(f: &mut Frame, area: Rect, state: &CommsState) { Span::styled(" ", Style::default()), Span::styled(branch, theme::dim_style()), Span::styled(format!("[{}]", child.state), state_color(&child.state)), - Span::styled(format!(" {} ", child.name), Style::default().fg(theme::TEXT)), + Span::styled( + format!(" {} ", child.name), + Style::default().fg(theme::TEXT), + ), Span::styled(format!("({})", child.model), theme::dim_style()), ])); } @@ -679,7 +675,10 @@ fn draw_task_modal(f: &mut Frame, area: Rect, state: &CommsState) { rows[3], ); f.render_widget( - Paragraph::new(Span::styled("Assign to (agent ID, optional):", field_style(2))), + Paragraph::new(Span::styled( + "Assign to (agent ID, optional):", + field_style(2), + )), rows[4], ); f.render_widget( diff --git a/crates/openfang-cli/src/tui/screens/dashboard.rs b/crates/openfang-cli/src/tui/screens/dashboard.rs index 4a6bac7b5..a6b8b25e8 100644 --- a/crates/openfang-cli/src/tui/screens/dashboard.rs +++ b/crates/openfang-cli/src/tui/screens/dashboard.rs @@ -273,6 +273,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/init_wizard.rs b/crates/openfang-cli/src/tui/screens/init_wizard.rs index 2ad2a3f91..9e60ae1c3 100644 --- a/crates/openfang-cli/src/tui/screens/init_wizard.rs +++ b/crates/openfang-cli/src/tui/screens/init_wizard.rs @@ -172,6 +172,14 @@ const PROVIDERS: &[ProviderInfo] = &[ needs_key: true, hint: "", }, + ProviderInfo { + name: "venice", + display: "Venice.ai", + env_var: "VENICE_API_KEY", + default_model: "venice-uncensored", + needs_key: true, + hint: "privacy-focused", + }, ProviderInfo { name: "ai21", display: "AI21", @@ -916,7 +924,9 @@ fn handle_migration_key( let target_dir = if let Ok(h) = std::env::var("OPENFANG_HOME") { PathBuf::from(h) } else { - dirs::home_dir().unwrap_or_else(|| PathBuf::from(".")).join(".openfang") + dirs::home_dir() + .unwrap_or_else(|| PathBuf::from(".")) + .join(".openfang") }; let tx = migrate_tx.clone(); std::thread::spawn(move || { diff --git a/crates/openfang-cli/src/tui/screens/logs.rs b/crates/openfang-cli/src/tui/screens/logs.rs index d69077e6d..40b6656a2 100644 --- a/crates/openfang-cli/src/tui/screens/logs.rs +++ b/crates/openfang-cli/src/tui/screens/logs.rs @@ -405,6 +405,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/memory.rs b/crates/openfang-cli/src/tui/screens/memory.rs index e8bea52dd..259a2a2ec 100644 --- a/crates/openfang-cli/src/tui/screens/memory.rs +++ b/crates/openfang-cli/src/tui/screens/memory.rs @@ -549,6 +549,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/mod.rs b/crates/openfang-cli/src/tui/screens/mod.rs index 9b395dcee..25897100f 100644 --- a/crates/openfang-cli/src/tui/screens/mod.rs +++ b/crates/openfang-cli/src/tui/screens/mod.rs @@ -1,8 +1,8 @@ pub mod agents; pub mod audit; pub mod channels; -pub mod comms; pub mod chat; +pub mod comms; pub mod dashboard; pub mod extensions; pub mod hands; diff --git a/crates/openfang-cli/src/tui/screens/peers.rs b/crates/openfang-cli/src/tui/screens/peers.rs index d9b3a95ce..a7039687f 100644 --- a/crates/openfang-cli/src/tui/screens/peers.rs +++ b/crates/openfang-cli/src/tui/screens/peers.rs @@ -208,6 +208,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/sessions.rs b/crates/openfang-cli/src/tui/screens/sessions.rs index 1c47893a7..b9eae648f 100644 --- a/crates/openfang-cli/src/tui/screens/sessions.rs +++ b/crates/openfang-cli/src/tui/screens/sessions.rs @@ -308,6 +308,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/settings.rs b/crates/openfang-cli/src/tui/screens/settings.rs index 978b6ad8b..b97e34605 100644 --- a/crates/openfang-cli/src/tui/screens/settings.rs +++ b/crates/openfang-cli/src/tui/screens/settings.rs @@ -604,7 +604,10 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/skills.rs b/crates/openfang-cli/src/tui/screens/skills.rs index 662d51043..5494ebaf6 100644 --- a/crates/openfang-cli/src/tui/screens/skills.rs +++ b/crates/openfang-cli/src/tui/screens/skills.rs @@ -612,7 +612,10 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/templates.rs b/crates/openfang-cli/src/tui/screens/templates.rs index b8a3a87c1..eae8faa72 100644 --- a/crates/openfang-cli/src/tui/screens/templates.rs +++ b/crates/openfang-cli/src/tui/screens/templates.rs @@ -399,6 +399,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/triggers.rs b/crates/openfang-cli/src/tui/screens/triggers.rs index 979f958c6..d55ddb6d5 100644 --- a/crates/openfang-cli/src/tui/screens/triggers.rs +++ b/crates/openfang-cli/src/tui/screens/triggers.rs @@ -549,6 +549,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/usage.rs b/crates/openfang-cli/src/tui/screens/usage.rs index 9e2fb1e53..e0f829cf2 100644 --- a/crates/openfang-cli/src/tui/screens/usage.rs +++ b/crates/openfang-cli/src/tui/screens/usage.rs @@ -439,6 +439,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-cli/src/tui/screens/workflows.rs b/crates/openfang-cli/src/tui/screens/workflows.rs index 50abde224..21514923a 100644 --- a/crates/openfang-cli/src/tui/screens/workflows.rs +++ b/crates/openfang-cli/src/tui/screens/workflows.rs @@ -697,6 +697,9 @@ fn truncate(s: &str, max: usize) -> String { if s.len() <= max { s.to_string() } else { - format!("{}\u{2026}", openfang_types::truncate_str(s, max.saturating_sub(1))) + format!( + "{}\u{2026}", + openfang_types::truncate_str(s, max.saturating_sub(1)) + ) } } diff --git a/crates/openfang-desktop/gen/schemas/linux-schema.json b/crates/openfang-desktop/gen/schemas/linux-schema.json new file mode 100644 index 000000000..c1dc14d8c --- /dev/null +++ b/crates/openfang-desktop/gen/schemas/linux-schema.json @@ -0,0 +1,2990 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CapabilityFile", + "description": "Capability formats accepted in a capability file.", + "anyOf": [ + { + "description": "A single capability.", + "allOf": [ + { + "$ref": "#/definitions/Capability" + } + ] + }, + { + "description": "A list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + }, + { + "description": "A list of capabilities.", + "type": "object", + "required": [ + "capabilities" + ], + "properties": { + "capabilities": { + "description": "The list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + } + } + } + ], + "definitions": { + "Capability": { + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows' and webviews' fine grained access to the Tauri core, application, or plugin commands. If a webview or its window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```", + "type": "object", + "required": [ + "identifier", + "permissions" + ], + "properties": { + "identifier": { + "description": "Identifier of the capability.\n\n## Example\n\n`main-user-files-write`", + "type": "string" + }, + "description": { + "description": "Description of what the capability is intended to allow on associated windows.\n\nIt should contain a description of what the grouped permissions should allow.\n\n## Example\n\nThis capability allows the `main` window access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.", + "default": "", + "type": "string" + }, + "remote": { + "description": "Configure remote URLs that can use the capability permissions.\n\nThis setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.\n\n:::caution Make sure you understand the security implications of providing remote sources with local system access. :::\n\n## Example\n\n```json { \"urls\": [\"https://*.mydomain.dev\"] } ```", + "anyOf": [ + { + "$ref": "#/definitions/CapabilityRemote" + }, + { + "type": "null" + } + ] + }, + "local": { + "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", + "default": true, + "type": "boolean" + }, + "windows": { + "description": "List of windows that are affected by this capability. Can be a glob pattern.\n\nIf a window label matches any of the patterns in this list, the capability will be enabled on all the webviews of that window, regardless of the value of [`Self::webviews`].\n\nOn multiwebview windows, prefer specifying [`Self::webviews`] and omitting [`Self::windows`] for a fine grained access control.\n\n## Example\n\n`[\"main\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "webviews": { + "description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\nThe capability will be enabled on all the webviews whose label matches any of the patterns in this list, regardless of whether the webview's window label matches a pattern in [`Self::windows`].\n\n## Example\n\n`[\"sub-webview-one\", \"sub-webview-two\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionEntry" + }, + "uniqueItems": true + }, + "platforms": { + "description": "Limit which target platforms this capability applies to.\n\nBy default all platforms are targeted.\n\n## Example\n\n`[\"macOS\",\"windows\"]`", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Target" + } + } + } + }, + "CapabilityRemote": { + "description": "Configuration for remote URLs that are associated with the capability.", + "type": "object", + "required": [ + "urls" + ], + "properties": { + "urls": { + "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n## Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PermissionEntry": { + "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.", + "anyOf": [ + { + "description": "Reference a permission or permission set by identifier.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + { + "description": "Reference a permission or permission set by identifier and extends its scope.", + "type": "object", + "allOf": [ + { + "if": { + "properties": { + "identifier": { + "anyOf": [ + { + "description": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n\n#### This default permission set includes:\n\n- `allow-open`", + "type": "string", + "const": "shell:default", + "markdownDescription": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n\n#### This default permission set includes:\n\n- `allow-open`" + }, + { + "description": "Enables the execute command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-execute", + "markdownDescription": "Enables the execute command without any pre-configured scope." + }, + { + "description": "Enables the kill command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-kill", + "markdownDescription": "Enables the kill command without any pre-configured scope." + }, + { + "description": "Enables the open command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-open", + "markdownDescription": "Enables the open command without any pre-configured scope." + }, + { + "description": "Enables the spawn command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-spawn", + "markdownDescription": "Enables the spawn command without any pre-configured scope." + }, + { + "description": "Enables the stdin_write command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-stdin-write", + "markdownDescription": "Enables the stdin_write command without any pre-configured scope." + }, + { + "description": "Denies the execute command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-execute", + "markdownDescription": "Denies the execute command without any pre-configured scope." + }, + { + "description": "Denies the kill command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-kill", + "markdownDescription": "Denies the kill command without any pre-configured scope." + }, + { + "description": "Denies the open command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-open", + "markdownDescription": "Denies the open command without any pre-configured scope." + }, + { + "description": "Denies the spawn command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-spawn", + "markdownDescription": "Denies the spawn command without any pre-configured scope." + }, + { + "description": "Denies the stdin_write command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-stdin-write", + "markdownDescription": "Denies the stdin_write command without any pre-configured scope." + } + ] + } + } + }, + "then": { + "properties": { + "allow": { + "items": { + "title": "ShellScopeEntry", + "description": "Shell scope entry.", + "anyOf": [ + { + "type": "object", + "required": [ + "cmd", + "name" + ], + "properties": { + "args": { + "description": "The allowed arguments for the command execution.", + "allOf": [ + { + "$ref": "#/definitions/ShellScopeEntryAllowedArgs" + } + ] + }, + "cmd": { + "description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", + "type": "string" + }, + "name": { + "description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "name", + "sidecar" + ], + "properties": { + "args": { + "description": "The allowed arguments for the command execution.", + "allOf": [ + { + "$ref": "#/definitions/ShellScopeEntryAllowedArgs" + } + ] + }, + "name": { + "description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.", + "type": "string" + }, + "sidecar": { + "description": "If this command is a sidecar command.", + "type": "boolean" + } + }, + "additionalProperties": false + } + ] + } + }, + "deny": { + "items": { + "title": "ShellScopeEntry", + "description": "Shell scope entry.", + "anyOf": [ + { + "type": "object", + "required": [ + "cmd", + "name" + ], + "properties": { + "args": { + "description": "The allowed arguments for the command execution.", + "allOf": [ + { + "$ref": "#/definitions/ShellScopeEntryAllowedArgs" + } + ] + }, + "cmd": { + "description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", + "type": "string" + }, + "name": { + "description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.", + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "name", + "sidecar" + ], + "properties": { + "args": { + "description": "The allowed arguments for the command execution.", + "allOf": [ + { + "$ref": "#/definitions/ShellScopeEntryAllowedArgs" + } + ] + }, + "name": { + "description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.", + "type": "string" + }, + "sidecar": { + "description": "If this command is a sidecar command.", + "type": "boolean" + } + }, + "additionalProperties": false + } + ] + } + } + } + }, + "properties": { + "identifier": { + "description": "Identifier of the permission or permission set.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + } + } + }, + { + "properties": { + "identifier": { + "description": "Identifier of the permission or permission set.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + "allow": { + "description": "Data that defines what is allowed by the scope.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + }, + "deny": { + "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + } + } + } + ], + "required": [ + "identifier" + ] + } + ] + }, + "Identifier": { + "description": "Permission identifier", + "oneOf": [ + { + "description": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`", + "type": "string", + "const": "autostart:default", + "markdownDescription": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`" + }, + { + "description": "Enables the disable command without any pre-configured scope.", + "type": "string", + "const": "autostart:allow-disable", + "markdownDescription": "Enables the disable command without any pre-configured scope." + }, + { + "description": "Enables the enable command without any pre-configured scope.", + "type": "string", + "const": "autostart:allow-enable", + "markdownDescription": "Enables the enable command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "autostart:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the disable command without any pre-configured scope.", + "type": "string", + "const": "autostart:deny-disable", + "markdownDescription": "Denies the disable command without any pre-configured scope." + }, + { + "description": "Denies the enable command without any pre-configured scope.", + "type": "string", + "const": "autostart:deny-enable", + "markdownDescription": "Denies the enable command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "autostart:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`", + "type": "string", + "const": "core:default", + "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`", + "type": "string", + "const": "core:app:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`" + }, + { + "description": "Enables the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-hide", + "markdownDescription": "Enables the app_hide command without any pre-configured scope." + }, + { + "description": "Enables the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-show", + "markdownDescription": "Enables the app_show command without any pre-configured scope." + }, + { + "description": "Enables the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-bundle-type", + "markdownDescription": "Enables the bundle_type command without any pre-configured scope." + }, + { + "description": "Enables the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-default-window-icon", + "markdownDescription": "Enables the default_window_icon command without any pre-configured scope." + }, + { + "description": "Enables the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-fetch-data-store-identifiers", + "markdownDescription": "Enables the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Enables the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-identifier", + "markdownDescription": "Enables the identifier command without any pre-configured scope." + }, + { + "description": "Enables the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-name", + "markdownDescription": "Enables the name command without any pre-configured scope." + }, + { + "description": "Enables the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-register-listener", + "markdownDescription": "Enables the register_listener command without any pre-configured scope." + }, + { + "description": "Enables the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-data-store", + "markdownDescription": "Enables the remove_data_store command without any pre-configured scope." + }, + { + "description": "Enables the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-listener", + "markdownDescription": "Enables the remove_listener command without any pre-configured scope." + }, + { + "description": "Enables the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-app-theme", + "markdownDescription": "Enables the set_app_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-dock-visibility", + "markdownDescription": "Enables the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Enables the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-tauri-version", + "markdownDescription": "Enables the tauri_version command without any pre-configured scope." + }, + { + "description": "Enables the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-version", + "markdownDescription": "Enables the version command without any pre-configured scope." + }, + { + "description": "Denies the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-hide", + "markdownDescription": "Denies the app_hide command without any pre-configured scope." + }, + { + "description": "Denies the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-show", + "markdownDescription": "Denies the app_show command without any pre-configured scope." + }, + { + "description": "Denies the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-bundle-type", + "markdownDescription": "Denies the bundle_type command without any pre-configured scope." + }, + { + "description": "Denies the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-default-window-icon", + "markdownDescription": "Denies the default_window_icon command without any pre-configured scope." + }, + { + "description": "Denies the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-fetch-data-store-identifiers", + "markdownDescription": "Denies the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Denies the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-identifier", + "markdownDescription": "Denies the identifier command without any pre-configured scope." + }, + { + "description": "Denies the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-name", + "markdownDescription": "Denies the name command without any pre-configured scope." + }, + { + "description": "Denies the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-register-listener", + "markdownDescription": "Denies the register_listener command without any pre-configured scope." + }, + { + "description": "Denies the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-data-store", + "markdownDescription": "Denies the remove_data_store command without any pre-configured scope." + }, + { + "description": "Denies the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-listener", + "markdownDescription": "Denies the remove_listener command without any pre-configured scope." + }, + { + "description": "Denies the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-app-theme", + "markdownDescription": "Denies the set_app_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-dock-visibility", + "markdownDescription": "Denies the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Denies the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-tauri-version", + "markdownDescription": "Denies the tauri_version command without any pre-configured scope." + }, + { + "description": "Denies the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-version", + "markdownDescription": "Denies the version command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`", + "type": "string", + "const": "core:event:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`" + }, + { + "description": "Enables the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit", + "markdownDescription": "Enables the emit command without any pre-configured scope." + }, + { + "description": "Enables the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit-to", + "markdownDescription": "Enables the emit_to command without any pre-configured scope." + }, + { + "description": "Enables the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-listen", + "markdownDescription": "Enables the listen command without any pre-configured scope." + }, + { + "description": "Enables the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-unlisten", + "markdownDescription": "Enables the unlisten command without any pre-configured scope." + }, + { + "description": "Denies the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit", + "markdownDescription": "Denies the emit command without any pre-configured scope." + }, + { + "description": "Denies the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit-to", + "markdownDescription": "Denies the emit_to command without any pre-configured scope." + }, + { + "description": "Denies the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-listen", + "markdownDescription": "Denies the listen command without any pre-configured scope." + }, + { + "description": "Denies the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-unlisten", + "markdownDescription": "Denies the unlisten command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`", + "type": "string", + "const": "core:image:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`" + }, + { + "description": "Enables the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-bytes", + "markdownDescription": "Enables the from_bytes command without any pre-configured scope." + }, + { + "description": "Enables the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-path", + "markdownDescription": "Enables the from_path command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-rgba", + "markdownDescription": "Enables the rgba command without any pre-configured scope." + }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-size", + "markdownDescription": "Enables the size command without any pre-configured scope." + }, + { + "description": "Denies the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-bytes", + "markdownDescription": "Denies the from_bytes command without any pre-configured scope." + }, + { + "description": "Denies the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-path", + "markdownDescription": "Denies the from_path command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-rgba", + "markdownDescription": "Denies the rgba command without any pre-configured scope." + }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-size", + "markdownDescription": "Denies the size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`", + "type": "string", + "const": "core:menu:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`" + }, + { + "description": "Enables the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-append", + "markdownDescription": "Enables the append command without any pre-configured scope." + }, + { + "description": "Enables the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-create-default", + "markdownDescription": "Enables the create_default command without any pre-configured scope." + }, + { + "description": "Enables the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-get", + "markdownDescription": "Enables the get command without any pre-configured scope." + }, + { + "description": "Enables the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-insert", + "markdownDescription": "Enables the insert command without any pre-configured scope." + }, + { + "description": "Enables the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-checked", + "markdownDescription": "Enables the is_checked command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-items", + "markdownDescription": "Enables the items command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-popup", + "markdownDescription": "Enables the popup command without any pre-configured scope." + }, + { + "description": "Enables the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-prepend", + "markdownDescription": "Enables the prepend command without any pre-configured scope." + }, + { + "description": "Enables the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove", + "markdownDescription": "Enables the remove command without any pre-configured scope." + }, + { + "description": "Enables the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove-at", + "markdownDescription": "Enables the remove_at command without any pre-configured scope." + }, + { + "description": "Enables the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-accelerator", + "markdownDescription": "Enables the set_accelerator command without any pre-configured scope." + }, + { + "description": "Enables the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-app-menu", + "markdownDescription": "Enables the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-help-menu-for-nsapp", + "markdownDescription": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-window-menu", + "markdownDescription": "Enables the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-windows-menu-for-nsapp", + "markdownDescription": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-checked", + "markdownDescription": "Enables the set_checked command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-text", + "markdownDescription": "Enables the set_text command without any pre-configured scope." + }, + { + "description": "Enables the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-text", + "markdownDescription": "Enables the text command without any pre-configured scope." + }, + { + "description": "Denies the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-append", + "markdownDescription": "Denies the append command without any pre-configured scope." + }, + { + "description": "Denies the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-create-default", + "markdownDescription": "Denies the create_default command without any pre-configured scope." + }, + { + "description": "Denies the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-get", + "markdownDescription": "Denies the get command without any pre-configured scope." + }, + { + "description": "Denies the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-insert", + "markdownDescription": "Denies the insert command without any pre-configured scope." + }, + { + "description": "Denies the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-checked", + "markdownDescription": "Denies the is_checked command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-items", + "markdownDescription": "Denies the items command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-popup", + "markdownDescription": "Denies the popup command without any pre-configured scope." + }, + { + "description": "Denies the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-prepend", + "markdownDescription": "Denies the prepend command without any pre-configured scope." + }, + { + "description": "Denies the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove", + "markdownDescription": "Denies the remove command without any pre-configured scope." + }, + { + "description": "Denies the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove-at", + "markdownDescription": "Denies the remove_at command without any pre-configured scope." + }, + { + "description": "Denies the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-accelerator", + "markdownDescription": "Denies the set_accelerator command without any pre-configured scope." + }, + { + "description": "Denies the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-app-menu", + "markdownDescription": "Denies the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-help-menu-for-nsapp", + "markdownDescription": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-window-menu", + "markdownDescription": "Denies the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-windows-menu-for-nsapp", + "markdownDescription": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-checked", + "markdownDescription": "Denies the set_checked command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-text", + "markdownDescription": "Denies the set_text command without any pre-configured scope." + }, + { + "description": "Denies the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-text", + "markdownDescription": "Denies the text command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`", + "type": "string", + "const": "core:path:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`" + }, + { + "description": "Enables the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-basename", + "markdownDescription": "Enables the basename command without any pre-configured scope." + }, + { + "description": "Enables the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-dirname", + "markdownDescription": "Enables the dirname command without any pre-configured scope." + }, + { + "description": "Enables the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-extname", + "markdownDescription": "Enables the extname command without any pre-configured scope." + }, + { + "description": "Enables the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-is-absolute", + "markdownDescription": "Enables the is_absolute command without any pre-configured scope." + }, + { + "description": "Enables the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-join", + "markdownDescription": "Enables the join command without any pre-configured scope." + }, + { + "description": "Enables the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-normalize", + "markdownDescription": "Enables the normalize command without any pre-configured scope." + }, + { + "description": "Enables the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve", + "markdownDescription": "Enables the resolve command without any pre-configured scope." + }, + { + "description": "Enables the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve-directory", + "markdownDescription": "Enables the resolve_directory command without any pre-configured scope." + }, + { + "description": "Denies the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-basename", + "markdownDescription": "Denies the basename command without any pre-configured scope." + }, + { + "description": "Denies the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-dirname", + "markdownDescription": "Denies the dirname command without any pre-configured scope." + }, + { + "description": "Denies the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-extname", + "markdownDescription": "Denies the extname command without any pre-configured scope." + }, + { + "description": "Denies the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-is-absolute", + "markdownDescription": "Denies the is_absolute command without any pre-configured scope." + }, + { + "description": "Denies the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-join", + "markdownDescription": "Denies the join command without any pre-configured scope." + }, + { + "description": "Denies the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-normalize", + "markdownDescription": "Denies the normalize command without any pre-configured scope." + }, + { + "description": "Denies the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve", + "markdownDescription": "Denies the resolve command without any pre-configured scope." + }, + { + "description": "Denies the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve-directory", + "markdownDescription": "Denies the resolve_directory command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`", + "type": "string", + "const": "core:resources:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`" + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`", + "type": "string", + "const": "core:tray:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`" + }, + { + "description": "Enables the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-get-by-id", + "markdownDescription": "Enables the get_by_id command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-remove-by-id", + "markdownDescription": "Enables the remove_by_id command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-as-template", + "markdownDescription": "Enables the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Enables the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-menu", + "markdownDescription": "Enables the set_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-show-menu-on-left-click", + "markdownDescription": "Enables the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Enables the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-temp-dir-path", + "markdownDescription": "Enables the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-tooltip", + "markdownDescription": "Enables the set_tooltip command without any pre-configured scope." + }, + { + "description": "Enables the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-visible", + "markdownDescription": "Enables the set_visible command without any pre-configured scope." + }, + { + "description": "Denies the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-get-by-id", + "markdownDescription": "Denies the get_by_id command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-remove-by-id", + "markdownDescription": "Denies the remove_by_id command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-as-template", + "markdownDescription": "Denies the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Denies the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-menu", + "markdownDescription": "Denies the set_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-show-menu-on-left-click", + "markdownDescription": "Denies the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Denies the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-temp-dir-path", + "markdownDescription": "Denies the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-tooltip", + "markdownDescription": "Denies the set_tooltip command without any pre-configured scope." + }, + { + "description": "Denies the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-visible", + "markdownDescription": "Denies the set_visible command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`", + "type": "string", + "const": "core:webview:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`" + }, + { + "description": "Enables the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-clear-all-browsing-data", + "markdownDescription": "Enables the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Enables the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview", + "markdownDescription": "Enables the create_webview command without any pre-configured scope." + }, + { + "description": "Enables the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview-window", + "markdownDescription": "Enables the create_webview_window command without any pre-configured scope." + }, + { + "description": "Enables the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-get-all-webviews", + "markdownDescription": "Enables the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-internal-toggle-devtools", + "markdownDescription": "Enables the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Enables the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-print", + "markdownDescription": "Enables the print command without any pre-configured scope." + }, + { + "description": "Enables the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-reparent", + "markdownDescription": "Enables the reparent command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-auto-resize", + "markdownDescription": "Enables the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-background-color", + "markdownDescription": "Enables the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-focus", + "markdownDescription": "Enables the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-position", + "markdownDescription": "Enables the set_webview_position command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-size", + "markdownDescription": "Enables the set_webview_size command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-zoom", + "markdownDescription": "Enables the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Enables the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-close", + "markdownDescription": "Enables the webview_close command without any pre-configured scope." + }, + { + "description": "Enables the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-hide", + "markdownDescription": "Enables the webview_hide command without any pre-configured scope." + }, + { + "description": "Enables the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-position", + "markdownDescription": "Enables the webview_position command without any pre-configured scope." + }, + { + "description": "Enables the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-show", + "markdownDescription": "Enables the webview_show command without any pre-configured scope." + }, + { + "description": "Enables the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-size", + "markdownDescription": "Enables the webview_size command without any pre-configured scope." + }, + { + "description": "Denies the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-clear-all-browsing-data", + "markdownDescription": "Denies the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Denies the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview", + "markdownDescription": "Denies the create_webview command without any pre-configured scope." + }, + { + "description": "Denies the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview-window", + "markdownDescription": "Denies the create_webview_window command without any pre-configured scope." + }, + { + "description": "Denies the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-get-all-webviews", + "markdownDescription": "Denies the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-internal-toggle-devtools", + "markdownDescription": "Denies the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Denies the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-print", + "markdownDescription": "Denies the print command without any pre-configured scope." + }, + { + "description": "Denies the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-reparent", + "markdownDescription": "Denies the reparent command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-auto-resize", + "markdownDescription": "Denies the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-background-color", + "markdownDescription": "Denies the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-focus", + "markdownDescription": "Denies the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-position", + "markdownDescription": "Denies the set_webview_position command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-size", + "markdownDescription": "Denies the set_webview_size command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-zoom", + "markdownDescription": "Denies the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Denies the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-close", + "markdownDescription": "Denies the webview_close command without any pre-configured scope." + }, + { + "description": "Denies the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-hide", + "markdownDescription": "Denies the webview_hide command without any pre-configured scope." + }, + { + "description": "Denies the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-position", + "markdownDescription": "Denies the webview_position command without any pre-configured scope." + }, + { + "description": "Denies the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-show", + "markdownDescription": "Denies the webview_show command without any pre-configured scope." + }, + { + "description": "Denies the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-size", + "markdownDescription": "Denies the webview_size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`", + "type": "string", + "const": "core:window:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`" + }, + { + "description": "Enables the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-available-monitors", + "markdownDescription": "Enables the available_monitors command without any pre-configured scope." + }, + { + "description": "Enables the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-center", + "markdownDescription": "Enables the center command without any pre-configured scope." + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Enables the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-create", + "markdownDescription": "Enables the create command without any pre-configured scope." + }, + { + "description": "Enables the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-current-monitor", + "markdownDescription": "Enables the current_monitor command without any pre-configured scope." + }, + { + "description": "Enables the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-cursor-position", + "markdownDescription": "Enables the cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-destroy", + "markdownDescription": "Enables the destroy command without any pre-configured scope." + }, + { + "description": "Enables the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-get-all-windows", + "markdownDescription": "Enables the get_all_windows command without any pre-configured scope." + }, + { + "description": "Enables the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-hide", + "markdownDescription": "Enables the hide command without any pre-configured scope." + }, + { + "description": "Enables the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-position", + "markdownDescription": "Enables the inner_position command without any pre-configured scope." + }, + { + "description": "Enables the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-size", + "markdownDescription": "Enables the inner_size command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-internal-toggle-maximize", + "markdownDescription": "Enables the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-always-on-top", + "markdownDescription": "Enables the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-closable", + "markdownDescription": "Enables the is_closable command without any pre-configured scope." + }, + { + "description": "Enables the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-decorated", + "markdownDescription": "Enables the is_decorated command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-focused", + "markdownDescription": "Enables the is_focused command without any pre-configured scope." + }, + { + "description": "Enables the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-fullscreen", + "markdownDescription": "Enables the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximizable", + "markdownDescription": "Enables the is_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximized", + "markdownDescription": "Enables the is_maximized command without any pre-configured scope." + }, + { + "description": "Enables the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimizable", + "markdownDescription": "Enables the is_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimized", + "markdownDescription": "Enables the is_minimized command without any pre-configured scope." + }, + { + "description": "Enables the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-resizable", + "markdownDescription": "Enables the is_resizable command without any pre-configured scope." + }, + { + "description": "Enables the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-visible", + "markdownDescription": "Enables the is_visible command without any pre-configured scope." + }, + { + "description": "Enables the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-maximize", + "markdownDescription": "Enables the maximize command without any pre-configured scope." + }, + { + "description": "Enables the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-minimize", + "markdownDescription": "Enables the minimize command without any pre-configured scope." + }, + { + "description": "Enables the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-monitor-from-point", + "markdownDescription": "Enables the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Enables the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-position", + "markdownDescription": "Enables the outer_position command without any pre-configured scope." + }, + { + "description": "Enables the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-size", + "markdownDescription": "Enables the outer_size command without any pre-configured scope." + }, + { + "description": "Enables the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-primary-monitor", + "markdownDescription": "Enables the primary_monitor command without any pre-configured scope." + }, + { + "description": "Enables the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-request-user-attention", + "markdownDescription": "Enables the request_user_attention command without any pre-configured scope." + }, + { + "description": "Enables the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scale-factor", + "markdownDescription": "Enables the scale_factor command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-bottom", + "markdownDescription": "Enables the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-top", + "markdownDescription": "Enables the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-background-color", + "markdownDescription": "Enables the set_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-count", + "markdownDescription": "Enables the set_badge_count command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-label", + "markdownDescription": "Enables the set_badge_label command without any pre-configured scope." + }, + { + "description": "Enables the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-closable", + "markdownDescription": "Enables the set_closable command without any pre-configured scope." + }, + { + "description": "Enables the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-content-protected", + "markdownDescription": "Enables the set_content_protected command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-grab", + "markdownDescription": "Enables the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-icon", + "markdownDescription": "Enables the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-position", + "markdownDescription": "Enables the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-visible", + "markdownDescription": "Enables the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Enables the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-decorations", + "markdownDescription": "Enables the set_decorations command without any pre-configured scope." + }, + { + "description": "Enables the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-effects", + "markdownDescription": "Enables the set_effects command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focus", + "markdownDescription": "Enables the set_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focusable", + "markdownDescription": "Enables the set_focusable command without any pre-configured scope." + }, + { + "description": "Enables the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-fullscreen", + "markdownDescription": "Enables the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-ignore-cursor-events", + "markdownDescription": "Enables the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Enables the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-max-size", + "markdownDescription": "Enables the set_max_size command without any pre-configured scope." + }, + { + "description": "Enables the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-maximizable", + "markdownDescription": "Enables the set_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-min-size", + "markdownDescription": "Enables the set_min_size command without any pre-configured scope." + }, + { + "description": "Enables the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-minimizable", + "markdownDescription": "Enables the set_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-overlay-icon", + "markdownDescription": "Enables the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-position", + "markdownDescription": "Enables the set_position command without any pre-configured scope." + }, + { + "description": "Enables the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-progress-bar", + "markdownDescription": "Enables the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Enables the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-resizable", + "markdownDescription": "Enables the set_resizable command without any pre-configured scope." + }, + { + "description": "Enables the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-shadow", + "markdownDescription": "Enables the set_shadow command without any pre-configured scope." + }, + { + "description": "Enables the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-simple-fullscreen", + "markdownDescription": "Enables the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size", + "markdownDescription": "Enables the set_size command without any pre-configured scope." + }, + { + "description": "Enables the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size-constraints", + "markdownDescription": "Enables the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Enables the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-skip-taskbar", + "markdownDescription": "Enables the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Enables the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-theme", + "markdownDescription": "Enables the set_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title-bar-style", + "markdownDescription": "Enables the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Enables the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-visible-on-all-workspaces", + "markdownDescription": "Enables the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Enables the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-show", + "markdownDescription": "Enables the show command without any pre-configured scope." + }, + { + "description": "Enables the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-dragging", + "markdownDescription": "Enables the start_dragging command without any pre-configured scope." + }, + { + "description": "Enables the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-resize-dragging", + "markdownDescription": "Enables the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Enables the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-theme", + "markdownDescription": "Enables the theme command without any pre-configured scope." + }, + { + "description": "Enables the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-title", + "markdownDescription": "Enables the title command without any pre-configured scope." + }, + { + "description": "Enables the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-toggle-maximize", + "markdownDescription": "Enables the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unmaximize", + "markdownDescription": "Enables the unmaximize command without any pre-configured scope." + }, + { + "description": "Enables the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unminimize", + "markdownDescription": "Enables the unminimize command without any pre-configured scope." + }, + { + "description": "Denies the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-available-monitors", + "markdownDescription": "Denies the available_monitors command without any pre-configured scope." + }, + { + "description": "Denies the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-center", + "markdownDescription": "Denies the center command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Denies the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-create", + "markdownDescription": "Denies the create command without any pre-configured scope." + }, + { + "description": "Denies the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-current-monitor", + "markdownDescription": "Denies the current_monitor command without any pre-configured scope." + }, + { + "description": "Denies the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-cursor-position", + "markdownDescription": "Denies the cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-destroy", + "markdownDescription": "Denies the destroy command without any pre-configured scope." + }, + { + "description": "Denies the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-get-all-windows", + "markdownDescription": "Denies the get_all_windows command without any pre-configured scope." + }, + { + "description": "Denies the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-hide", + "markdownDescription": "Denies the hide command without any pre-configured scope." + }, + { + "description": "Denies the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-position", + "markdownDescription": "Denies the inner_position command without any pre-configured scope." + }, + { + "description": "Denies the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-size", + "markdownDescription": "Denies the inner_size command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-internal-toggle-maximize", + "markdownDescription": "Denies the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-always-on-top", + "markdownDescription": "Denies the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-closable", + "markdownDescription": "Denies the is_closable command without any pre-configured scope." + }, + { + "description": "Denies the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-decorated", + "markdownDescription": "Denies the is_decorated command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-focused", + "markdownDescription": "Denies the is_focused command without any pre-configured scope." + }, + { + "description": "Denies the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-fullscreen", + "markdownDescription": "Denies the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximizable", + "markdownDescription": "Denies the is_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximized", + "markdownDescription": "Denies the is_maximized command without any pre-configured scope." + }, + { + "description": "Denies the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimizable", + "markdownDescription": "Denies the is_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimized", + "markdownDescription": "Denies the is_minimized command without any pre-configured scope." + }, + { + "description": "Denies the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-resizable", + "markdownDescription": "Denies the is_resizable command without any pre-configured scope." + }, + { + "description": "Denies the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-visible", + "markdownDescription": "Denies the is_visible command without any pre-configured scope." + }, + { + "description": "Denies the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-maximize", + "markdownDescription": "Denies the maximize command without any pre-configured scope." + }, + { + "description": "Denies the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-minimize", + "markdownDescription": "Denies the minimize command without any pre-configured scope." + }, + { + "description": "Denies the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-monitor-from-point", + "markdownDescription": "Denies the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Denies the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-position", + "markdownDescription": "Denies the outer_position command without any pre-configured scope." + }, + { + "description": "Denies the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-size", + "markdownDescription": "Denies the outer_size command without any pre-configured scope." + }, + { + "description": "Denies the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-primary-monitor", + "markdownDescription": "Denies the primary_monitor command without any pre-configured scope." + }, + { + "description": "Denies the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-request-user-attention", + "markdownDescription": "Denies the request_user_attention command without any pre-configured scope." + }, + { + "description": "Denies the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scale-factor", + "markdownDescription": "Denies the scale_factor command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-bottom", + "markdownDescription": "Denies the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-top", + "markdownDescription": "Denies the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-background-color", + "markdownDescription": "Denies the set_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-count", + "markdownDescription": "Denies the set_badge_count command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-label", + "markdownDescription": "Denies the set_badge_label command without any pre-configured scope." + }, + { + "description": "Denies the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-closable", + "markdownDescription": "Denies the set_closable command without any pre-configured scope." + }, + { + "description": "Denies the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-content-protected", + "markdownDescription": "Denies the set_content_protected command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-grab", + "markdownDescription": "Denies the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-icon", + "markdownDescription": "Denies the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-position", + "markdownDescription": "Denies the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-visible", + "markdownDescription": "Denies the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Denies the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-decorations", + "markdownDescription": "Denies the set_decorations command without any pre-configured scope." + }, + { + "description": "Denies the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-effects", + "markdownDescription": "Denies the set_effects command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focus", + "markdownDescription": "Denies the set_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focusable", + "markdownDescription": "Denies the set_focusable command without any pre-configured scope." + }, + { + "description": "Denies the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-fullscreen", + "markdownDescription": "Denies the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-ignore-cursor-events", + "markdownDescription": "Denies the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Denies the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-max-size", + "markdownDescription": "Denies the set_max_size command without any pre-configured scope." + }, + { + "description": "Denies the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-maximizable", + "markdownDescription": "Denies the set_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-min-size", + "markdownDescription": "Denies the set_min_size command without any pre-configured scope." + }, + { + "description": "Denies the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-minimizable", + "markdownDescription": "Denies the set_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-overlay-icon", + "markdownDescription": "Denies the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-position", + "markdownDescription": "Denies the set_position command without any pre-configured scope." + }, + { + "description": "Denies the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-progress-bar", + "markdownDescription": "Denies the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Denies the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-resizable", + "markdownDescription": "Denies the set_resizable command without any pre-configured scope." + }, + { + "description": "Denies the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-shadow", + "markdownDescription": "Denies the set_shadow command without any pre-configured scope." + }, + { + "description": "Denies the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-simple-fullscreen", + "markdownDescription": "Denies the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size", + "markdownDescription": "Denies the set_size command without any pre-configured scope." + }, + { + "description": "Denies the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size-constraints", + "markdownDescription": "Denies the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Denies the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-skip-taskbar", + "markdownDescription": "Denies the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Denies the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-theme", + "markdownDescription": "Denies the set_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title-bar-style", + "markdownDescription": "Denies the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Denies the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-visible-on-all-workspaces", + "markdownDescription": "Denies the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Denies the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-show", + "markdownDescription": "Denies the show command without any pre-configured scope." + }, + { + "description": "Denies the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-dragging", + "markdownDescription": "Denies the start_dragging command without any pre-configured scope." + }, + { + "description": "Denies the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-resize-dragging", + "markdownDescription": "Denies the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Denies the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-theme", + "markdownDescription": "Denies the theme command without any pre-configured scope." + }, + { + "description": "Denies the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-title", + "markdownDescription": "Denies the title command without any pre-configured scope." + }, + { + "description": "Denies the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-toggle-maximize", + "markdownDescription": "Denies the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unmaximize", + "markdownDescription": "Denies the unmaximize command without any pre-configured scope." + }, + { + "description": "Denies the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unminimize", + "markdownDescription": "Denies the unminimize command without any pre-configured scope." + }, + { + "description": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-ask`\n- `allow-confirm`\n- `allow-message`\n- `allow-save`\n- `allow-open`", + "type": "string", + "const": "dialog:default", + "markdownDescription": "This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n\n#### This default permission set includes:\n\n- `allow-ask`\n- `allow-confirm`\n- `allow-message`\n- `allow-save`\n- `allow-open`" + }, + { + "description": "Enables the ask command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-ask", + "markdownDescription": "Enables the ask command without any pre-configured scope." + }, + { + "description": "Enables the confirm command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-confirm", + "markdownDescription": "Enables the confirm command without any pre-configured scope." + }, + { + "description": "Enables the message command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-message", + "markdownDescription": "Enables the message command without any pre-configured scope." + }, + { + "description": "Enables the open command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-open", + "markdownDescription": "Enables the open command without any pre-configured scope." + }, + { + "description": "Enables the save command without any pre-configured scope.", + "type": "string", + "const": "dialog:allow-save", + "markdownDescription": "Enables the save command without any pre-configured scope." + }, + { + "description": "Denies the ask command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-ask", + "markdownDescription": "Denies the ask command without any pre-configured scope." + }, + { + "description": "Denies the confirm command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-confirm", + "markdownDescription": "Denies the confirm command without any pre-configured scope." + }, + { + "description": "Denies the message command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-message", + "markdownDescription": "Denies the message command without any pre-configured scope." + }, + { + "description": "Denies the open command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-open", + "markdownDescription": "Denies the open command without any pre-configured scope." + }, + { + "description": "Denies the save command without any pre-configured scope.", + "type": "string", + "const": "dialog:deny-save", + "markdownDescription": "Denies the save command without any pre-configured scope." + }, + { + "description": "No features are enabled by default, as we believe\nthe shortcuts can be inherently dangerous and it is\napplication specific if specific shortcuts should be\nregistered or unregistered.\n", + "type": "string", + "const": "global-shortcut:default", + "markdownDescription": "No features are enabled by default, as we believe\nthe shortcuts can be inherently dangerous and it is\napplication specific if specific shortcuts should be\nregistered or unregistered.\n" + }, + { + "description": "Enables the is_registered command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-is-registered", + "markdownDescription": "Enables the is_registered command without any pre-configured scope." + }, + { + "description": "Enables the register command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-register", + "markdownDescription": "Enables the register command without any pre-configured scope." + }, + { + "description": "Enables the register_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-register-all", + "markdownDescription": "Enables the register_all command without any pre-configured scope." + }, + { + "description": "Enables the unregister command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-unregister", + "markdownDescription": "Enables the unregister command without any pre-configured scope." + }, + { + "description": "Enables the unregister_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-unregister-all", + "markdownDescription": "Enables the unregister_all command without any pre-configured scope." + }, + { + "description": "Denies the is_registered command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-is-registered", + "markdownDescription": "Denies the is_registered command without any pre-configured scope." + }, + { + "description": "Denies the register command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-register", + "markdownDescription": "Denies the register command without any pre-configured scope." + }, + { + "description": "Denies the register_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-register-all", + "markdownDescription": "Denies the register_all command without any pre-configured scope." + }, + { + "description": "Denies the unregister command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-unregister", + "markdownDescription": "Denies the unregister command without any pre-configured scope." + }, + { + "description": "Denies the unregister_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-unregister-all", + "markdownDescription": "Denies the unregister_all command without any pre-configured scope." + }, + { + "description": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n\n#### This default permission set includes:\n\n- `allow-is-permission-granted`\n- `allow-request-permission`\n- `allow-notify`\n- `allow-register-action-types`\n- `allow-register-listener`\n- `allow-cancel`\n- `allow-get-pending`\n- `allow-remove-active`\n- `allow-get-active`\n- `allow-check-permissions`\n- `allow-show`\n- `allow-batch`\n- `allow-list-channels`\n- `allow-delete-channel`\n- `allow-create-channel`\n- `allow-permission-state`", + "type": "string", + "const": "notification:default", + "markdownDescription": "This permission set configures which\nnotification features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all notification related features.\n\n\n#### This default permission set includes:\n\n- `allow-is-permission-granted`\n- `allow-request-permission`\n- `allow-notify`\n- `allow-register-action-types`\n- `allow-register-listener`\n- `allow-cancel`\n- `allow-get-pending`\n- `allow-remove-active`\n- `allow-get-active`\n- `allow-check-permissions`\n- `allow-show`\n- `allow-batch`\n- `allow-list-channels`\n- `allow-delete-channel`\n- `allow-create-channel`\n- `allow-permission-state`" + }, + { + "description": "Enables the batch command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-batch", + "markdownDescription": "Enables the batch command without any pre-configured scope." + }, + { + "description": "Enables the cancel command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-cancel", + "markdownDescription": "Enables the cancel command without any pre-configured scope." + }, + { + "description": "Enables the check_permissions command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-check-permissions", + "markdownDescription": "Enables the check_permissions command without any pre-configured scope." + }, + { + "description": "Enables the create_channel command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-create-channel", + "markdownDescription": "Enables the create_channel command without any pre-configured scope." + }, + { + "description": "Enables the delete_channel command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-delete-channel", + "markdownDescription": "Enables the delete_channel command without any pre-configured scope." + }, + { + "description": "Enables the get_active command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-get-active", + "markdownDescription": "Enables the get_active command without any pre-configured scope." + }, + { + "description": "Enables the get_pending command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-get-pending", + "markdownDescription": "Enables the get_pending command without any pre-configured scope." + }, + { + "description": "Enables the is_permission_granted command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-is-permission-granted", + "markdownDescription": "Enables the is_permission_granted command without any pre-configured scope." + }, + { + "description": "Enables the list_channels command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-list-channels", + "markdownDescription": "Enables the list_channels command without any pre-configured scope." + }, + { + "description": "Enables the notify command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-notify", + "markdownDescription": "Enables the notify command without any pre-configured scope." + }, + { + "description": "Enables the permission_state command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-permission-state", + "markdownDescription": "Enables the permission_state command without any pre-configured scope." + }, + { + "description": "Enables the register_action_types command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-register-action-types", + "markdownDescription": "Enables the register_action_types command without any pre-configured scope." + }, + { + "description": "Enables the register_listener command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-register-listener", + "markdownDescription": "Enables the register_listener command without any pre-configured scope." + }, + { + "description": "Enables the remove_active command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-remove-active", + "markdownDescription": "Enables the remove_active command without any pre-configured scope." + }, + { + "description": "Enables the request_permission command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-request-permission", + "markdownDescription": "Enables the request_permission command without any pre-configured scope." + }, + { + "description": "Enables the show command without any pre-configured scope.", + "type": "string", + "const": "notification:allow-show", + "markdownDescription": "Enables the show command without any pre-configured scope." + }, + { + "description": "Denies the batch command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-batch", + "markdownDescription": "Denies the batch command without any pre-configured scope." + }, + { + "description": "Denies the cancel command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-cancel", + "markdownDescription": "Denies the cancel command without any pre-configured scope." + }, + { + "description": "Denies the check_permissions command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-check-permissions", + "markdownDescription": "Denies the check_permissions command without any pre-configured scope." + }, + { + "description": "Denies the create_channel command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-create-channel", + "markdownDescription": "Denies the create_channel command without any pre-configured scope." + }, + { + "description": "Denies the delete_channel command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-delete-channel", + "markdownDescription": "Denies the delete_channel command without any pre-configured scope." + }, + { + "description": "Denies the get_active command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-get-active", + "markdownDescription": "Denies the get_active command without any pre-configured scope." + }, + { + "description": "Denies the get_pending command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-get-pending", + "markdownDescription": "Denies the get_pending command without any pre-configured scope." + }, + { + "description": "Denies the is_permission_granted command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-is-permission-granted", + "markdownDescription": "Denies the is_permission_granted command without any pre-configured scope." + }, + { + "description": "Denies the list_channels command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-list-channels", + "markdownDescription": "Denies the list_channels command without any pre-configured scope." + }, + { + "description": "Denies the notify command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-notify", + "markdownDescription": "Denies the notify command without any pre-configured scope." + }, + { + "description": "Denies the permission_state command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-permission-state", + "markdownDescription": "Denies the permission_state command without any pre-configured scope." + }, + { + "description": "Denies the register_action_types command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-register-action-types", + "markdownDescription": "Denies the register_action_types command without any pre-configured scope." + }, + { + "description": "Denies the register_listener command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-register-listener", + "markdownDescription": "Denies the register_listener command without any pre-configured scope." + }, + { + "description": "Denies the remove_active command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-remove-active", + "markdownDescription": "Denies the remove_active command without any pre-configured scope." + }, + { + "description": "Denies the request_permission command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-request-permission", + "markdownDescription": "Denies the request_permission command without any pre-configured scope." + }, + { + "description": "Denies the show command without any pre-configured scope.", + "type": "string", + "const": "notification:deny-show", + "markdownDescription": "Denies the show command without any pre-configured scope." + }, + { + "description": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n\n#### This default permission set includes:\n\n- `allow-open`", + "type": "string", + "const": "shell:default", + "markdownDescription": "This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n\n#### This default permission set includes:\n\n- `allow-open`" + }, + { + "description": "Enables the execute command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-execute", + "markdownDescription": "Enables the execute command without any pre-configured scope." + }, + { + "description": "Enables the kill command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-kill", + "markdownDescription": "Enables the kill command without any pre-configured scope." + }, + { + "description": "Enables the open command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-open", + "markdownDescription": "Enables the open command without any pre-configured scope." + }, + { + "description": "Enables the spawn command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-spawn", + "markdownDescription": "Enables the spawn command without any pre-configured scope." + }, + { + "description": "Enables the stdin_write command without any pre-configured scope.", + "type": "string", + "const": "shell:allow-stdin-write", + "markdownDescription": "Enables the stdin_write command without any pre-configured scope." + }, + { + "description": "Denies the execute command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-execute", + "markdownDescription": "Denies the execute command without any pre-configured scope." + }, + { + "description": "Denies the kill command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-kill", + "markdownDescription": "Denies the kill command without any pre-configured scope." + }, + { + "description": "Denies the open command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-open", + "markdownDescription": "Denies the open command without any pre-configured scope." + }, + { + "description": "Denies the spawn command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-spawn", + "markdownDescription": "Denies the spawn command without any pre-configured scope." + }, + { + "description": "Denies the stdin_write command without any pre-configured scope.", + "type": "string", + "const": "shell:deny-stdin-write", + "markdownDescription": "Denies the stdin_write command without any pre-configured scope." + }, + { + "description": "This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n\n#### This default permission set includes:\n\n- `allow-check`\n- `allow-download`\n- `allow-install`\n- `allow-download-and-install`", + "type": "string", + "const": "updater:default", + "markdownDescription": "This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n\n#### This default permission set includes:\n\n- `allow-check`\n- `allow-download`\n- `allow-install`\n- `allow-download-and-install`" + }, + { + "description": "Enables the check command without any pre-configured scope.", + "type": "string", + "const": "updater:allow-check", + "markdownDescription": "Enables the check command without any pre-configured scope." + }, + { + "description": "Enables the download command without any pre-configured scope.", + "type": "string", + "const": "updater:allow-download", + "markdownDescription": "Enables the download command without any pre-configured scope." + }, + { + "description": "Enables the download_and_install command without any pre-configured scope.", + "type": "string", + "const": "updater:allow-download-and-install", + "markdownDescription": "Enables the download_and_install command without any pre-configured scope." + }, + { + "description": "Enables the install command without any pre-configured scope.", + "type": "string", + "const": "updater:allow-install", + "markdownDescription": "Enables the install command without any pre-configured scope." + }, + { + "description": "Denies the check command without any pre-configured scope.", + "type": "string", + "const": "updater:deny-check", + "markdownDescription": "Denies the check command without any pre-configured scope." + }, + { + "description": "Denies the download command without any pre-configured scope.", + "type": "string", + "const": "updater:deny-download", + "markdownDescription": "Denies the download command without any pre-configured scope." + }, + { + "description": "Denies the download_and_install command without any pre-configured scope.", + "type": "string", + "const": "updater:deny-download-and-install", + "markdownDescription": "Denies the download_and_install command without any pre-configured scope." + }, + { + "description": "Denies the install command without any pre-configured scope.", + "type": "string", + "const": "updater:deny-install", + "markdownDescription": "Denies the install command without any pre-configured scope." + } + ] + }, + "Value": { + "description": "All supported ACL values.", + "anyOf": [ + { + "description": "Represents a null JSON value.", + "type": "null" + }, + { + "description": "Represents a [`bool`].", + "type": "boolean" + }, + { + "description": "Represents a valid ACL [`Number`].", + "allOf": [ + { + "$ref": "#/definitions/Number" + } + ] + }, + { + "description": "Represents a [`String`].", + "type": "string" + }, + { + "description": "Represents a list of other [`Value`]s.", + "type": "array", + "items": { + "$ref": "#/definitions/Value" + } + }, + { + "description": "Represents a map of [`String`] keys to [`Value`]s.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + ] + }, + "Number": { + "description": "A valid ACL number.", + "anyOf": [ + { + "description": "Represents an [`i64`].", + "type": "integer", + "format": "int64" + }, + { + "description": "Represents a [`f64`].", + "type": "number", + "format": "double" + } + ] + }, + "Target": { + "description": "Platform target.", + "oneOf": [ + { + "description": "MacOS.", + "type": "string", + "enum": [ + "macOS" + ] + }, + { + "description": "Windows.", + "type": "string", + "enum": [ + "windows" + ] + }, + { + "description": "Linux.", + "type": "string", + "enum": [ + "linux" + ] + }, + { + "description": "Android.", + "type": "string", + "enum": [ + "android" + ] + }, + { + "description": "iOS.", + "type": "string", + "enum": [ + "iOS" + ] + } + ] + }, + "ShellScopeEntryAllowedArg": { + "description": "A command argument allowed to be executed by the webview API.", + "anyOf": [ + { + "description": "A non-configurable argument that is passed to the command in the order it was specified.", + "type": "string" + }, + { + "description": "A variable that is set while calling the command from the webview API.", + "type": "object", + "required": [ + "validator" + ], + "properties": { + "raw": { + "description": "Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.", + "default": false, + "type": "boolean" + }, + "validator": { + "description": "[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ", + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "ShellScopeEntryAllowedArgs": { + "description": "A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration.", + "anyOf": [ + { + "description": "Use a simple boolean to allow all or disable all arguments to this command configuration.", + "type": "boolean" + }, + { + "description": "A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.", + "type": "array", + "items": { + "$ref": "#/definitions/ShellScopeEntryAllowedArg" + } + } + ] + } + } +} \ No newline at end of file diff --git a/crates/openfang-extensions/src/oauth.rs b/crates/openfang-extensions/src/oauth.rs index 811484dfe..beabe01b9 100644 --- a/crates/openfang-extensions/src/oauth.rs +++ b/crates/openfang-extensions/src/oauth.rs @@ -27,9 +27,7 @@ pub fn default_client_ids() -> HashMap<&'static str, &'static str> { } /// Resolve OAuth client IDs with config overrides applied on top of defaults. -pub fn resolve_client_ids( - config: &openfang_types::config::OAuthConfig, -) -> HashMap { +pub fn resolve_client_ids(config: &openfang_types::config::OAuthConfig) -> HashMap { let defaults = default_client_ids(); let mut resolved: HashMap = defaults .into_iter() diff --git a/crates/openfang-hands/src/registry.rs b/crates/openfang-hands/src/registry.rs index 22ad9452a..b58221eb0 100644 --- a/crates/openfang-hands/src/registry.rs +++ b/crates/openfang-hands/src/registry.rs @@ -117,7 +117,8 @@ impl HandRegistry { /// List all known hand definitions. pub fn list_definitions(&self) -> Vec { - let mut defs: Vec = self.definitions.iter().map(|r| r.value().clone()).collect(); + let mut defs: Vec = + self.definitions.iter().map(|r| r.value().clone()).collect(); defs.sort_by(|a, b| a.name.cmp(&b.name)); defs } diff --git a/crates/openfang-kernel/src/config_reload.rs b/crates/openfang-kernel/src/config_reload.rs index b194db454..df9d5b7a7 100644 --- a/crates/openfang-kernel/src/config_reload.rs +++ b/crates/openfang-kernel/src/config_reload.rs @@ -411,7 +411,10 @@ mod tests { let mut b = default_cfg(); b.default_model.model = "gpt-4".to_string(); let plan = build_reload_plan(&a, &b); - assert!(!plan.restart_required, "default_model should be hot-reloadable"); + assert!( + !plan.restart_required, + "default_model should be hot-reloadable" + ); assert!(plan.hot_actions.contains(&HotAction::UpdateDefaultModel)); } diff --git a/crates/openfang-kernel/src/cron.rs b/crates/openfang-kernel/src/cron.rs index d304190a8..e20494a94 100644 --- a/crates/openfang-kernel/src/cron.rs +++ b/crates/openfang-kernel/src/cron.rs @@ -287,8 +287,7 @@ impl CronScheduler { ); meta.job.enabled = false; } else { - meta.job.next_run = - Some(compute_next_run_after(&meta.job.schedule, Utc::now())); + meta.job.next_run = Some(compute_next_run_after(&meta.job.schedule, Utc::now())); } } } diff --git a/crates/openfang-kernel/src/kernel.rs b/crates/openfang-kernel/src/kernel.rs index 7e17cf2d9..cbd824c41 100644 --- a/crates/openfang-kernel/src/kernel.rs +++ b/crates/openfang-kernel/src/kernel.rs @@ -148,9 +148,11 @@ pub struct OpenFangKernel { /// WhatsApp Web gateway child process PID (for shutdown cleanup). pub whatsapp_gateway_pid: Arc>>, /// Channel adapters registered at bridge startup (for proactive `channel_send` tool). - pub channel_adapters: dashmap::DashMap>, + pub channel_adapters: + dashmap::DashMap>, /// Hot-reloadable default model override (set via config hot-reload, read at agent spawn). - pub default_model_override: std::sync::RwLock>, + pub default_model_override: + std::sync::RwLock>, /// Weak self-reference for trigger dispatch (set after Arc wrapping). self_handle: OnceLock>, } @@ -550,11 +552,12 @@ impl OpenFangKernel { let driver_config = DriverConfig { provider: config.default_model.provider.clone(), api_key: std::env::var(&config.default_model.api_key_env).ok(), - base_url: config - .default_model - .base_url - .clone() - .or_else(|| config.provider_urls.get(&config.default_model.provider).cloned()), + base_url: config.default_model.base_url.clone().or_else(|| { + config + .provider_urls + .get(&config.default_model.provider) + .cloned() + }), }; // Primary driver failure is non-fatal: the dashboard should remain accessible // even if the LLM provider is misconfigured. Users can fix config via dashboard. @@ -964,11 +967,16 @@ impl OpenFangKernel { Ok(disk_manifest) => { // Compare key fields to detect changes let changed = disk_manifest.name != entry.manifest.name - || disk_manifest.description != entry.manifest.description - || disk_manifest.model.system_prompt != entry.manifest.model.system_prompt - || disk_manifest.model.provider != entry.manifest.model.provider - || disk_manifest.model.model != entry.manifest.model.model - || disk_manifest.capabilities.tools != entry.manifest.capabilities.tools; + || disk_manifest.description + != entry.manifest.description + || disk_manifest.model.system_prompt + != entry.manifest.model.system_prompt + || disk_manifest.model.provider + != entry.manifest.model.provider + || disk_manifest.model.model + != entry.manifest.model.model + || disk_manifest.capabilities.tools + != entry.manifest.capabilities.tools; if changed { info!( agent = %name, @@ -1048,11 +1056,20 @@ impl OpenFangKernel { if !dm.model.is_empty() { restored_entry.manifest.model.model = dm.model.clone(); } - if !dm.api_key_env.is_empty() { - restored_entry.manifest.model.api_key_env = Some(dm.api_key_env.clone()); + if !dm.api_key_env.is_empty() + && restored_entry.manifest.model.api_key_env.is_none() + { + restored_entry.manifest.model.api_key_env = + Some(dm.api_key_env.clone()); } - if dm.base_url.is_some() { - restored_entry.manifest.model.base_url.clone_from(&dm.base_url); + if dm.base_url.is_some() + && restored_entry.manifest.model.base_url.is_none() + { + restored_entry + .manifest + .model + .base_url + .clone_from(&dm.base_url); } } } @@ -1191,9 +1208,10 @@ impl OpenFangKernel { apply_budget_defaults(&self.config.budget, &mut manifest.resources); // Create workspace directory for the agent (name-based, so SOUL.md survives recreation) - let workspace_dir = manifest.workspace.clone().unwrap_or_else(|| { - self.config.effective_workspaces_dir().join(&name) - }); + let workspace_dir = manifest + .workspace + .clone() + .unwrap_or_else(|| self.config.effective_workspaces_dir().join(&name)); ensure_workspace(&workspace_dir)?; if manifest.generate_identity_files { generate_identity_files(&workspace_dir, &manifest); @@ -1616,7 +1634,11 @@ impl OpenFangKernel { None }, peer_agents, - current_date: Some(chrono::Local::now().format("%A, %B %d, %Y (%Y-%m-%d %H:%M %Z)").to_string()), + current_date: Some( + chrono::Local::now() + .format("%A, %B %d, %Y (%Y-%m-%d %H:%M %Z)") + .to_string(), + ), }; manifest.model.system_prompt = openfang_runtime::prompt_builder::build_system_prompt(&prompt_ctx); @@ -2085,7 +2107,11 @@ impl OpenFangKernel { None }, peer_agents, - current_date: Some(chrono::Local::now().format("%A, %B %d, %Y (%Y-%m-%d %H:%M %Z)").to_string()), + current_date: Some( + chrono::Local::now() + .format("%A, %B %d, %Y (%Y-%m-%d %H:%M %Z)") + .to_string(), + ), }; manifest.model.system_prompt = openfang_runtime::prompt_builder::build_system_prompt(&prompt_ctx); @@ -2509,15 +2535,11 @@ impl OpenFangKernel { /// Switch an agent's model. pub fn set_agent_model(&self, agent_id: AgentId, model: &str) -> KernelResult<()> { // Resolve provider from model catalog so switching models also switches provider - let resolved_provider = self - .model_catalog - .read() - .ok() - .and_then(|catalog| { - catalog - .find_model(model) - .map(|entry| entry.provider.clone()) - }); + let resolved_provider = self.model_catalog.read().ok().and_then(|catalog| { + catalog + .find_model(model) + .map(|entry| entry.provider.clone()) + }); // If catalog lookup failed, try to infer provider from model name prefix let provider = resolved_provider.or_else(|| infer_provider_from_model(model)); @@ -2978,7 +3000,11 @@ impl OpenFangKernel { } // If an agent with this hand's name already exists, remove it first - let existing = self.registry.list().into_iter().find(|e| e.name == def.agent.name); + let existing = self + .registry + .list() + .into_iter() + .find(|e| e.name == def.agent.name); if let Some(old) = existing { info!(agent = %old.name, id = %old.id, "Removing existing hand agent for reactivation"); let _ = self.kill_agent(old.id); @@ -3310,14 +3336,17 @@ impl OpenFangKernel { /// `Continuous`, `Periodic`, or `Proactive` schedules. pub fn start_background_agents(self: &Arc) { let agents = self.registry.list(); - let mut bg_agents: Vec<(openfang_types::agent::AgentId, String, ScheduleMode)> = - Vec::new(); + let mut bg_agents: Vec<(openfang_types::agent::AgentId, String, ScheduleMode)> = Vec::new(); for entry in &agents { if matches!(entry.manifest.schedule, ScheduleMode::Reactive) { continue; } - bg_agents.push((entry.id, entry.name.clone(), entry.manifest.schedule.clone())); + bg_agents.push(( + entry.id, + entry.name.clone(), + entry.manifest.schedule.clone(), + )); } if !bg_agents.is_empty() { @@ -3524,7 +3553,9 @@ impl OpenFangKernel { let timeout_s = timeout_secs.unwrap_or(120); let timeout = std::time::Duration::from_secs(timeout_s); let delivery = job.delivery.clone(); - let kh: std::sync::Arc = kernel.clone(); + let kh: std::sync::Arc< + dyn openfang_runtime::kernel_handle::KernelHandle, + > = kernel.clone(); match tokio::time::timeout( timeout, kernel.send_message_with_handle(agent_id, message, Some(kh)), @@ -3895,14 +3926,18 @@ impl OpenFangKernel { let base_url = if has_custom_url { manifest.model.base_url.clone() } else if agent_provider == default_provider { - self.config - .default_model - .base_url - .clone() - .or_else(|| self.config.provider_urls.get(agent_provider.as_str()).cloned()) + self.config.default_model.base_url.clone().or_else(|| { + self.config + .provider_urls + .get(agent_provider.as_str()) + .cloned() + }) } else { // Check provider_urls before falling back to hardcoded defaults - self.config.provider_urls.get(agent_provider.as_str()).cloned() + self.config + .provider_urls + .get(agent_provider.as_str()) + .cloned() }; let driver_config = DriverConfig { @@ -3919,8 +3954,10 @@ impl OpenFangKernel { // If fallback models are configured, wrap in FallbackDriver if !manifest.fallback_models.is_empty() { // Primary driver uses the agent's own model name (already set in request) - let mut chain: Vec<(std::sync::Arc, String)> = - vec![(primary.clone(), String::new())]; + let mut chain: Vec<( + std::sync::Arc, + String, + )> = vec![(primary.clone(), String::new())]; for fb in &manifest.fallback_models { let config = DriverConfig { provider: fb.provider.clone(), @@ -4345,7 +4382,12 @@ impl OpenFangKernel { // Apply per-agent tool allowlist/blocklist (manifest-level filtering) let (tool_allowlist, tool_blocklist) = entry .as_ref() - .map(|e| (e.manifest.tool_allowlist.clone(), e.manifest.tool_blocklist.clone())) + .map(|e| { + ( + e.manifest.tool_allowlist.clone(), + e.manifest.tool_blocklist.clone(), + ) + }) .unwrap_or_default(); if !tool_allowlist.is_empty() { @@ -4504,7 +4546,8 @@ impl OpenFangKernel { tool_names.join(", ") )); } - summary.push_str("MCP tools are prefixed with mcp_{server}_ and work like regular tools.\n"); + summary + .push_str("MCP tools are prefixed with mcp_{server}_ and work like regular tools.\n"); // Add filesystem-specific guidance when a filesystem MCP server is connected let has_filesystem = servers.keys().any(|s| s.contains("filesystem")); if has_filesystem { @@ -4683,8 +4726,8 @@ fn infer_provider_from_model(model: &str) -> Option { "minimax" | "gemini" | "anthropic" | "openai" | "groq" | "deepseek" | "mistral" | "cohere" | "xai" | "ollama" | "together" | "fireworks" | "perplexity" | "cerebras" | "sambanova" | "replicate" | "huggingface" | "ai21" | "codex" - | "claude-code" | "copilot" | "github-copilot" | "qwen" | "zhipu" | "zai" | "moonshot" - | "openrouter" | "volcengine" | "doubao" | "dashscope" => { + | "claude-code" | "copilot" | "github-copilot" | "qwen" | "zhipu" | "zai" + | "moonshot" | "openrouter" | "volcengine" | "doubao" | "dashscope" => { return Some(prefix.to_string()); } _ => {} @@ -4697,16 +4740,26 @@ fn infer_provider_from_model(model: &str) -> Option { Some("gemini".to_string()) } else if lower.starts_with("claude") { Some("anthropic".to_string()) - } else if lower.starts_with("gpt") || lower.starts_with("o1") || lower.starts_with("o3") || lower.starts_with("o4") { + } else if lower.starts_with("gpt") + || lower.starts_with("o1") + || lower.starts_with("o3") + || lower.starts_with("o4") + { Some("openai".to_string()) - } else if lower.starts_with("llama") || lower.starts_with("mixtral") || lower.starts_with("qwen") { + } else if lower.starts_with("llama") + || lower.starts_with("mixtral") + || lower.starts_with("qwen") + { // These could be on multiple providers; don't infer None } else if lower.starts_with("grok") { Some("xai".to_string()) } else if lower.starts_with("deepseek") { Some("deepseek".to_string()) - } else if lower.starts_with("mistral") || lower.starts_with("codestral") || lower.starts_with("pixtral") { + } else if lower.starts_with("mistral") + || lower.starts_with("codestral") + || lower.starts_with("pixtral") + { Some("mistral".to_string()) } else if lower.starts_with("command") || lower.starts_with("embed-") { Some("cohere".to_string()) @@ -5274,7 +5327,10 @@ impl KernelHandle for OpenFangKernel { }; adapter - .send(&user, openfang_channels::types::ChannelContent::Text(message.to_string())) + .send( + &user, + openfang_channels::types::ChannelContent::Text(message.to_string()), + ) .await .map_err(|e| format!("Channel send failed: {e}"))?; @@ -5322,7 +5378,9 @@ impl KernelHandle for OpenFangKernel { filename: filename.unwrap_or("file").to_string(), }, _ => { - return Err(format!("Unsupported media type: '{media_type}'. Use 'image' or 'file'.")); + return Err(format!( + "Unsupported media type: '{media_type}'. Use 'image' or 'file'." + )); } }; @@ -5331,7 +5389,10 @@ impl KernelHandle for OpenFangKernel { .await .map_err(|e| format!("Channel media send failed: {e}"))?; - Ok(format!("{} sent to {} via {}", media_type, recipient, channel)) + Ok(format!( + "{} sent to {} via {}", + media_type, recipient, channel + )) } async fn spawn_agent_checked( diff --git a/crates/openfang-kernel/src/metering.rs b/crates/openfang-kernel/src/metering.rs index 58dc42397..6ede6d8f4 100644 --- a/crates/openfang-kernel/src/metering.rs +++ b/crates/openfang-kernel/src/metering.rs @@ -343,6 +343,11 @@ fn estimate_cost_rates(model: &str) -> (f64, f64) { return (0.40, 0.40); } + // ── Venice.ai ── must come before llama/qwen ────────────── + if model.contains("venice") { + return (0.20, 0.90); + } + // ── Open-source (Groq, Together, etc.) ───────────────────── if model.contains("llama-4-maverick") { return (0.50, 0.77); diff --git a/crates/openfang-kernel/src/scheduler.rs b/crates/openfang-kernel/src/scheduler.rs index 31c2b0731..94c91a943 100644 --- a/crates/openfang-kernel/src/scheduler.rs +++ b/crates/openfang-kernel/src/scheduler.rs @@ -88,8 +88,7 @@ impl AgentScheduler { // Reset the window if an hour has passed tracker.reset_if_expired(); - if quota.max_llm_tokens_per_hour > 0 - && tracker.total_tokens > quota.max_llm_tokens_per_hour + if quota.max_llm_tokens_per_hour > 0 && tracker.total_tokens > quota.max_llm_tokens_per_hour { return Err(OpenFangError::QuotaExceeded(format!( "Token limit exceeded: {} / {}", diff --git a/crates/openfang-kernel/src/whatsapp_gateway.rs b/crates/openfang-kernel/src/whatsapp_gateway.rs index a4214a744..17b3aa017 100644 --- a/crates/openfang-kernel/src/whatsapp_gateway.rs +++ b/crates/openfang-kernel/src/whatsapp_gateway.rs @@ -10,10 +10,8 @@ use std::sync::Arc; use tracing::{info, warn}; /// Gateway source files embedded at compile time. -const GATEWAY_INDEX_JS: &str = - include_str!("../../../packages/whatsapp-gateway/index.js"); -const GATEWAY_PACKAGE_JSON: &str = - include_str!("../../../packages/whatsapp-gateway/package.json"); +const GATEWAY_INDEX_JS: &str = include_str!("../../../packages/whatsapp-gateway/index.js"); +const GATEWAY_PACKAGE_JSON: &str = include_str!("../../../packages/whatsapp-gateway/package.json"); /// Default port for the WhatsApp Web gateway. const DEFAULT_GATEWAY_PORT: u16 = 3009; @@ -69,8 +67,8 @@ async fn ensure_gateway_installed() -> Result { let package_path = dir.join("package.json"); // Write files only if content changed (avoids unnecessary npm install) - let index_changed = - write_if_changed(&index_path, GATEWAY_INDEX_JS).map_err(|e| format!("Write index.js: {e}"))?; + let index_changed = write_if_changed(&index_path, GATEWAY_INDEX_JS) + .map_err(|e| format!("Write index.js: {e}"))?; let package_changed = write_if_changed(&package_path, GATEWAY_PACKAGE_JSON) .map_err(|e| format!("Write package.json: {e}"))?; @@ -164,7 +162,10 @@ pub async fn start_whatsapp_gateway(kernel: &Arc) .to_string(); // Auto-set the env var so the rest of the system finds the gateway - std::env::set_var("WHATSAPP_WEB_GATEWAY_URL", format!("http://127.0.0.1:{port}")); + std::env::set_var( + "WHATSAPP_WEB_GATEWAY_URL", + format!("http://127.0.0.1:{port}"), + ); info!("WHATSAPP_WEB_GATEWAY_URL set to http://127.0.0.1:{port}"); // Spawn with crash monitoring @@ -247,9 +248,7 @@ pub async fn start_whatsapp_gateway(kernel: &Arc) restarts += 1; if restarts >= MAX_RESTARTS { - warn!( - "WhatsApp gateway exceeded max restarts ({MAX_RESTARTS}), giving up" - ); + warn!("WhatsApp gateway exceeded max restarts ({MAX_RESTARTS}), giving up"); return; } diff --git a/crates/openfang-memory/src/structured.rs b/crates/openfang-memory/src/structured.rs index d71b6bc9b..fb7b45f5e 100644 --- a/crates/openfang-memory/src/structured.rs +++ b/crates/openfang-memory/src/structured.rs @@ -99,13 +99,12 @@ impl StructuredStore { let mut pairs = Vec::new(); for row in rows { let (key, blob) = row.map_err(|e| OpenFangError::Memory(e.to_string()))?; - let value: serde_json::Value = serde_json::from_slice(&blob) - .unwrap_or_else(|_| { - // Fallback: try as UTF-8 string - String::from_utf8(blob) - .map(serde_json::Value::String) - .unwrap_or(serde_json::Value::Null) - }); + let value: serde_json::Value = serde_json::from_slice(&blob).unwrap_or_else(|_| { + // Fallback: try as UTF-8 string + String::from_utf8(blob) + .map(serde_json::Value::String) + .unwrap_or(serde_json::Value::Null) + }); pairs.push((key, value)); } Ok(pairs) @@ -192,7 +191,14 @@ impl StructuredStore { } else { None }; - Ok((name, manifest_blob, state_str, created_str, session_id_str, identity_str)) + Ok(( + name, + manifest_blob, + state_str, + created_str, + session_id_str, + identity_str, + )) }); match result { @@ -307,13 +313,14 @@ impl StructuredStore { let mut repair_queue: Vec<(String, Vec, String)> = Vec::new(); for row in rows { - let (id_str, name, manifest_blob, state_str, created_str, session_id_str, identity_str) = match row { - Ok(r) => r, - Err(e) => { - tracing::warn!("Skipping agent row with read error: {e}"); - continue; - } - }; + let (id_str, name, manifest_blob, state_str, created_str, session_id_str, identity_str) = + match row { + Ok(r) => r, + Err(e) => { + tracing::warn!("Skipping agent row with read error: {e}"); + continue; + } + }; // Deduplicate: skip agents with names we've already seen let name_lower = name.to_lowercase(); diff --git a/crates/openfang-runtime/src/agent_loop.rs b/crates/openfang-runtime/src/agent_loop.rs index 11fa8ea12..4ea3f6004 100644 --- a/crates/openfang-runtime/src/agent_loop.rs +++ b/crates/openfang-runtime/src/agent_loop.rs @@ -691,10 +691,13 @@ pub async fn run_agent_loop( } // Detect approval denials and inject guidance to prevent infinite retry loops - let denial_count = tool_result_blocks.iter().filter(|b| { - matches!(b, ContentBlock::ToolResult { content, is_error: true, .. } + let denial_count = tool_result_blocks + .iter() + .filter(|b| { + matches!(b, ContentBlock::ToolResult { content, is_error: true, .. } if content.contains("requires human approval and was denied")) - }).count(); + }) + .count(); if denial_count > 0 { tool_result_blocks.push(ContentBlock::Text { text: format!( @@ -1614,10 +1617,13 @@ pub async fn run_agent_loop_streaming( } // Detect approval denials and inject guidance to prevent infinite retry loops - let denial_count = tool_result_blocks.iter().filter(|b| { - matches!(b, ContentBlock::ToolResult { content, is_error: true, .. } + let denial_count = tool_result_blocks + .iter() + .filter(|b| { + matches!(b, ContentBlock::ToolResult { content, is_error: true, .. } if content.contains("requires human approval and was denied")) - }).count(); + }) + .count(); if denial_count > 0 { tool_result_blocks.push(ContentBlock::Text { text: format!( @@ -2897,7 +2903,8 @@ mod tests { input_schema: serde_json::json!({}), }]; // Same call in both function tag and tool tag — should only appear once - let text = r#"{"command":"ls"} exec{"command":"ls"}"#; + let text = + r#"{"command":"ls"} exec{"command":"ls"}"#; let calls = recover_text_tool_calls(text, &tools); assert_eq!(calls.len(), 1); } diff --git a/crates/openfang-runtime/src/browser.rs b/crates/openfang-runtime/src/browser.rs index 4bb0f2e79..cf800e8fb 100644 --- a/crates/openfang-runtime/src/browser.rs +++ b/crates/openfang-runtime/src/browser.rs @@ -141,13 +141,13 @@ impl CdpConnection { if let Some(id) = json.get("id").and_then(|v| v.as_u64()) { if let Some((_, sender)) = pending.remove(&id) { if let Some(error) = json.get("error") { - let msg = error["message"] - .as_str() - .unwrap_or("CDP error") - .to_string(); + let msg = error["message"].as_str().unwrap_or("CDP error").to_string(); let _ = sender.send(Err(msg)); } else { - let result = json.get("result").cloned().unwrap_or(serde_json::Value::Null); + let result = json + .get("result") + .cloned() + .unwrap_or(serde_json::Value::Null); let _ = sender.send(Ok(result)); } } @@ -287,9 +287,12 @@ impl BrowserSession { } } - let mut child = cmd - .spawn() - .map_err(|e| format!("Failed to launch Chromium at {}: {e}", chrome_path.display()))?; + let mut child = cmd.spawn().map_err(|e| { + format!( + "Failed to launch Chromium at {}: {e}", + chrome_path.display() + ) + })?; // Parse stderr for the DevTools WebSocket URL let stderr = child.stderr.take().ok_or("No stderr from Chromium")?; @@ -453,7 +456,10 @@ impl BrowserSession { .unwrap_or(val); if parsed["success"].as_bool() == Some(false) { return BrowserResponse::err( - parsed["error"].as_str().unwrap_or("Click failed").to_string(), + parsed["error"] + .as_str() + .unwrap_or("Click failed") + .to_string(), ); } // Wait briefly for any navigation triggered by click @@ -632,7 +638,11 @@ impl BrowserSession { .and_then(|s| serde_json::from_str(s).ok()) .unwrap_or(info); - let content_val = self.cdp.run_js(EXTRACT_CONTENT_JS).await.unwrap_or_default(); + let content_val = self + .cdp + .run_js(EXTRACT_CONTENT_JS) + .await + .unwrap_or_default(); let content_obj: serde_json::Value = content_val .as_str() .and_then(|s| serde_json::from_str(s).ok()) @@ -987,9 +997,7 @@ pub async fn tool_browser_read_page( mgr: &BrowserManager, agent_id: &str, ) -> Result { - let resp = mgr - .send_command(agent_id, BrowserCommand::ReadPage) - .await?; + let resp = mgr.send_command(agent_id, BrowserCommand::ReadPage).await?; if !resp.success { return Err(resp.error.unwrap_or_else(|| "ReadPage failed".to_string())); } @@ -1293,7 +1301,10 @@ mod tests { #[test] fn test_chromium_candidates_not_empty() { let paths = chromium_candidates(); - assert!(!paths.is_empty(), "Should have platform-specific candidates"); + assert!( + !paths.is_empty(), + "Should have platform-specific candidates" + ); } #[test] diff --git a/crates/openfang-runtime/src/compactor.rs b/crates/openfang-runtime/src/compactor.rs index 6fd7056e3..f62d9fea4 100644 --- a/crates/openfang-runtime/src/compactor.rs +++ b/crates/openfang-runtime/src/compactor.rs @@ -343,7 +343,11 @@ fn build_conversation_text(messages: &[Message], config: &CompactionConfig) -> S if oversized { let limit = config.max_chunk_chars / 4; let truncated = if s.len() > limit { - format!("{}...[truncated from {} chars]", safe_truncate_str(s, limit), s.len()) + format!( + "{}...[truncated from {} chars]", + safe_truncate_str(s, limit), + s.len() + ) } else { s.clone() }; @@ -431,7 +435,11 @@ async fn summarize_messages( let safe_start = if conversation_text.is_char_boundary(start) { start } else { - conversation_text[start..].char_indices().next().map(|(i, _)| start + i).unwrap_or(conversation_text.len()) + conversation_text[start..] + .char_indices() + .next() + .map(|(i, _)| start + i) + .unwrap_or(conversation_text.len()) }; conversation_text = conversation_text[safe_start..].to_string(); } diff --git a/crates/openfang-runtime/src/context_budget.rs b/crates/openfang-runtime/src/context_budget.rs index cbf844905..a0ea0bb4e 100644 --- a/crates/openfang-runtime/src/context_budget.rs +++ b/crates/openfang-runtime/src/context_budget.rs @@ -68,7 +68,11 @@ pub fn truncate_tool_result_dynamic(content: &str, budget: &ContextBudget) -> St let safe_cap = if content.is_char_boundary(cap) { cap } else { - content[..cap].char_indices().next_back().map(|(i, _)| i).unwrap_or(0) + content[..cap] + .char_indices() + .next_back() + .map(|(i, _)| i) + .unwrap_or(0) }; let search_start = safe_cap.saturating_sub(200); let break_point = content[search_start..safe_cap] @@ -79,7 +83,11 @@ pub fn truncate_tool_result_dynamic(content: &str, budget: &ContextBudget) -> St let break_point = if content.is_char_boundary(break_point) { break_point } else { - content[..break_point].char_indices().next_back().map(|(i, _)| i).unwrap_or(0) + content[..break_point] + .char_indices() + .next_back() + .map(|(i, _)| i) + .unwrap_or(0) }; format!( diff --git a/crates/openfang-runtime/src/context_overflow.rs b/crates/openfang-runtime/src/context_overflow.rs index 69ce02f77..b4744e441 100644 --- a/crates/openfang-runtime/src/context_overflow.rs +++ b/crates/openfang-runtime/src/context_overflow.rs @@ -107,7 +107,11 @@ pub fn recover_from_overflow( let safe_keep = if content.is_char_boundary(keep) { keep } else { - content[..keep].char_indices().next_back().map(|(i, _)| i).unwrap_or(0) + content[..keep] + .char_indices() + .next_back() + .map(|(i, _)| i) + .unwrap_or(0) }; *content = format!( "{}\n\n[OVERFLOW RECOVERY: truncated from {} to {} chars]", diff --git a/crates/openfang-runtime/src/copilot_oauth.rs b/crates/openfang-runtime/src/copilot_oauth.rs index b63d69a21..0fe33360a 100644 --- a/crates/openfang-runtime/src/copilot_oauth.rs +++ b/crates/openfang-runtime/src/copilot_oauth.rs @@ -89,10 +89,7 @@ pub async fn poll_device_flow(device_code: &str) -> DeviceFlowStatus { .header("Accept", "application/json") .form(&[ ("client_id", COPILOT_CLIENT_ID), - ( - "grant_type", - "urn:ietf:params:oauth:grant-type:device_code", - ), + ("grant_type", "urn:ietf:params:oauth:grant-type:device_code"), ("device_code", device_code), ]) .send() @@ -112,10 +109,7 @@ pub async fn poll_device_flow(device_code: &str) -> DeviceFlowStatus { return match error { "authorization_pending" => DeviceFlowStatus::Pending, "slow_down" => { - let interval = body - .get("interval") - .and_then(|v| v.as_u64()) - .unwrap_or(10); + let interval = body.get("interval").and_then(|v| v.as_u64()).unwrap_or(10); DeviceFlowStatus::SlowDown { new_interval: interval, } diff --git a/crates/openfang-runtime/src/drivers/claude_code.rs b/crates/openfang-runtime/src/drivers/claude_code.rs index 7361c67a5..0b39b573d 100644 --- a/crates/openfang-runtime/src/drivers/claude_code.rs +++ b/crates/openfang-runtime/src/drivers/claude_code.rs @@ -70,9 +70,7 @@ impl ClaudeCodeDriver { /// Map a model ID like "claude-code/opus" to CLI --model flag value. fn model_flag(model: &str) -> Option { - let stripped = model - .strip_prefix("claude-code/") - .unwrap_or(model); + let stripped = model.strip_prefix("claude-code/").unwrap_or(model); match stripped { "opus" => Some("opus".to_string()), "sonnet" => Some("sonnet".to_string()), @@ -124,10 +122,7 @@ struct ClaudeStreamEvent { #[async_trait] impl LlmDriver for ClaudeCodeDriver { - async fn complete( - &self, - request: CompletionRequest, - ) -> Result { + async fn complete(&self, request: CompletionRequest) -> Result { let prompt = Self::build_prompt(&request); let model_flag = Self::model_flag(&request.model); @@ -165,7 +160,8 @@ impl LlmDriver for ClaudeCodeDriver { // Try JSON parse first if let Ok(parsed) = serde_json::from_str::(&stdout) { - let text = parsed.result + let text = parsed + .result .or(parsed.content) .or(parsed.text) .unwrap_or_default(); @@ -290,9 +286,7 @@ impl LlmDriver for ClaudeCodeDriver { // Not valid JSON — treat as raw text warn!(line = %line, error = %e, "Non-JSON line from Claude CLI"); full_text.push_str(&line); - let _ = tx - .send(StreamEvent::TextDelta { text: line }) - .await; + let _ = tx.send(StreamEvent::TextDelta { text: line }).await; } } } @@ -325,8 +319,7 @@ impl LlmDriver for ClaudeCodeDriver { /// Check if the Claude Code CLI is available. pub fn claude_code_available() -> bool { - ClaudeCodeDriver::detect().is_some() - || claude_credentials_exist() + ClaudeCodeDriver::detect().is_some() || claude_credentials_exist() } /// Check if Claude credentials file exists (~/.claude/.credentials.json). @@ -342,7 +335,9 @@ fn claude_credentials_exist() -> bool { fn home_dir() -> Option { #[cfg(target_os = "windows")] { - std::env::var("USERPROFILE").ok().map(std::path::PathBuf::from) + std::env::var("USERPROFILE") + .ok() + .map(std::path::PathBuf::from) } #[cfg(not(target_os = "windows"))] { diff --git a/crates/openfang-runtime/src/drivers/copilot.rs b/crates/openfang-runtime/src/drivers/copilot.rs index 3170163a8..44cb3e22d 100644 --- a/crates/openfang-runtime/src/drivers/copilot.rs +++ b/crates/openfang-runtime/src/drivers/copilot.rs @@ -204,12 +204,19 @@ impl CopilotDriver { } else { token.base_url.clone() }; - super::openai::OpenAIDriver::new(token.token.to_string(), base_url) - .with_extra_headers(vec![ + super::openai::OpenAIDriver::new(token.token.to_string(), base_url).with_extra_headers( + vec![ ("Editor-Version".to_string(), "vscode/1.96.0".to_string()), - ("Editor-Plugin-Version".to_string(), "copilot/1.250.0".to_string()), - ("Copilot-Integration-Id".to_string(), "vscode-chat".to_string()), - ]) + ( + "Editor-Plugin-Version".to_string(), + "copilot/1.250.0".to_string(), + ), + ( + "Copilot-Integration-Id".to_string(), + "vscode-chat".to_string(), + ), + ], + ) } } diff --git a/crates/openfang-runtime/src/drivers/gemini.rs b/crates/openfang-runtime/src/drivers/gemini.rs index f0acd32b4..14196ee85 100644 --- a/crates/openfang-runtime/src/drivers/gemini.rs +++ b/crates/openfang-runtime/src/drivers/gemini.rs @@ -334,10 +334,7 @@ fn convert_response(resp: GeminiResponse) -> Result { - let reason = candidate - .finish_reason - .as_deref() - .unwrap_or("unknown"); + let reason = candidate.finish_reason.as_deref().unwrap_or("unknown"); warn!(finish_reason = %reason, "Gemini returned candidate with no content"); return Err(LlmError::Parse(format!( "Gemini returned empty response (finish_reason: {reason})" diff --git a/crates/openfang-runtime/src/drivers/mod.rs b/crates/openfang-runtime/src/drivers/mod.rs index 0e6fbef62..bf2c8ed83 100644 --- a/crates/openfang-runtime/src/drivers/mod.rs +++ b/crates/openfang-runtime/src/drivers/mod.rs @@ -16,10 +16,10 @@ use openfang_types::model_catalog::{ AI21_BASE_URL, ANTHROPIC_BASE_URL, CEREBRAS_BASE_URL, COHERE_BASE_URL, DEEPSEEK_BASE_URL, FIREWORKS_BASE_URL, GEMINI_BASE_URL, GROQ_BASE_URL, HUGGINGFACE_BASE_URL, LMSTUDIO_BASE_URL, MINIMAX_BASE_URL, MISTRAL_BASE_URL, MOONSHOT_BASE_URL, OLLAMA_BASE_URL, OPENAI_BASE_URL, - OPENROUTER_BASE_URL, PERPLEXITY_BASE_URL, QIANFAN_BASE_URL, QWEN_BASE_URL, - REPLICATE_BASE_URL, SAMBANOVA_BASE_URL, TOGETHER_BASE_URL, VLLM_BASE_URL, - VOLCENGINE_BASE_URL, VOLCENGINE_CODING_BASE_URL, XAI_BASE_URL, ZAI_BASE_URL, - ZAI_CODING_BASE_URL, ZHIPU_BASE_URL, ZHIPU_CODING_BASE_URL, + OPENROUTER_BASE_URL, PERPLEXITY_BASE_URL, QIANFAN_BASE_URL, QWEN_BASE_URL, REPLICATE_BASE_URL, + SAMBANOVA_BASE_URL, TOGETHER_BASE_URL, VENICE_BASE_URL, VLLM_BASE_URL, VOLCENGINE_BASE_URL, + VOLCENGINE_CODING_BASE_URL, XAI_BASE_URL, ZAI_BASE_URL, ZAI_CODING_BASE_URL, ZHIPU_BASE_URL, + ZHIPU_CODING_BASE_URL, }; use std::sync::Arc; @@ -129,6 +129,11 @@ fn provider_defaults(provider: &str) -> Option { api_key_env: "REPLICATE_API_TOKEN", key_required: true, }), + "venice" => Some(ProviderDefaults { + base_url: VENICE_BASE_URL, + api_key_env: "VENICE_API_KEY", + key_required: true, + }), "github-copilot" | "copilot" => Some(ProviderDefaults { base_url: copilot::GITHUB_COPILOT_BASE_URL, api_key_env: "GITHUB_TOKEN", @@ -220,6 +225,7 @@ fn provider_defaults(provider: &str) -> Option { /// - `huggingface` — Hugging Face Inference API /// - `xai` — xAI (Grok) /// - `replicate` — Replicate +/// - `venice` — Venice.ai (privacy-focused, uncensored) /// - Any custom provider with `base_url` set uses OpenAI-compatible format pub fn create_driver(config: &DriverConfig) -> Result, LlmError> { let provider = config.provider.as_str(); @@ -267,9 +273,7 @@ pub fn create_driver(config: &DriverConfig) -> Result, LlmErr .or_else(|| std::env::var("OPENAI_API_KEY").ok()) .or_else(crate::model_catalog::read_codex_credential) .ok_or_else(|| { - LlmError::MissingApiKey( - "Set OPENAI_API_KEY or install Codex CLI".to_string(), - ) + LlmError::MissingApiKey("Set OPENAI_API_KEY or install Codex CLI".to_string()) })?; let base_url = config .base_url @@ -344,8 +348,8 @@ pub fn create_driver(config: &DriverConfig) -> Result, LlmErr message: format!( "Unknown provider '{}'. Supported: anthropic, gemini, openai, groq, openrouter, \ deepseek, together, mistral, fireworks, ollama, vllm, lmstudio, perplexity, \ - cohere, ai21, cerebras, sambanova, huggingface, xai, replicate, github-copilot, \ - codex, claude-code. Or set base_url for a custom OpenAI-compatible endpoint.", + cohere, ai21, cerebras, sambanova, huggingface, xai, replicate, venice, \ + github-copilot, codex, claude-code. Or set base_url for a custom OpenAI-compatible endpoint.", provider ), }) @@ -374,6 +378,7 @@ pub fn known_providers() -> &'static [&'static str] { "huggingface", "xai", "replicate", + "venice", "github-copilot", "moonshot", "qwen", @@ -470,6 +475,7 @@ mod tests { assert!(providers.contains(&"huggingface")); assert!(providers.contains(&"xai")); assert!(providers.contains(&"replicate")); + assert!(providers.contains(&"venice")); assert!(providers.contains(&"github-copilot")); assert!(providers.contains(&"moonshot")); assert!(providers.contains(&"qwen")); @@ -480,7 +486,7 @@ mod tests { assert!(providers.contains(&"volcengine")); assert!(providers.contains(&"codex")); assert!(providers.contains(&"claude-code")); - assert_eq!(providers.len(), 30); + assert_eq!(providers.len(), 31); } #[test] diff --git a/crates/openfang-runtime/src/drivers/openai.rs b/crates/openfang-runtime/src/drivers/openai.rs index 212122f01..c913b44f5 100644 --- a/crates/openfang-runtime/src/drivers/openai.rs +++ b/crates/openfang-runtime/src/drivers/openai.rs @@ -389,9 +389,16 @@ impl LlmDriver for OpenAIDriver { // Auto-cap max_tokens when model rejects our value (e.g. Groq Maverick limit 8192) if status == 400 && body.contains("max_tokens") && attempt < max_retries { - let current = oai_request.max_tokens.or(oai_request.max_completion_tokens).unwrap_or(4096); + let current = oai_request + .max_tokens + .or(oai_request.max_completion_tokens) + .unwrap_or(4096); let cap = extract_max_tokens_limit(&body).unwrap_or(current / 2); - warn!(old = current, new = cap, "Auto-capping max_tokens to model limit"); + warn!( + old = current, + new = cap, + "Auto-capping max_tokens to model limit" + ); if oai_request.max_completion_tokens.is_some() { oai_request.max_completion_tokens = Some(cap); } else { @@ -716,7 +723,10 @@ impl LlmDriver for OpenAIDriver { // Auto-cap max_tokens when model rejects our value if status == 400 && body.contains("max_tokens") && attempt < max_retries { - let current = oai_request.max_tokens.or(oai_request.max_completion_tokens).unwrap_or(4096); + let current = oai_request + .max_tokens + .or(oai_request.max_completion_tokens) + .unwrap_or(4096); let cap = extract_max_tokens_limit(&body).unwrap_or(current / 2); warn!(old = current, new = cap, "Auto-capping max_tokens (stream)"); if oai_request.max_completion_tokens.is_some() { diff --git a/crates/openfang-runtime/src/lib.rs b/crates/openfang-runtime/src/lib.rs index 77fa4fcfe..ed8fe854b 100644 --- a/crates/openfang-runtime/src/lib.rs +++ b/crates/openfang-runtime/src/lib.rs @@ -11,9 +11,9 @@ pub mod auth_cooldown; pub mod browser; pub mod command_lane; pub mod compactor; -pub mod copilot_oauth; pub mod context_budget; pub mod context_overflow; +pub mod copilot_oauth; pub mod docker_sandbox; pub mod drivers; pub mod embedding; diff --git a/crates/openfang-runtime/src/llm_errors.rs b/crates/openfang-runtime/src/llm_errors.rs index 0f4278fde..9ef265839 100644 --- a/crates/openfang-runtime/src/llm_errors.rs +++ b/crates/openfang-runtime/src/llm_errors.rs @@ -4,7 +4,7 @@ //! against error messages and HTTP status codes. Handles error formats from //! all 19+ providers OpenFang supports: Anthropic, OpenAI, Gemini, Groq, //! DeepSeek, Mistral, Together, Fireworks, Ollama, vLLM, LM Studio, -//! Perplexity, Cohere, AI21, Cerebras, SambaNova, HuggingFace, XAI, Replicate. +//! Perplexity, Cohere, AI21, Cerebras, SambaNova, HuggingFace, XAI, Replicate, Venice. //! //! Pattern matching is done via case-insensitive substring checks with no //! external regex dependency, keeping the crate dependency graph lean. diff --git a/crates/openfang-runtime/src/mcp.rs b/crates/openfang-runtime/src/mcp.rs index 6b492e69b..e002dce3c 100644 --- a/crates/openfang-runtime/src/mcp.rs +++ b/crates/openfang-runtime/src/mcp.rs @@ -419,9 +419,7 @@ impl McpConnection { let has_cmd = std::env::var("PATH") .unwrap_or_default() .split(';') - .any(|dir| { - std::path::Path::new(dir).join(&cmd_variant).exists() - }); + .any(|dir| std::path::Path::new(dir).join(&cmd_variant).exists()); if has_cmd { cmd_variant } else { diff --git a/crates/openfang-runtime/src/model_catalog.rs b/crates/openfang-runtime/src/model_catalog.rs index 3c4198e90..d10fb70e2 100644 --- a/crates/openfang-runtime/src/model_catalog.rs +++ b/crates/openfang-runtime/src/model_catalog.rs @@ -9,7 +9,7 @@ use openfang_types::model_catalog::{ GEMINI_BASE_URL, GITHUB_COPILOT_BASE_URL, GROQ_BASE_URL, HUGGINGFACE_BASE_URL, LMSTUDIO_BASE_URL, MINIMAX_BASE_URL, MISTRAL_BASE_URL, MOONSHOT_BASE_URL, OLLAMA_BASE_URL, OPENAI_BASE_URL, OPENROUTER_BASE_URL, PERPLEXITY_BASE_URL, QIANFAN_BASE_URL, QWEN_BASE_URL, - REPLICATE_BASE_URL, SAMBANOVA_BASE_URL, TOGETHER_BASE_URL, VLLM_BASE_URL, + REPLICATE_BASE_URL, SAMBANOVA_BASE_URL, TOGETHER_BASE_URL, VENICE_BASE_URL, VLLM_BASE_URL, VOLCENGINE_BASE_URL, VOLCENGINE_CODING_BASE_URL, XAI_BASE_URL, ZAI_BASE_URL, ZAI_CODING_BASE_URL, ZHIPU_BASE_URL, ZHIPU_CODING_BASE_URL, }; @@ -67,8 +67,7 @@ impl ModelCatalog { let has_fallback = match provider.id.as_str() { "gemini" => std::env::var("GOOGLE_API_KEY").is_ok(), "codex" => { - std::env::var("OPENAI_API_KEY").is_ok() - || read_codex_credential().is_some() + std::env::var("OPENAI_API_KEY").is_ok() || read_codex_credential().is_some() } "claude-code" => crate::drivers::claude_code::claude_code_available(), _ => false, @@ -572,6 +571,15 @@ fn builtin_providers() -> Vec { auth_status: AuthStatus::Missing, model_count: 0, }, + ProviderInfo { + id: "venice".into(), + display_name: "Venice.ai".into(), + api_key_env: "VENICE_API_KEY".into(), + base_url: VENICE_BASE_URL.into(), + key_required: true, + auth_status: AuthStatus::Missing, + model_count: 0, + }, // ── GitHub Copilot ─────────────────────────────────────────── ProviderInfo { id: "github-copilot".into(), @@ -767,6 +775,8 @@ fn builtin_aliases() -> HashMap { ("codex", "codex/gpt-4.1"), ("codex-4.1", "codex/gpt-4.1"), ("codex-o4", "codex/o4-mini"), + // Venice aliases + ("venice", "venice-uncensored"), // Claude Code aliases ("claude-code", "claude-code/sonnet"), ("claude-code-opus", "claude-code/opus"), @@ -2480,6 +2490,51 @@ fn builtin_models() -> Vec { aliases: vec![], }, // ══════════════════════════════════════════════════════════════ + // Venice.ai (3) — privacy-focused inference + // ══════════════════════════════════════════════════════════════ + ModelCatalogEntry { + id: "venice-uncensored".into(), + display_name: "Venice Uncensored".into(), + provider: "venice".into(), + tier: ModelTier::Fast, + context_window: 32_000, + max_output_tokens: 4_096, + input_cost_per_m: 0.20, + output_cost_per_m: 0.90, + supports_tools: false, + supports_vision: false, + supports_streaming: true, + aliases: vec!["venice".into()], + }, + ModelCatalogEntry { + id: "llama-3.3-70b".into(), + display_name: "Llama 3.3 70B (Venice)".into(), + provider: "venice".into(), + tier: ModelTier::Balanced, + context_window: 128_000, + max_output_tokens: 4_096, + input_cost_per_m: 0.70, + output_cost_per_m: 2.80, + supports_tools: true, + supports_vision: false, + supports_streaming: true, + aliases: vec![], + }, + ModelCatalogEntry { + id: "qwen3-235b-a22b-instruct-2507".into(), + display_name: "Qwen3 235B Instruct (Venice)".into(), + provider: "venice".into(), + tier: ModelTier::Smart, + context_window: 128_000, + max_output_tokens: 12_288, + input_cost_per_m: 0.15, + output_cost_per_m: 0.75, + supports_tools: true, + supports_vision: false, + supports_streaming: true, + aliases: vec![], + }, + // ══════════════════════════════════════════════════════════════ // GitHub Copilot (2) — free for subscribers // ══════════════════════════════════════════════════════════════ ModelCatalogEntry { @@ -3186,7 +3241,7 @@ mod tests { #[test] fn test_catalog_has_providers() { let catalog = ModelCatalog::new(); - assert_eq!(catalog.list_providers().len(), 34); + assert_eq!(catalog.list_providers().len(), 35); } #[test] @@ -3221,10 +3276,7 @@ mod tests { #[test] fn test_resolve_alias() { let catalog = ModelCatalog::new(); - assert_eq!( - catalog.resolve_alias("sonnet"), - Some("claude-sonnet-4-6") - ); + assert_eq!(catalog.resolve_alias("sonnet"), Some("claude-sonnet-4-6")); assert_eq!( catalog.resolve_alias("haiku"), Some("claude-haiku-4-5-20251001") @@ -3329,6 +3381,7 @@ mod tests { assert!(catalog.get_provider("huggingface").is_some()); assert!(catalog.get_provider("xai").is_some()); assert!(catalog.get_provider("replicate").is_some()); + assert!(catalog.get_provider("venice").is_some()); } #[test] diff --git a/crates/openfang-runtime/src/str_utils.rs b/crates/openfang-runtime/src/str_utils.rs index beb13a8bc..00ba72ce3 100644 --- a/crates/openfang-runtime/src/str_utils.rs +++ b/crates/openfang-runtime/src/str_utils.rs @@ -44,7 +44,7 @@ mod tests { fn multibyte_chinese() { // Each Chinese character is 3 bytes in UTF-8 let s = "\u{4f60}\u{597d}\u{4e16}\u{754c}"; // "hello world" in Chinese, 12 bytes - // Truncating at 7 bytes should not split the 3rd char (bytes 6..9) + // Truncating at 7 bytes should not split the 3rd char (bytes 6..9) let t = safe_truncate_str(s, 7); assert_eq!(t, "\u{4f60}\u{597d}"); // 6 bytes, 2 chars assert!(t.len() <= 7); diff --git a/crates/openfang-runtime/src/tool_runner.rs b/crates/openfang-runtime/src/tool_runner.rs index 7f3c5397e..ad9453a14 100644 --- a/crates/openfang-runtime/src/tool_runner.rs +++ b/crates/openfang-runtime/src/tool_runner.rs @@ -191,7 +191,9 @@ pub async fn execute_tool( let headers = input.get("headers").and_then(|v| v.as_object()); let body = input["body"].as_str(); if let Some(ctx) = web_ctx { - ctx.fetch.fetch_with_options(url, method, headers, body).await + ctx.fetch + .fetch_with_options(url, method, headers, body) + .await } else { tool_web_fetch_legacy(input).await } @@ -337,8 +339,7 @@ pub async fn execute_tool( crate::browser::tool_browser_navigate(input, mgr, aid).await } None => Err( - "Browser tools not available. Ensure Chrome/Chromium is installed." - .to_string(), + "Browser tools not available. Ensure Chrome/Chromium is installed.".to_string(), ), } } @@ -347,63 +348,81 @@ pub async fn execute_tool( let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_click(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, "browser_type" => match browser_ctx { Some(mgr) => { let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_type(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, "browser_screenshot" => match browser_ctx { Some(mgr) => { let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_screenshot(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, "browser_read_page" => match browser_ctx { Some(mgr) => { let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_read_page(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, "browser_close" => match browser_ctx { Some(mgr) => { let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_close(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, "browser_scroll" => match browser_ctx { Some(mgr) => { let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_scroll(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, "browser_wait" => match browser_ctx { Some(mgr) => { let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_wait(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, "browser_run_js" => match browser_ctx { Some(mgr) => { let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_run_js(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, "browser_back" => match browser_ctx { Some(mgr) => { let aid = caller_agent_id.unwrap_or("default"); crate::browser::tool_browser_back(input, mgr, aid).await } - None => Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()), + None => { + Err("Browser tools not available. Ensure Chrome/Chromium is installed.".to_string()) + } }, // Canvas / A2UI tool diff --git a/crates/openfang-runtime/src/web_content.rs b/crates/openfang-runtime/src/web_content.rs index d24c4198e..f8d32d926 100644 --- a/crates/openfang-runtime/src/web_content.rs +++ b/crates/openfang-runtime/src/web_content.rs @@ -424,7 +424,10 @@ mod tests { let html = "İstanbul ẞtraße bold text"; let md = html_to_markdown(html); assert!(md.contains("**bold**"), "Expected bold, got: {md}"); - assert!(md.contains("İstanbul"), "Expected unicode preserved, got: {md}"); + assert!( + md.contains("İstanbul"), + "Expected unicode preserved, got: {md}" + ); } #[test] diff --git a/crates/openfang-runtime/src/web_fetch.rs b/crates/openfang-runtime/src/web_fetch.rs index b76ea08cb..4adb12b15 100644 --- a/crates/openfang-runtime/src/web_fetch.rs +++ b/crates/openfang-runtime/src/web_fetch.rs @@ -186,9 +186,7 @@ pub(crate) fn check_ssrf(url: &str) -> Result<(), String> { let host = extract_host(url); // For IPv6 bracket notation like [::1]:80, extract [::1] as hostname let hostname = if host.starts_with('[') { - host.find(']') - .map(|i| &host[..=i]) - .unwrap_or(&host) + host.find(']').map(|i| &host[..=i]).unwrap_or(&host) } else { host.split(':').next().unwrap_or(&host) }; diff --git a/crates/openfang-types/src/approval.rs b/crates/openfang-types/src/approval.rs index a53dd45fc..157efed27 100644 --- a/crates/openfang-types/src/approval.rs +++ b/crates/openfang-types/src/approval.rs @@ -562,8 +562,7 @@ mod tests { #[test] fn policy_require_approval_bool_true() { // require_approval = true → ["shell_exec"] - let policy: ApprovalPolicy = - serde_json::from_str(r#"{"require_approval": true}"#).unwrap(); + let policy: ApprovalPolicy = serde_json::from_str(r#"{"require_approval": true}"#).unwrap(); assert_eq!(policy.require_approval, vec!["shell_exec"]); } diff --git a/crates/openfang-types/src/model_catalog.rs b/crates/openfang-types/src/model_catalog.rs index e1fbb17d7..3e98e76b8 100644 --- a/crates/openfang-types/src/model_catalog.rs +++ b/crates/openfang-types/src/model_catalog.rs @@ -28,6 +28,7 @@ pub const SAMBANOVA_BASE_URL: &str = "https://api.sambanova.ai/v1"; pub const HUGGINGFACE_BASE_URL: &str = "https://api-inference.huggingface.co/v1"; pub const XAI_BASE_URL: &str = "https://api.x.ai/v1"; pub const REPLICATE_BASE_URL: &str = "https://api.replicate.com/v1"; +pub const VENICE_BASE_URL: &str = "https://api.venice.ai/api/v1"; // ── GitHub Copilot ────────────────────────────────────────────── pub const GITHUB_COPILOT_BASE_URL: &str = "https://api.githubcopilot.com"; diff --git a/docs/providers.md b/docs/providers.md index 631bda5d1..e793d79df 100644 --- a/docs/providers.md +++ b/docs/providers.md @@ -1,6 +1,6 @@ # LLM Providers Guide -OpenFang ships with a comprehensive model catalog covering **3 native LLM drivers**, **20 providers**, **51 builtin models**, and **23 aliases**. Every provider uses one of three battle-tested drivers: the native **Anthropic** driver, the native **Gemini** driver, or the universal **OpenAI-compatible** driver. This guide is the single source of truth for configuring, selecting, and managing LLM providers in OpenFang. +OpenFang ships with a comprehensive model catalog covering **3 native LLM drivers**, **21 providers**, **54 builtin models**, and **24 aliases**. Every provider uses one of three battle-tested drivers: the native **Anthropic** driver, the native **Gemini** driver, or the universal **OpenAI-compatible** driver. This guide is the single source of truth for configuring, selecting, and managing LLM providers in OpenFang. --- @@ -542,6 +542,33 @@ For Gemini specifically, either `GEMINI_API_KEY` or `GOOGLE_API_KEY` will work. --- +### 21. Venice.ai + +| | | +|---|---| +| **Display Name** | Venice.ai | +| **Driver** | OpenAI-compatible | +| **Env Var** | `VENICE_API_KEY` | +| **Base URL** | `https://api.venice.ai/api/v1` | +| **Key Required** | Yes | +| **Free Tier** | No | +| **Auth** | `Authorization: Bearer` header | +| **Models** | 3 | + +**Available Models:** +- `venice-uncensored` (Fast) -- Venice's signature uncensored model +- `llama-3.3-70b` (Balanced) -- Llama 3.3 70B with privacy +- `qwen3-235b-a22b-instruct-2507` (Smart) -- Qwen3 235B on Venice + +**Setup:** +1. Sign up at [venice.ai](https://venice.ai) +2. Go to Settings > API and create an API key +3. `export VENICE_API_KEY="..."` + +**Notes:** Venice.ai is a privacy-focused AI platform. All models run with zero data retention in private mode. Venice also offers an uncensored model variant. The API is OpenAI-compatible. + +--- + ## Model Catalog The complete catalog of all 51 builtin models, sorted by provider. Pricing is per million tokens. @@ -594,6 +621,9 @@ The complete catalog of all 51 builtin models, sorted by provider. Pricing is pe | 44 | `grok-2-mini` | Grok 2 Mini | xai | Fast | 131,072 | 32,768 | $0.30 | $0.50 | Yes | No | | 45 | `hf/meta-llama/Llama-3.3-70B-Instruct` | Llama 3.3 70B (HF) | huggingface | Balanced | 128,000 | 4,096 | $0.30 | $0.30 | No | No | | 46 | `replicate/meta-llama-3.3-70b-instruct` | Llama 3.3 70B (Replicate) | replicate | Balanced | 128,000 | 4,096 | $0.40 | $0.40 | No | No | +| 47 | `venice-uncensored` | Venice Uncensored | venice | Fast | 32,000 | 4,096 | $0.20 | $0.90 | No | No | +| 48 | `llama-3.3-70b` | Llama 3.3 70B (Venice) | venice | Balanced | 128,000 | 4,096 | $0.70 | $2.80 | Yes | No | +| 49 | `qwen3-235b-a22b-instruct-2507` | Qwen3 235B Instruct (Venice) | venice | Smart | 128,000 | 12,288 | $0.15 | $0.75 | Yes | No | **Model Tiers:** @@ -640,6 +670,7 @@ All 23 aliases resolve to canonical model IDs. Aliases are case-insensitive. | `sonar` | `sonar-pro` | | `jamba` | `jamba-1.5-large` | | `command-r` | `command-r-plus` | +| `venice` | `venice-uncensored` | You can use aliases anywhere a model ID is accepted: in config files, REST API calls, chat commands, and the model routing configuration. @@ -762,6 +793,7 @@ The `MeteringEngine` first checks the **model catalog** for exact pricing. If th | `*cerebras*` | $0.06 | $0.06 | | `*sambanova*` | $0.06 | $0.06 | | `*replicate*` | $0.40 | $0.40 | +| `*venice*` | $0.20 | $0.90 | | `*llama*` / `*mixtral*` | $0.05 | $0.10 | | `*qwen*` | $0.20 | $0.60 | | `mistral-large*` | $2.00 | $6.00 | @@ -889,7 +921,7 @@ Returns a map of all alias-to-canonical-ID mappings. GET /api/providers ``` -Returns all 20 providers with auth status and model counts. +Returns all 21 providers with auth status and model counts. **Response:** ```json @@ -984,7 +1016,7 @@ Local: ### `/providers` -Lists all 20 providers with their authentication status. +Lists all 21 providers with their authentication status. ``` /providers @@ -992,7 +1024,7 @@ Lists all 20 providers with their authentication status. Example output: ``` -LLM Providers (20): +LLM Providers (21): Anthropic ANTHROPIC_API_KEY Configured 3 models OpenAI OPENAI_API_KEY Missing 6 models @@ -1033,6 +1065,7 @@ Quick reference for all provider environment variables: | Hugging Face | `HF_API_KEY` | Yes | | xAI | `XAI_API_KEY` | Yes | | Replicate | `REPLICATE_API_TOKEN` | Yes | +| Venice.ai | `VENICE_API_KEY` | Yes | ---