update docs + agents
This commit is contained in:
115
src/agent_integrator/mod.rs
Normal file
115
src/agent_integrator/mod.rs
Normal file
@@ -0,0 +1,115 @@
|
||||
//! System Service Integration (Agent Integrator)
|
||||
//!
|
||||
//! This module translates the mathematical optimums defined by the Analyst
|
||||
//! into actionable, real-world Linux/OS service configurations.
|
||||
//! It generates templates for fan daemons (i8kmon, thinkfan) and handles
|
||||
//! resolution strategies for overlapping daemons.
|
||||
|
||||
use anyhow::Result;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
use crate::agent_analyst::OptimizationMatrix;
|
||||
|
||||
pub struct ServiceIntegrator;
|
||||
|
||||
impl ServiceIntegrator {
|
||||
/// Generates and saves an i8kmon configuration based on the balanced profile.
|
||||
pub fn generate_i8kmon_config(matrix: &OptimizationMatrix, output_path: &Path) -> Result<()> {
|
||||
let profile = &matrix.balanced;
|
||||
|
||||
let mut conf = String::new();
|
||||
conf.push_str("# Auto-generated by ember-tune Integrator
|
||||
");
|
||||
conf.push_str(&format!("# Profile: {}
|
||||
|
||||
", profile.name));
|
||||
|
||||
for (i, p) in profile.fan_curve.iter().enumerate() {
|
||||
// i8kmon syntax: set config(state) {left_fan right_fan temp_on temp_off}
|
||||
// State 0, 1, 2, 3 correspond to BIOS fan states (off, low, high)
|
||||
|
||||
let state = match p.pwm_percent {
|
||||
0..=20 => 0,
|
||||
21..=50 => 1,
|
||||
51..=100 => 2,
|
||||
_ => 2,
|
||||
};
|
||||
|
||||
let off = if i == 0 { "-".to_string() } else { format!("{}", p.temp_off) };
|
||||
conf.push_str(&format!("set config({}) {{{} {} {} {}}}
|
||||
", i, state, state, p.temp_on, off));
|
||||
}
|
||||
|
||||
fs::write(output_path, conf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generates a thinkfan configuration.
|
||||
pub fn generate_thinkfan_config(matrix: &OptimizationMatrix, output_path: &Path) -> Result<()> {
|
||||
let profile = &matrix.balanced;
|
||||
|
||||
let mut conf = String::new();
|
||||
conf.push_str("# Auto-generated by ember-tune Integrator
|
||||
");
|
||||
conf.push_str("sensors:
|
||||
- hwmon: /sys/class/hwmon/hwmon0/temp1_input
|
||||
|
||||
");
|
||||
conf.push_str("levels:
|
||||
");
|
||||
|
||||
for (i, p) in profile.fan_curve.iter().enumerate() {
|
||||
// thinkfan syntax: - [level, temp_down, temp_up]
|
||||
let level = match p.pwm_percent {
|
||||
0..=20 => 0,
|
||||
21..=40 => 1,
|
||||
41..=60 => 3,
|
||||
61..=80 => 5,
|
||||
_ => 7,
|
||||
};
|
||||
|
||||
let down = if i == 0 { 0.0 } else { p.temp_off };
|
||||
conf.push_str(&format!(" - [{}, {}, {}]
|
||||
", level, down, p.temp_on));
|
||||
}
|
||||
|
||||
fs::write(output_path, conf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generates a resolution checklist/script for daemons.
|
||||
pub fn generate_conflict_resolution_script(output_path: &Path) -> Result<()> {
|
||||
let script = r#"#!/bin/bash
|
||||
# ember-tune Daemon Neutralization Script
|
||||
|
||||
# 1. Mask power-profiles-daemon (Prevent ACPI overrides)
|
||||
systemctl mask power-profiles-daemon
|
||||
|
||||
# 2. Filter TLP (Prevent CPU governor fights while keeping PCIe saving)
|
||||
sed -i 's/^CPU_SCALING_GOVERNOR_ON_AC=.*/CPU_SCALING_GOVERNOR_ON_AC=""/' /etc/tlp.conf
|
||||
sed -i 's/^CPU_BOOST_ON_AC=.*/CPU_BOOST_ON_AC=""/' /etc/tlp.conf
|
||||
systemctl restart tlp
|
||||
|
||||
# 3. Thermald Delegate (We provide the trips, it handles the rest)
|
||||
# (Ensure your custom thermal-conf.xml is in /etc/thermald/)
|
||||
systemctl restart thermald
|
||||
"#;
|
||||
fs::write(output_path, script)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generates a thermald configuration XML.
|
||||
pub fn generate_thermald_config(matrix: &OptimizationMatrix, output_path: &Path) -> Result<()> {
|
||||
let profile = &matrix.balanced;
|
||||
let mut xml = String::new();
|
||||
xml.push_str("<?xml version=\"1.0\"?>\n<ThermalConfiguration>\n <Platform>\n <Name>ember-tune Balanced</Name>\n <ProductName>Generic</ProductName>\n <Preference>balanced</Preference>\n <ThermalZones>\n <ThermalZone>\n <Type>cpu</Type>\n <TripPoints>\n");
|
||||
|
||||
for (i, p) in profile.fan_curve.iter().enumerate() {
|
||||
xml.push_str(&format!(" <TripPoint>\n <SensorType>cpu</SensorType>\n <Temperature>{}</Temperature>\n <Type>Passive</Type>\n <ControlId>{}</ControlId>\n </TripPoint>\n", p.temp_on * 1000.0, i));
|
||||
}
|
||||
|
||||
xml.push_str(" </TripPoints>\n </ThermalZone>\n </ThermalZones>\n </Platform>\n</ThermalConfiguration>\n");
|
||||
fs::write(output_path, xml)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user