feat: added REPL support for interacting with the Loki vault

This commit is contained in:
2025-10-15 15:15:04 -06:00
parent 591f204b67
commit df8b326d89
9 changed files with 419 additions and 324 deletions
+29 -26
View File
@@ -24,8 +24,8 @@ use crate::utils::*;
use crate::mcp::{
McpRegistry, MCP_INVOKE_META_FUNCTION_NAME_PREFIX, MCP_LIST_META_FUNCTION_NAME_PREFIX,
};
use crate::vault::Vault;
use anyhow::{anyhow, bail, Context, Result};
use gman::providers::local::LocalProvider;
use indexmap::IndexMap;
use inquire::{list_option::ListOption, validator::Validation, Confirm, MultiSelect, Select, Text};
use log::LevelFilter;
@@ -121,7 +121,7 @@ pub struct Config {
pub editor: Option<String>,
pub wrap: Option<String>,
pub wrap_code: bool,
pub(crate) password_file: Option<PathBuf>,
vault_password_file: Option<PathBuf>,
pub function_calling: bool,
pub mapping_tools: IndexMap<String, String>,
@@ -162,8 +162,8 @@ pub struct Config {
pub clients: Vec<ClientConfig>,
#[serde(skip)]
pub secrets_provider: Option<LocalProvider>,
#[serde(skip)]
pub vault: Vault,
#[serde(skip)]
pub macro_flag: bool,
@@ -207,7 +207,7 @@ impl Default for Config {
editor: None,
wrap: None,
wrap_code: false,
password_file: None,
vault_password_file: None,
function_calling: true,
mapping_tools: Default::default(),
@@ -247,7 +247,7 @@ impl Default for Config {
clients: vec![],
secrets_provider: None,
vault: Default::default(),
macro_flag: false,
info_flag: false,
@@ -312,7 +312,6 @@ impl Config {
config.working_mode = working_mode;
config.info_flag = info_flag;
config.load_secrets_provider();
let setup = async |config: &mut Self| -> Result<()> {
config.load_envs();
@@ -329,6 +328,7 @@ impl Config {
config.setup_model()?;
config.setup_document_loaders();
config.setup_user_agent();
config.vault = Vault::init(config);
Ok(())
};
let ret = setup(&mut config).await;
@@ -370,8 +370,8 @@ impl Config {
}
}
pub fn secrets_password_file(&self) -> PathBuf {
match &self.password_file {
pub fn vault_password_file(&self) -> PathBuf {
match &self.vault_password_file {
Some(path) => match path.exists() {
true => path.clone(),
false => gman::config::Config::local_provider_password_file(),
@@ -707,6 +707,10 @@ impl Config {
("macros_dir", display_path(&Self::macros_dir())),
("functions_dir", display_path(&Self::functions_dir())),
("messages_file", display_path(&self.messages_file())),
(
"vault_password_file",
display_path(&self.vault_password_file()),
),
];
if let Ok((_, Some(log_path))) = Self::log_config(self.working_mode.is_serve()) {
items.push(("log_path", display_path(&log_path)));
@@ -2050,6 +2054,14 @@ impl Config {
".delete" => {
map_completion_values(vec!["role", "session", "rag", "macro", "agent-data"])
}
".vault" => {
let mut values = vec!["add", "get", "update", "delete", "list"];
values.sort_unstable();
values
.into_iter()
.map(|v| (format!("{v} "), None))
.collect()
}
_ => vec![],
};
} else if cmd == ".set" && args.len() == 2 {
@@ -2139,6 +2151,14 @@ impl Config {
_ => vec![],
};
values = candidates.into_iter().map(|v| (v, None)).collect();
} else if cmd == ".vault" && args.len() == 2 {
values = self
.vault
.list_secrets(false)
.unwrap_or_default()
.into_iter()
.map(|v| (v, None))
.collect();
} else if cmd == ".agent" {
if args.len() == 2 {
let dir = Self::agent_data_dir(args[0]).join(SESSIONS_DIR_NAME);
@@ -2523,23 +2543,6 @@ impl Config {
Ok(config)
}
fn load_secrets_provider(&mut self) {
let secrets_password_file = self.secrets_password_file();
if !secrets_password_file.exists() {
eprintln!(
"Warning: secrets password file '{}' does not exist.",
secrets_password_file.display()
);
return;
}
self.secrets_provider = Some(LocalProvider {
password_file: Some(secrets_password_file),
git_branch: None,
..LocalProvider::default()
});
}
fn load_envs(&mut self) {
if let Ok(v) = env::var(get_env_name("model")) {
self.model_id = v;