algocline_app/service/
status.rs1use algocline_engine::PendingFilter;
2
3use super::AppService;
4
5impl AppService {
6 pub async fn status(
26 &self,
27 session_id: Option<&str>,
28 pending_filter: Option<serde_json::Value>,
29 ) -> Result<String, String> {
30 let filter = self.resolve_pending_filter(pending_filter)?;
31 let snapshots = self.registry.list_snapshots(filter.as_ref()).await;
32
33 if let Some(sid) = session_id {
35 return match snapshots.get(sid) {
36 Some(snapshot) => {
37 let mut result = snapshot.clone();
38 if let Ok(strategies) = self.session_strategies.lock() {
40 if let Some(name) = strategies.get(sid) {
41 result["strategy"] = serde_json::json!(name);
42 }
43 }
44 result["session_id"] = serde_json::json!(sid);
45 serde_json::to_string_pretty(&result).map_err(|e| e.to_string())
46 }
47 None => Err(format!("session '{sid}' not found (may have completed)")),
48 };
49 }
50
51 if snapshots.is_empty() {
53 return Ok(serde_json::json!({
54 "active_sessions": 0,
55 "sessions": [],
56 })
57 .to_string());
58 }
59
60 let strategies = self.session_strategies.lock().ok();
61 let sessions: Vec<serde_json::Value> = snapshots
62 .into_iter()
63 .map(|(id, mut snapshot)| {
64 if let Some(ref strats) = strategies {
65 if let Some(name) = strats.get(&id) {
66 snapshot["strategy"] = serde_json::json!(name);
67 }
68 }
69 snapshot["session_id"] = serde_json::json!(id);
70 snapshot
71 })
72 .collect();
73
74 let result = serde_json::json!({
75 "active_sessions": sessions.len(),
76 "sessions": sessions,
77 });
78
79 serde_json::to_string_pretty(&result).map_err(|e| e.to_string())
80 }
81
82 fn resolve_pending_filter(
87 &self,
88 raw: Option<serde_json::Value>,
89 ) -> Result<Option<PendingFilter>, String> {
90 let Some(value) = raw else {
91 return Ok(None);
92 };
93 match value {
94 serde_json::Value::String(name) => PendingFilter::from_preset_with(
95 &name,
96 self.log_config.prompt_preview_chars,
97 )
98 .map(Some)
99 .ok_or_else(|| {
100 format!(
101 "unknown pending_filter preset '{name}' (valid: \"meta\" | \"preview\" | \"full\")"
102 )
103 }),
104 serde_json::Value::Object(_) => serde_json::from_value::<PendingFilter>(value)
105 .map(Some)
106 .map_err(|e| format!("invalid pending_filter object: {e}")),
107 other => Err(format!(
108 "pending_filter must be a preset name (string) or filter object, got {}",
109 match other {
110 serde_json::Value::Null => "null",
111 serde_json::Value::Bool(_) => "bool",
112 serde_json::Value::Number(_) => "number",
113 serde_json::Value::Array(_) => "array",
114 _ => "unknown",
115 }
116 )),
117 }
118 }
119}