lean_ctx/core/knowledge_router/
manifest_builder.rs1use std::fs;
3
4use super::source_manifest::{CostClass, SourceCapabilities, SourceManifestEntry};
5
6#[derive(Debug, Clone, Default, PartialEq, Eq)]
7pub struct ProviderConfig {
8 pub jira_configured: bool,
9 pub github_configured: bool,
10 pub gitlab_configured: bool,
11 pub postgres_configured: bool,
12 pub custom_providers: Vec<String>,
13}
14
15pub fn build_manifests_from_config(config: &ProviderConfig) -> Vec<SourceManifestEntry> {
16 let mut provider_ids = config.custom_providers.clone();
17 provider_ids.extend(
18 [
19 (config.jira_configured, "jira"),
20 (config.github_configured, "github"),
21 (config.gitlab_configured, "gitlab"),
22 (config.postgres_configured, "postgres"),
23 ]
24 .into_iter()
25 .filter_map(|(enabled, id)| enabled.then_some(id.to_string())),
26 );
27 build_manifests_for_provider_ids(&provider_ids)
28}
29
30pub fn build_manifests_for_provider_ids(provider_ids: &[String]) -> Vec<SourceManifestEntry> {
32 let mut manifests = vec![entry(
33 "local_files",
34 "LocalFiles",
35 &["file"],
36 CostClass::Negligible,
37 )];
38 let mut provider_ids = provider_ids.to_vec();
39 provider_ids.sort();
40 provider_ids.dedup();
41 manifests.extend(provider_ids.iter().map(|id| provider_entry(id)));
42 manifests
43}
44
45pub fn detect_config() -> ProviderConfig {
46 let providers = crate::core::config::Config::load().providers;
47 let file = crate::core::config::Config::path()
48 .and_then(|path| fs::read_to_string(path).ok())
49 .unwrap_or_default();
50 let configured = |env: &str, value: bool| std::env::var_os(env).is_some() || value;
51 ProviderConfig {
52 jira_configured: configured("JIRA_URL", file.contains("[providers.jira]")),
53 github_configured: configured(
54 "GITHUB_TOKEN",
55 providers.github.token.is_some() || providers.github.api_url.is_some(),
56 ),
57 gitlab_configured: configured(
58 "GITLAB_TOKEN",
59 providers.gitlab.token.is_some() || providers.gitlab.api_url.is_some(),
60 ),
61 postgres_configured: std::env::var_os("DATABASE_URL").is_some()
62 || std::env::var_os("PGDATABASE").is_some(),
63 custom_providers: providers.mcp_bridges.keys().cloned().collect(),
64 }
65}
66
67fn provider_entry(id: &str) -> SourceManifestEntry {
68 match id {
69 "jira" => entry(id, "Jira", &["issue"], CostClass::Low),
70 "github" => entry(id, "GitHub", &["issue", "pull_request"], CostClass::Low),
71 "gitlab" => entry(id, "GitLab", &["issue", "pull_request"], CostClass::Low),
72 "postgres" => entry(id, "PostgreSQL", &["schema", "table"], CostClass::Medium),
73 "emspace" => entry(id, "Emspace", &["page", "task"], CostClass::Low),
74 _ => entry(id, id, &["external"], CostClass::Medium),
75 }
76}
77
78fn entry(id: &str, name: &str, kinds: &[&str], cost_class: CostClass) -> SourceManifestEntry {
79 SourceManifestEntry {
80 source_id: id.into(),
81 display_name: name.into(),
82 kinds: kinds.iter().map(|kind| (*kind).into()).collect(),
83 capabilities: SourceCapabilities {
84 search: true,
85 exact_get: true,
86 delta_sync: true,
87 live_query: id != "local_files",
88 graph_edges: true,
89 },
90 freshness_typical_ms: 60_000,
91 cost_class,
92 }
93}