ui: auto update card upon config (#1610)

This commit is contained in:
Lily Delalande
2025-03-11 17:02:32 -07:00
committed by GitHub
parent abf44e2197
commit 4aafc49707
9 changed files with 173 additions and 154 deletions
@@ -11,9 +11,9 @@ use http::{HeaderMap, StatusCode};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::env;
use utoipa::ToSchema;
use crate::routes::utils::check_provider_configured;
use crate::state::AppState;
fn verify_secret_key(headers: &HeaderMap, state: &AppState) -> Result<StatusCode, StatusCode> {
@@ -123,7 +123,7 @@ pub async fn remove_config(
}
#[utoipa::path(
post, // Change from get to post
post,
path = "/config/read",
request_body = ConfigKeyQuery, // Switch back to request_body
responses(
@@ -335,31 +335,6 @@ pub async fn providers(
Ok(Json(providers_response))
}
fn check_provider_configured(metadata: &ProviderMetadata) -> bool {
let config = Config::global();
// Check all required keys for the provider
for key in &metadata.config_keys {
if key.required {
let key_name = &key.name;
// First, check if the key is set in the environment
let is_set_in_env = env::var(key_name).is_ok();
// If not set in environment, check the config file based on whether it's a secret or not
let is_set_in_config = config.get(key_name, key.secret).is_ok();
// If the key is neither in the environment nor in the config, the provider is not configured
if !is_set_in_env && !is_set_in_config {
return false;
}
}
}
// If all required keys are accounted for, the provider is considered configured
true
}
pub fn routes(state: AppState) -> Router {
Router::new()
.route("/config", get(read_all_config))
+1 -1
View File
@@ -6,7 +6,7 @@ pub mod extension;
pub mod health;
pub mod reply;
pub mod session;
pub mod utils;
use axum::Router;
// Function to configure all routes
+66 -18
View File
@@ -1,13 +1,15 @@
use serde::{Deserialize, Serialize};
use std::error::Error;
use goose::config::Config;
use goose::providers::base::{ConfigKey, ProviderMetadata};
use serde::{Deserialize, Serialize};
use std::env;
use std::error::Error;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum KeyLocation {
Environment,
ConfigFile,
Keychain,
NotFound
NotFound,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -20,10 +22,8 @@ pub struct KeyInfo {
}
/// Inspects a configuration key to determine if it's set, its location, and value (for non-secret keys)
pub fn inspect_key(
key_name: &str,
is_secret: bool,
) -> Result<KeyInfo, Box<dyn Error>> {
#[allow(dead_code)]
pub fn inspect_key(key_name: &str, is_secret: bool) -> Result<KeyInfo, Box<dyn Error>> {
let config = Config::global();
// Check environment variable first
@@ -44,7 +44,7 @@ pub fn inspect_key(
let config_result = if is_secret {
config.get_secret(key_name).map(|v| (v, true))
} else {
config.get(key_name).map(|v| (v, false))
config.get_param(key_name).map(|v| (v, false))
};
match config_result {
@@ -64,20 +64,19 @@ pub fn inspect_key(
// Only include value for non-secret keys
value: if !is_secret_actual { Some(value) } else { None },
})
},
Err(_) => {
Ok(KeyInfo {
name: key_name.to_string(),
is_set: false,
location: KeyLocation::NotFound,
is_secret,
value: None,
})
}
Err(_) => Ok(KeyInfo {
name: key_name.to_string(),
is_set: false,
location: KeyLocation::NotFound,
is_secret,
value: None,
}),
}
}
/// Inspects multiple keys at once
#[allow(dead_code)]
pub fn inspect_keys(
keys: &[(String, bool)], // (name, is_secret) pairs
) -> Result<Vec<KeyInfo>, Box<dyn Error>> {
@@ -89,4 +88,53 @@ pub fn inspect_keys(
}
Ok(results)
}
}
pub fn check_provider_configured(metadata: &ProviderMetadata) -> bool {
let config = Config::global();
// Get all required keys
let required_keys: Vec<&ConfigKey> = metadata
.config_keys
.iter()
.filter(|key| key.required)
.collect();
// Special case: If a provider has exactly one required key and that key
// has a default value, check if it's explicitly set
if required_keys.len() == 1 && required_keys[0].default.is_some() {
let key = &required_keys[0];
// Check if the key is explicitly set (either in env or config)
let is_set_in_env = env::var(&key.name).is_ok();
let is_set_in_config = config.get(&key.name, key.secret).is_ok();
return is_set_in_env || is_set_in_config;
}
// For providers with multiple keys or keys without defaults:
// Find required keys that don't have default values
let required_non_default_keys: Vec<&ConfigKey> = required_keys
.iter()
.filter(|key| key.default.is_none())
.cloned()
.collect();
// If there are no non-default keys, this provider needs at least one key explicitly set
if required_non_default_keys.is_empty() {
return required_keys.iter().any(|key| {
let is_set_in_env = env::var(&key.name).is_ok();
let is_set_in_config = config.get(&key.name, key.secret).is_ok();
is_set_in_env || is_set_in_config
});
}
// Otherwise, all non-default keys must be set
required_non_default_keys.iter().all(|key| {
let is_set_in_env = env::var(&key.name).is_ok();
let is_set_in_config = config.get(&key.name, key.secret).is_ok();
is_set_in_env || is_set_in_config
})
}