systemprompt_cli/commands/admin/setup/
catalog.rs1use std::collections::HashMap;
16
17use systemprompt_identifiers::{ProviderId, RouteId};
18use systemprompt_models::profile::{GatewayRoute, ProviderRegistry};
19
20use super::secrets::SecretsData;
21
22struct ProviderDefault {
23 name: &'static str,
24 route_pattern: &'static str,
25 default_upstream: Option<&'static str>,
29 present: fn(&SecretsData) -> bool,
30}
31
32const PROVIDER_DEFAULTS: &[ProviderDefault] = &[
33 ProviderDefault {
34 name: "anthropic",
35 route_pattern: "claude-*",
36 default_upstream: None,
37 present: |s| s.anthropic.is_some(),
38 },
39 ProviderDefault {
40 name: "openai",
41 route_pattern: "gpt-*",
42 default_upstream: Some("gpt-5-mini"),
43 present: |s| s.openai.is_some(),
44 },
45 ProviderDefault {
46 name: "gemini",
47 route_pattern: "gemini-*",
48 default_upstream: None,
49 present: |s| s.gemini.is_some(),
50 },
51];
52
53fn present_defaults(secrets: &SecretsData) -> Vec<&'static ProviderDefault> {
54 PROVIDER_DEFAULTS
55 .iter()
56 .filter(|p| (p.present)(secrets))
57 .collect()
58}
59
60pub fn build_routes(secrets: &SecretsData) -> Vec<GatewayRoute> {
61 present_defaults(secrets)
62 .iter()
63 .map(|d| {
64 let mut route = GatewayRoute {
65 id: RouteId::new(""),
66 model_pattern: d.route_pattern.to_owned(),
67 provider: ProviderId::new(d.name),
68 upstream_model: d.default_upstream.map(str::to_owned),
69 extra_headers: HashMap::new(),
70 pricing: None,
71 when: None,
72 };
73 route.ensure_id();
74 route
75 })
76 .collect()
77}
78
79pub fn build_registry(secrets: &SecretsData) -> ProviderRegistry {
80 let seed = match ProviderRegistry::default_seed() {
81 Ok(seed) => seed,
82 Err(e) => {
83 tracing::error!(
84 error = %e,
85 "embedded default provider catalog failed to parse; seeding an empty provider \
86 registry"
87 );
88 return ProviderRegistry::default();
89 },
90 };
91 ProviderRegistry {
92 providers: present_defaults(secrets)
93 .iter()
94 .filter_map(|d| seed.find_provider(d.name).cloned())
95 .collect(),
96 }
97}