From 2954ae258fbb175f3b76ca7eed5d52a0baa217d6 Mon Sep 17 00:00:00 2001 From: Musa Date: Fri, 24 Apr 2026 16:32:00 -0700 Subject: [PATCH] fix(config): accept `vercel` and `openrouter` as provider_interface values (#915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Python CLI (#902) and the JSON schema both allow `vercel` and `openrouter` as `provider_interface`, and `hermesllm::ProviderId` knows how to dispatch them — but `crates/common::LlmProviderType` was never extended to deserialize them. As a result, `planoai up` with no user config (which synthesizes both providers via `cli/planoai/defaults.py`) caused brightstaff to crash on startup with: unknown variant `vercel`, expected one of `anthropic`, ..., `digitalocean` Add the missing enum variants and Display arms, plus a regression test that asserts both round-trip through serde and resolve through `to_provider_id()` (the exact path that previously panicked at parse). --- crates/common/src/configuration.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/common/src/configuration.rs b/crates/common/src/configuration.rs index 1275d77d..37492904 100644 --- a/crates/common/src/configuration.rs +++ b/crates/common/src/configuration.rs @@ -396,6 +396,10 @@ pub enum LlmProviderType { ChatGPT, #[serde(rename = "digitalocean")] DigitalOcean, + #[serde(rename = "vercel")] + Vercel, + #[serde(rename = "openrouter")] + OpenRouter, } impl Display for LlmProviderType { @@ -419,6 +423,8 @@ impl Display for LlmProviderType { LlmProviderType::Plano => write!(f, "plano"), LlmProviderType::ChatGPT => write!(f, "chatgpt"), LlmProviderType::DigitalOcean => write!(f, "digitalocean"), + LlmProviderType::Vercel => write!(f, "vercel"), + LlmProviderType::OpenRouter => write!(f, "openrouter"), } } } @@ -757,6 +763,26 @@ mod test { assert!(!model_ids.contains(&"plano-orchestrator".to_string())); } + #[test] + fn test_llm_provider_type_vercel_and_openrouter_roundtrip() { + // Regression: brightstaff used to reject `provider_interface: vercel` + // (and `openrouter`) because these variants were missing from + // `LlmProviderType`, causing `planoai up` with the synthesized default + // config to crash on startup. + for (yaml_value, expected) in [ + ("vercel", LlmProviderType::Vercel), + ("openrouter", LlmProviderType::OpenRouter), + ] { + let parsed: LlmProviderType = + serde_yaml::from_str(yaml_value).expect("variant should deserialize"); + assert_eq!(parsed, expected); + assert_eq!(parsed.to_string(), yaml_value); + // to_provider_id() bridges into hermesllm; both providers must be + // recognized there as well or this panics. + let _ = parsed.to_provider_id(); + } + } + #[test] fn test_overrides_disable_signals_default_none() { let overrides = super::Overrides::default();