feat(ai): curated OpenRouter model picker for hybrid backend
Add OPENROUTER_ALLOWED_MODELS env var and GET /insights/openrouter/models endpoint returning the curated list verbatim. Drop the live capability precheck in hybrid mode — trust the operator's allowlist; bad ids surface as a chat-call error. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
20
src/state.rs
20
src/state.rs
@@ -39,6 +39,9 @@ pub struct AppState {
|
||||
/// generator.
|
||||
#[allow(dead_code)]
|
||||
pub openrouter: Option<Arc<OpenRouterClient>>,
|
||||
/// Curated list of OpenRouter model ids exposed to clients. Sourced from
|
||||
/// `OPENROUTER_ALLOWED_MODELS` (comma-separated). Empty when unset.
|
||||
pub openrouter_allowed_models: Vec<String>,
|
||||
pub sms_client: SmsApiClient,
|
||||
pub insight_generator: InsightGenerator,
|
||||
}
|
||||
@@ -70,6 +73,7 @@ impl AppState {
|
||||
excluded_dirs: Vec<String>,
|
||||
ollama: OllamaClient,
|
||||
openrouter: Option<Arc<OpenRouterClient>>,
|
||||
openrouter_allowed_models: Vec<String>,
|
||||
sms_client: SmsApiClient,
|
||||
insight_generator: InsightGenerator,
|
||||
preview_dao: Arc<Mutex<Box<dyn PreviewDao>>>,
|
||||
@@ -102,6 +106,7 @@ impl AppState {
|
||||
excluded_dirs,
|
||||
ollama,
|
||||
openrouter,
|
||||
openrouter_allowed_models,
|
||||
sms_client,
|
||||
insight_generator,
|
||||
}
|
||||
@@ -138,6 +143,7 @@ impl Default for AppState {
|
||||
);
|
||||
|
||||
let openrouter = build_openrouter_from_env();
|
||||
let openrouter_allowed_models = parse_openrouter_allowed_models();
|
||||
|
||||
let sms_api_url =
|
||||
env::var("SMS_API_URL").unwrap_or_else(|_| "http://localhost:8000".to_string());
|
||||
@@ -209,6 +215,7 @@ impl Default for AppState {
|
||||
Self::parse_excluded_dirs(),
|
||||
ollama,
|
||||
openrouter,
|
||||
openrouter_allowed_models,
|
||||
sms_client,
|
||||
insight_generator,
|
||||
preview_dao,
|
||||
@@ -235,6 +242,18 @@ fn build_openrouter_from_env() -> Option<Arc<OpenRouterClient>> {
|
||||
Some(Arc::new(client))
|
||||
}
|
||||
|
||||
/// Parse `OPENROUTER_ALLOWED_MODELS` (comma-separated) into a vec. Returns
|
||||
/// empty when unset, in which case `/insights/openrouter/models` reports no
|
||||
/// curated picks and the server falls back to `OPENROUTER_DEFAULT_MODEL`.
|
||||
fn parse_openrouter_allowed_models() -> Vec<String> {
|
||||
env::var("OPENROUTER_ALLOWED_MODELS")
|
||||
.unwrap_or_default()
|
||||
.split(',')
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl AppState {
|
||||
/// Creates an AppState instance for testing with temporary directories
|
||||
@@ -321,6 +340,7 @@ impl AppState {
|
||||
Vec::new(), // No excluded directories for test state
|
||||
ollama,
|
||||
None,
|
||||
Vec::new(),
|
||||
sms_client,
|
||||
insight_generator,
|
||||
preview_dao,
|
||||
|
||||
Reference in New Issue
Block a user