lean_ctx/core/
host_state.rs1pub fn persist_detected_model(model: &str) {
13 if crate::core::model_registry::is_background_model(model) {
14 return;
15 }
16
17 let Ok(data_dir) = crate::core::data_dir::lean_ctx_data_dir() else {
18 return;
19 };
20 let path = data_dir.join("detected_model.json");
21 let ts = std::time::SystemTime::now()
22 .duration_since(std::time::UNIX_EPOCH)
23 .unwrap_or_default()
24 .as_secs();
25 let window = crate::core::model_registry::context_window_for_model(model);
26 let payload = serde_json::json!({
27 "model": model,
28 "window_size": window,
29 "detected_at": ts,
30 });
31 if let Ok(json) = serde_json::to_string_pretty(&payload) {
32 let tmp = path.with_extension("tmp");
33 if std::fs::write(&tmp, &json).is_ok() {
34 let _ = std::fs::rename(&tmp, &path);
35 }
36 }
37}
38
39pub fn load_detected_model() -> Option<(String, usize)> {
42 let data_dir = crate::core::data_dir::lean_ctx_data_dir().ok()?;
43 let path = data_dir.join("detected_model.json");
44 let content = std::fs::read_to_string(&path).ok()?;
45 let v: serde_json::Value = serde_json::from_str(&content).ok()?;
46 let model = v.get("model")?.as_str()?.to_string();
47 let window = v.get("window_size")?.as_u64()? as usize;
48 let detected_at = v.get("detected_at")?.as_u64()?;
49 let now = std::time::SystemTime::now()
50 .duration_since(std::time::UNIX_EPOCH)
51 .unwrap_or_default()
52 .as_secs();
53 if now.saturating_sub(detected_at) > 7200 {
54 return None;
55 }
56 Some((model, window))
57}
58
59pub fn persist_transcript_path(
62 path: &str,
63 conversation_id: Option<&str>,
64 session_id: Option<&str>,
65) {
66 let Ok(data_dir) = crate::core::data_dir::lean_ctx_data_dir() else {
67 return;
68 };
69 let meta_path = data_dir.join("active_transcript.json");
70 let ts = std::time::SystemTime::now()
71 .duration_since(std::time::UNIX_EPOCH)
72 .unwrap_or_default()
73 .as_secs();
74 let payload = serde_json::json!({
75 "transcript_path": path,
76 "conversation_id": conversation_id,
77 "session_id": session_id,
78 "updated_at": ts,
79 });
80 if let Ok(json) = serde_json::to_string_pretty(&payload) {
81 let tmp = meta_path.with_extension("tmp");
82 if std::fs::write(&tmp, &json).is_ok() {
83 let _ = std::fs::rename(&tmp, &meta_path);
84 }
85 }
86}
87
88pub fn load_active_transcript() -> Option<(String, Option<String>)> {
89 let data_dir = crate::core::data_dir::lean_ctx_data_dir().ok()?;
90 let path = data_dir.join("active_transcript.json");
91 let content = std::fs::read_to_string(&path).ok()?;
92 let v: serde_json::Value = serde_json::from_str(&content).ok()?;
93 let tp = v.get("transcript_path")?.as_str()?.to_string();
94 let conv = v
98 .get("conversation_id")
99 .and_then(|c| c.as_str())
100 .or_else(|| v.get("session_id").and_then(|s| s.as_str()))
101 .map(String::from);
102 let updated = v.get("updated_at")?.as_u64()?;
103 let now = std::time::SystemTime::now()
104 .duration_since(std::time::UNIX_EPOCH)
105 .unwrap_or_default()
106 .as_secs();
107 if now.saturating_sub(updated) > 7200 {
108 return None;
109 }
110 Some((tp, conv))
111}