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