1use axum::{extract::State, http::StatusCode, response::Json};
2use serde::{Deserialize, Serialize};
3use serde_json::{json, Value};
4
5use super::AppState;
6use crate::memory::{MemoryPatternType, SilentHarvesterConfig};
7
8#[derive(Debug, Serialize, Deserialize)]
9pub struct HarvesterConfigResponse {
10 pub enabled: bool,
11 pub confidence_threshold: f64,
12 pub deduplication_threshold: f64,
13 pub message_trigger_count: usize,
14 pub time_trigger_minutes: u64,
15 pub max_batch_size: usize,
16 pub max_processing_time_seconds: u64,
17 pub silent_mode: bool,
18 pub privacy_mode: bool,
19 pub pattern_types: Vec<PatternTypeConfig>,
20 pub harvest_frequency: HarvestFrequency,
21}
22
23#[derive(Debug, Serialize, Deserialize)]
24pub struct PatternTypeConfig {
25 pub pattern_type: MemoryPatternType,
26 pub enabled: bool,
27 pub patterns: Vec<String>,
28 pub description: String,
29}
30
31#[derive(Debug, Serialize, Deserialize)]
32pub struct HarvestFrequency {
33 pub message_count: usize,
34 pub time_minutes: u64,
35}
36
37#[derive(Debug, Deserialize)]
38pub struct UpdateConfigRequest {
39 pub enabled: Option<bool>,
40 pub confidence_threshold: Option<f64>,
41 pub deduplication_threshold: Option<f64>,
42 pub message_trigger_count: Option<usize>,
43 pub time_trigger_minutes: Option<u64>,
44 pub max_batch_size: Option<usize>,
45 pub silent_mode: Option<bool>,
46 pub privacy_mode: Option<bool>,
47 pub pattern_types: Option<Vec<PatternTypeConfig>>,
48}
49
50pub async fn get_harvester_config(
52 State(state): State<AppState>,
53) -> Result<Json<HarvesterConfigResponse>, StatusCode> {
54 let config = get_current_config(&state).await?;
55
56 let pattern_types = vec![
57 PatternTypeConfig {
58 pattern_type: MemoryPatternType::Preference,
59 enabled: true,
60 patterns: config.pattern_config.preference_patterns.clone(),
61 description: "User preferences and likes/dislikes".to_string(),
62 },
63 PatternTypeConfig {
64 pattern_type: MemoryPatternType::Fact,
65 enabled: true,
66 patterns: config.pattern_config.fact_patterns.clone(),
67 description: "Personal facts and biographical information".to_string(),
68 },
69 PatternTypeConfig {
70 pattern_type: MemoryPatternType::Decision,
71 enabled: true,
72 patterns: config.pattern_config.decision_patterns.clone(),
73 description: "Decisions and choices made by the user".to_string(),
74 },
75 PatternTypeConfig {
76 pattern_type: MemoryPatternType::Correction,
77 enabled: true,
78 patterns: config.pattern_config.correction_patterns.clone(),
79 description: "Corrections and clarifications".to_string(),
80 },
81 PatternTypeConfig {
82 pattern_type: MemoryPatternType::Emotion,
83 enabled: true,
84 patterns: config.pattern_config.emotion_patterns.clone(),
85 description: "Emotional expressions and feelings".to_string(),
86 },
87 PatternTypeConfig {
88 pattern_type: MemoryPatternType::Goal,
89 enabled: true,
90 patterns: config.pattern_config.goal_patterns.clone(),
91 description: "Goals and aspirations".to_string(),
92 },
93 PatternTypeConfig {
94 pattern_type: MemoryPatternType::Relationship,
95 enabled: true,
96 patterns: config.pattern_config.relationship_patterns.clone(),
97 description: "Relationships and social connections".to_string(),
98 },
99 PatternTypeConfig {
100 pattern_type: MemoryPatternType::Skill,
101 enabled: true,
102 patterns: config.pattern_config.skill_patterns.clone(),
103 description: "Skills and abilities".to_string(),
104 },
105 ];
106
107 let response = HarvesterConfigResponse {
108 enabled: !config.silent_mode, confidence_threshold: config.confidence_threshold,
110 deduplication_threshold: config.deduplication_threshold,
111 message_trigger_count: config.message_trigger_count,
112 time_trigger_minutes: config.time_trigger_minutes,
113 max_batch_size: config.max_batch_size,
114 max_processing_time_seconds: config.max_processing_time_seconds,
115 silent_mode: config.silent_mode,
116 privacy_mode: false, pattern_types,
118 harvest_frequency: HarvestFrequency {
119 message_count: config.message_trigger_count,
120 time_minutes: config.time_trigger_minutes,
121 },
122 };
123
124 Ok(Json(response))
125}
126
127pub async fn update_harvester_config(
129 State(state): State<AppState>,
130 Json(update): Json<UpdateConfigRequest>,
131) -> Result<Json<Value>, StatusCode> {
132 let mut config = get_current_config(&state).await?;
133
134 if let Some(enabled) = update.enabled {
136 config.silent_mode = !enabled; }
138
139 if let Some(threshold) = update.confidence_threshold {
140 if threshold >= 0.5 && threshold <= 0.9 {
141 config.confidence_threshold = threshold;
142 } else {
143 return Err(StatusCode::BAD_REQUEST);
144 }
145 }
146
147 if let Some(threshold) = update.deduplication_threshold {
148 if threshold >= 0.5 && threshold <= 1.0 {
149 config.deduplication_threshold = threshold;
150 } else {
151 return Err(StatusCode::BAD_REQUEST);
152 }
153 }
154
155 if let Some(count) = update.message_trigger_count {
156 if count > 0 && count <= 1000 {
157 config.message_trigger_count = count;
158 } else {
159 return Err(StatusCode::BAD_REQUEST);
160 }
161 }
162
163 if let Some(minutes) = update.time_trigger_minutes {
164 if minutes > 0 && minutes <= 1440 {
165 config.time_trigger_minutes = minutes;
167 } else {
168 return Err(StatusCode::BAD_REQUEST);
169 }
170 }
171
172 if let Some(batch_size) = update.max_batch_size {
173 if batch_size > 0 && batch_size <= 1000 {
174 config.max_batch_size = batch_size;
175 } else {
176 return Err(StatusCode::BAD_REQUEST);
177 }
178 }
179
180 if let Some(silent_mode) = update.silent_mode {
181 config.silent_mode = silent_mode;
182 }
183
184 if let Some(pattern_types) = update.pattern_types {
186 for pattern_type in pattern_types {
187 match pattern_type.pattern_type {
188 MemoryPatternType::Preference => {
189 if pattern_type.enabled {
190 config.pattern_config.preference_patterns = pattern_type.patterns;
191 }
192 }
193 MemoryPatternType::Fact => {
194 if pattern_type.enabled {
195 config.pattern_config.fact_patterns = pattern_type.patterns;
196 }
197 }
198 MemoryPatternType::Decision => {
199 if pattern_type.enabled {
200 config.pattern_config.decision_patterns = pattern_type.patterns;
201 }
202 }
203 MemoryPatternType::Correction => {
204 if pattern_type.enabled {
205 config.pattern_config.correction_patterns = pattern_type.patterns;
206 }
207 }
208 MemoryPatternType::Emotion => {
209 if pattern_type.enabled {
210 config.pattern_config.emotion_patterns = pattern_type.patterns;
211 }
212 }
213 MemoryPatternType::Goal => {
214 if pattern_type.enabled {
215 config.pattern_config.goal_patterns = pattern_type.patterns;
216 }
217 }
218 MemoryPatternType::Relationship => {
219 if pattern_type.enabled {
220 config.pattern_config.relationship_patterns = pattern_type.patterns;
221 }
222 }
223 MemoryPatternType::Skill => {
224 if pattern_type.enabled {
225 config.pattern_config.skill_patterns = pattern_type.patterns;
226 }
227 }
228 }
229 }
230 }
231
232 save_config(&state, &config).await?;
234
235 Ok(Json(json!({
236 "status": "success",
237 "message": "Configuration updated successfully",
238 "applied_immediately": true
239 })))
240}
241
242async fn get_current_config(state: &AppState) -> Result<SilentHarvesterConfig, StatusCode> {
243 Ok(SilentHarvesterConfig::default())
246}
247
248async fn save_config(state: &AppState, config: &SilentHarvesterConfig) -> Result<(), StatusCode> {
249 tracing::info!("Configuration update requested (persistence not yet implemented)");
252 Ok(())
253}