ferrum_cli/
runtime_env.rs1use ferrum_types::{RuntimeConfigEntry, RuntimeConfigSnapshot, RuntimeConfigSource};
9
10pub fn push_cli_runtime_entry(
11 entries: &mut Vec<RuntimeConfigEntry>,
12 key: &str,
13 value: Option<&str>,
14) {
15 if let Some(value) = value.filter(|value| !value.trim().is_empty()) {
16 entries.push(RuntimeConfigEntry::new(
17 key,
18 value.to_string(),
19 RuntimeConfigSource::Cli,
20 ));
21 }
22}
23
24pub fn push_cli_runtime_usize(
25 entries: &mut Vec<RuntimeConfigEntry>,
26 key: &str,
27 value: Option<usize>,
28) {
29 if let Some(value) = value {
30 entries.push(RuntimeConfigEntry::new(
31 key,
32 value.to_string(),
33 RuntimeConfigSource::Cli,
34 ));
35 }
36}
37
38pub fn materialize_runtime_env_defaults(entries: &[RuntimeConfigEntry]) -> Vec<String> {
39 let mut materialized = Vec::new();
40 for entry in entries {
41 if std::env::var_os(&entry.key).is_none() {
42 std::env::set_var(&entry.key, &entry.effective_value);
43 materialized.push(entry.key.clone());
44 }
45 }
46 materialized
47}
48
49pub fn materialize_runtime_env_effective(snapshot: &RuntimeConfigSnapshot) -> Vec<String> {
50 let mut materialized = Vec::new();
51 for entry in &snapshot.entries {
52 if entry.source != RuntimeConfigSource::Env {
53 std::env::set_var(&entry.key, &entry.effective_value);
54 materialized.push(entry.key.clone());
55 }
56 }
57 materialized
58}
59
60pub fn moe_graph_default_entries(
66 current: &RuntimeConfigSnapshot,
67 source: RuntimeConfigSource,
68) -> Vec<RuntimeConfigEntry> {
69 let mut entries = Vec::new();
70 let moe_graph_enabled = match runtime_snapshot_value(current, "FERRUM_MOE_GRAPH") {
71 Some(value) => value == "1",
72 None => {
73 entries.push(RuntimeConfigEntry::new("FERRUM_MOE_GRAPH", "0", source));
74 false
75 }
76 };
77
78 if !moe_graph_enabled {
79 return entries;
80 }
81
82 #[cfg(feature = "vllm-moe-marlin")]
83 {
84 if runtime_snapshot_value(current, "FERRUM_VLLM_MOE").is_none() {
85 entries.push(RuntimeConfigEntry::new("FERRUM_VLLM_MOE", "1", source));
86 }
87 if runtime_snapshot_value(current, "FERRUM_VLLM_MOE_PAIR_IDS").is_none() {
88 entries.push(RuntimeConfigEntry::new(
89 "FERRUM_VLLM_MOE_PAIR_IDS",
90 "1",
91 source,
92 ));
93 }
94 }
95
96 entries
97}
98
99pub fn warn_if_moe_graph_needs_unbuilt_vllm_moe(_snapshot: &RuntimeConfigSnapshot) {
100 #[cfg(not(feature = "vllm-moe-marlin"))]
101 if runtime_snapshot_value(_snapshot, "FERRUM_MOE_GRAPH") == Some("1")
102 && runtime_snapshot_value(_snapshot, "FERRUM_VLLM_MOE") != Some("1")
103 {
104 eprintln!(
105 "[auto-size] MOE_GRAPH=1 requested, but vllm-moe-marlin is not built; graph capture requires FERRUM_VLLM_MOE=1"
106 );
107 }
108}
109
110pub fn runtime_snapshot_value<'a>(
111 snapshot: &'a RuntimeConfigSnapshot,
112 key: &str,
113) -> Option<&'a str> {
114 snapshot
115 .entries
116 .iter()
117 .find(|entry| entry.key == key)
118 .map(|entry| entry.effective_value.as_str())
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 fn snapshot(entries: &[(&str, &str, RuntimeConfigSource)]) -> RuntimeConfigSnapshot {
126 RuntimeConfigSnapshot::from_entries(
127 entries
128 .iter()
129 .map(|(key, value, source)| RuntimeConfigEntry::new(*key, *value, *source)),
130 )
131 }
132
133 #[test]
134 fn moe_graph_defaults_add_missing_graph_default() {
135 let entries = moe_graph_default_entries(
136 &RuntimeConfigSnapshot::default(),
137 RuntimeConfigSource::Default,
138 );
139 let resolved = RuntimeConfigSnapshot::from_entries(entries);
140 let graph = runtime_snapshot_value(&resolved, "FERRUM_MOE_GRAPH");
141
142 assert_eq!(graph, Some("0"));
143 assert_eq!(resolved.entries.len(), 1);
144 }
145
146 #[test]
147 fn moe_graph_defaults_respect_forced_off_graph() {
148 let current = snapshot(&[("FERRUM_MOE_GRAPH", "0", RuntimeConfigSource::Env)]);
149 let entries = moe_graph_default_entries(¤t, RuntimeConfigSource::Default);
150
151 assert!(entries.is_empty());
152 }
153
154 #[test]
155 fn moe_graph_defaults_complete_graph_enabled_snapshot() {
156 let current = snapshot(&[("FERRUM_MOE_GRAPH", "1", RuntimeConfigSource::ConfigFile)]);
157 let entries = moe_graph_default_entries(¤t, RuntimeConfigSource::Default);
158 let resolved = RuntimeConfigSnapshot::from_entries(entries);
159
160 assert_eq!(runtime_snapshot_value(&resolved, "FERRUM_MOE_GRAPH"), None);
161 #[cfg(feature = "vllm-moe-marlin")]
162 assert_eq!(
163 runtime_snapshot_value(&resolved, "FERRUM_VLLM_MOE"),
164 Some("1")
165 );
166 #[cfg(not(feature = "vllm-moe-marlin"))]
167 assert!(resolved.entries.is_empty());
168 }
169}