diff --git a/.github/workflows/update-models.yaml b/.github/workflows/update-models.yaml index 99ee468..b4d20f3 100644 --- a/.github/workflows/update-models.yaml +++ b/.github/workflows/update-models.yaml @@ -46,9 +46,6 @@ jobs: if: steps.duckdb-extensions.outputs.cache-hit != 'true' run: cargo test --all duckdb - # Coyote loads its config before handling --generate-models/--list-models, and a - # bare non-TTY runner has no config file (and no way to answer the first-run - # prompt), so point COYOTE_CONFIG_DIR at a throwaway dir with a minimal stub. - name: Write stub config run: | COYOTE_CONFIG_DIR="$(mktemp -d)" diff --git a/src/config/app_state.rs b/src/config/app_state.rs index ebe65aa..4190b49 100644 --- a/src/config/app_state.rs +++ b/src/config/app_state.rs @@ -42,9 +42,14 @@ impl AppState { config: Arc, log_path: Option, start_mcp_servers: bool, + lenient_vault: bool, abort_signal: AbortSignal, ) -> Result { - let vault = Arc::new(Vault::init(&config)?); + let vault = if lenient_vault { + Arc::new(Vault::init_lenient(&config)) + } else { + Arc::new(Vault::init(&config)?) + }; let mcp_registry = McpRegistry::init( log_path, diff --git a/src/config/mod.rs b/src/config/mod.rs index 36d16ae..381b283 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -705,6 +705,10 @@ impl Config { Self::load_from_file(&config_path)? }; + if info_flag { + return Ok(config); + } + let bootstrap_app = AppConfig { vault_password_file: config.vault_password_file.clone(), secrets_provider: config.secrets_provider.clone(), @@ -712,7 +716,7 @@ impl Config { }; let vault = Vault::init(&bootstrap_app)?; let (parsed_config, missing_secrets) = interpolate_secrets(&content, &vault)?; - if !missing_secrets.is_empty() && !info_flag { + if !missing_secrets.is_empty() { debug!( "Global config references secrets that are missing from the vault: {missing_secrets:?}" ); @@ -723,7 +727,7 @@ impl Config { missing_secrets ))); } - if !parsed_config.is_empty() && !info_flag { + if !parsed_config.is_empty() { debug!("Global config is invalid once secrets are injected: {parsed_config}"); let new_config = Self::load_from_str(&parsed_config).with_context(|| { formatdoc!( @@ -735,6 +739,7 @@ impl Config { })?; config = new_config; } + Ok(config) } diff --git a/src/main.rs b/src/main.rs index 8f99d3c..091a822 100644 --- a/src/main.rs +++ b/src/main.rs @@ -102,7 +102,6 @@ async fn main() -> Result<()> { let info_flag = cli.info || cli.sync_models - || cli.generate_models.is_some() || cli.list_models || cli.list_roles || cli.list_agents @@ -118,6 +117,10 @@ async fn main() -> Result<()> { let log_path = setup_logger(cli.acp_server)?; + if let Some(path) = &cli.generate_models { + return catalog::generate_models_file(path).await; + } + if let Some(version) = &cli.update { let version = version.clone(); let force = cli.force; @@ -250,6 +253,7 @@ async fn main() -> Result<()> { app_config, log_path, start_mcp_servers, + info_flag, abort_signal.clone(), ) .await?, @@ -297,10 +301,6 @@ async fn run( return sync_models(url.as_deref(), abort_signal.clone()).await; } - if let Some(path) = &cli.generate_models { - return catalog::generate_models_file(path).await; - } - if cli.list_models { for model in list_models(ctx.app.config.as_ref(), ModelType::Chat) { println!("{}", model.id()); diff --git a/src/vault/mod.rs b/src/vault/mod.rs index 2573520..43dad8a 100644 --- a/src/vault/mod.rs +++ b/src/vault/mod.rs @@ -96,14 +96,25 @@ impl Vault { } pub fn init(config: &AppConfig) -> Result { - if env::var_os(SANDBOX_ENV_FLAG).is_some() { - return Ok(Self { - sandbox_mode: true, - ..Self::default() - }); + let mut vault = Self::init_lenient(config); + if !vault.sandbox_mode + && let SupportedProvider::Local { provider_def } = &mut vault.provider + { + ensure_password_file_initialized(provider_def)?; } - let mut provider = match &config.secrets_provider { + Ok(vault) + } + + pub fn init_lenient(config: &AppConfig) -> Self { + if env::var_os(SANDBOX_ENV_FLAG).is_some() { + return Self { + sandbox_mode: true, + ..Self::default() + }; + } + + let provider = match &config.secrets_provider { Some(p) => p.clone(), None => SupportedProvider::Local { provider_def: LocalProvider { @@ -113,14 +124,10 @@ impl Vault { }, }; - if let SupportedProvider::Local { provider_def } = &mut provider { - ensure_password_file_initialized(provider_def)?; - } - - Ok(Self { + Self { provider, sandbox_mode: false, - }) + } } pub fn local_password_file(&self) -> Result {