steer_core/
preferences.rs1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3use strum::Display;
4
5#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Default, Display)]
6#[strum(serialize_all = "kebab-case")]
7pub enum EditingMode {
8 #[default]
9 Simple, Vim, }
12
13#[derive(Debug, Clone, Serialize, Deserialize, Default)]
14pub struct Preferences {
15 #[serde(default)]
16 pub ui: UiPreferences,
17
18 #[serde(default)]
19 pub tools: ToolPreferences,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, Default)]
23pub struct UiPreferences {
24 pub default_model: Option<String>,
25 pub theme: Option<String>,
26 pub notifications: NotificationPreferences,
27 pub history_limit: Option<usize>,
28 pub provider_priority: Option<Vec<String>>,
29 #[serde(default)]
30 pub editing_mode: EditingMode,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct NotificationPreferences {
35 pub sound: bool,
36 pub desktop: bool,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize, Default)]
40pub struct ToolPreferences {
41 pub pre_approved: Vec<String>,
42}
43
44impl Default for NotificationPreferences {
45 fn default() -> Self {
46 Self {
47 sound: true,
48 desktop: true,
49 }
50 }
51}
52
53impl Preferences {
54 pub fn config_path() -> Result<PathBuf, crate::error::Error> {
56 let config_dir = dirs::config_dir().ok_or_else(|| {
57 crate::error::Error::Configuration("Could not determine config directory".to_string())
58 })?;
59 Ok(config_dir.join("steer").join("preferences.toml"))
60 }
61
62 pub fn load() -> Result<Self, crate::error::Error> {
64 let path = Self::config_path()?;
65
66 if path.exists() {
67 let contents = std::fs::read_to_string(&path)?;
68 match toml::from_str(&contents) {
69 Ok(prefs) => Ok(prefs),
70 Err(e) => {
71 tracing::warn!(
72 "Failed to parse preferences file at {:?}: {}. Using defaults.",
73 path,
74 e
75 );
76 Ok(Self::default())
77 }
78 }
79 } else {
80 Ok(Self::default())
81 }
82 }
83
84 pub fn save(&self) -> Result<(), crate::error::Error> {
86 let path = Self::config_path()?;
87
88 if let Some(parent) = path.parent() {
90 std::fs::create_dir_all(parent)?;
91 }
92
93 let contents = toml::to_string_pretty(self).map_err(|e| {
94 crate::error::Error::Configuration(format!("Failed to serialize preferences: {e}"))
95 })?;
96
97 std::fs::write(&path, contents)?;
98
99 Ok(())
100 }
101}