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