fur_cli/commands/status/
core.rs1use serde_json::Value;
2use std::collections::HashMap;
3use std::fs;
4use std::path::Path;
5
6pub fn load_index_and_conversation(fur_dir: &Path) -> (Value, Value, String) {
7 let index_path = fur_dir.join("index.json");
8 let index: Value = read_json(&index_path);
9
10 let conversation_id = index["active_thread"].as_str().unwrap_or("");
11 let current = index["current_message"].as_str().unwrap_or("").to_string();
12
13 let convo_path = fur_dir
14 .join("threads")
15 .join(format!("{}.json", conversation_id));
16 let conversation: Value = read_json(&convo_path);
17
18 (index, conversation, current)
19}
20
21pub fn load_conversation_messages(fur_dir: &Path, conversation: &Value) -> HashMap<String, Value> {
23 let mut id_to_message = HashMap::new();
24
25 let mut stack: Vec<String> = conversation["messages"]
26 .as_array()
27 .unwrap_or(&vec![])
28 .iter()
29 .filter_map(|id| id.as_str().map(|s| s.to_string()))
30 .collect();
31
32 let messages_dir = fur_dir.join("messages");
33
34 while let Some(mid) = stack.pop() {
35 let msg_path = messages_dir.join(format!("{}.json", mid));
36
37 if let Some(content) = crate::security::io::read_text_file(&msg_path) {
38 if let Ok(mut obj) = serde_json::from_str::<Value>(&content) {
39 if crate::commands::jot::upgrade_message_schema(&mut obj) {
43 if let Ok(serialized) = serde_json::to_string_pretty(&obj) {
45 let _ = fs::write(&msg_path, serialized);
46 }
47 }
48
49 if let Some(children) = obj["children"].as_array() {
53 for c in children {
54 if let Some(cid) = c.as_str() {
55 stack.push(cid.to_string());
56 }
57 }
58 }
59
60 if let Some(blocks) = obj["branches"].as_array() {
64 for block in blocks {
65 if let Some(arr) = block.as_array() {
66 for c in arr {
67 if let Some(cid) = c.as_str() {
68 stack.push(cid.to_string());
69 }
70 }
71 }
72 }
73 }
74
75 id_to_message.insert(mid.clone(), obj);
76 }
77 }
78 }
79
80 id_to_message
81}
82
83pub fn first_message_fallback(conversation: &Value) -> String {
85 conversation["messages"]
86 .as_array()
87 .and_then(|arr| arr.get(0))
88 .and_then(|v| v.as_str())
89 .unwrap_or("")
90 .to_string()
91}
92
93fn read_json(path: &Path) -> Value {
94 use crate::security::io::read_text_file;
95
96 serde_json::from_str(&read_text_file(path).expect("❌ Project locked. Run `fur unlock`."))
97 .unwrap()
98}