11use std:: fs;
2- use std:: path:: { Path , PathBuf } ;
2+ use std:: path:: { Path } ;
33use serde_json:: { Value , json} ;
44use clap:: Parser ;
55use chrono:: { DateTime , Local , Utc } ;
@@ -40,6 +40,8 @@ pub fn run_conversation(args: ThreadArgs) {
4040 let mut rows = Vec :: new ( ) ;
4141 let mut active_idx = None ;
4242
43+ let mut total_size_bytes: u64 = 0 ;
44+
4345 // Collect conversation metadata first
4446 let mut conversation_info = Vec :: new ( ) ;
4547 for tid in threads {
@@ -56,7 +58,11 @@ pub fn run_conversation(args: ThreadArgs) {
5658 conversation_json[ "created_at" ] . as_str ( ) . unwrap_or ( "" ) ;
5759 let msg_ids = conversation_json[ "messages" ]
5860 . as_array ( )
59- . map ( |a| a. iter ( ) . filter_map ( |v| v. as_str ( ) . map ( |s| s. to_string ( ) ) ) . collect :: < Vec < _ > > ( ) )
61+ . map ( |a| {
62+ a. iter ( )
63+ . filter_map ( |v| v. as_str ( ) . map ( |s| s. to_string ( ) ) )
64+ . collect :: < Vec < _ > > ( )
65+ } )
6066 . unwrap_or_default ( ) ;
6167
6268 let msg_count = msg_ids. len ( ) ;
@@ -72,9 +78,12 @@ pub fn run_conversation(args: ThreadArgs) {
7278 let time_str = local_time. format ( "%H:%M" ) . to_string ( ) ;
7379
7480 // Compute total footprint (JSON + markdown attachments)
75- let size_bytes = compute_conversation_size ( fur_dir, tid_str, & msg_ids) ;
76- let size_mb =
77- ( size_bytes as f64 / ( 1024.0 * 1024.0 ) ) . min ( 9999.0 ) ;
81+ let size_bytes =
82+ compute_conversation_size ( fur_dir, tid_str, & msg_ids) ;
83+
84+ total_size_bytes += size_bytes;
85+
86+ let size_str = format_size ( size_bytes) ;
7887
7988 conversation_info. push ( (
8089 tid_str. to_string ( ) ,
@@ -83,7 +92,7 @@ pub fn run_conversation(args: ThreadArgs) {
8392 time_str,
8493 msg_count,
8594 parsed_time,
86- size_mb ,
95+ size_str ,
8796 ) ) ;
8897 }
8998 }
@@ -94,7 +103,7 @@ pub fn run_conversation(args: ThreadArgs) {
94103 conversation_info. sort_by ( |a, b| b. 5 . cmp ( & a. 5 ) ) ;
95104
96105 // Build rows and track active index
97- for ( i, ( tid, title, date, time, msg_count, _, size_mb ) ) in
106+ for ( i, ( tid, title, date, time, msg_count, _, size_str ) ) in
98107 conversation_info. iter ( ) . enumerate ( )
99108 {
100109 let short_id = & tid[ ..8 ] ;
@@ -104,7 +113,7 @@ pub fn run_conversation(args: ThreadArgs) {
104113 title. to_string( ) ,
105114 format!( "{} | {}" , date, time) ,
106115 msg_count. to_string( ) ,
107- format! ( "{:.2} MB" , size_mb ) ,
116+ size_str . to_string ( ) ,
108117 ] ) ;
109118
110119 if tid == active {
@@ -119,6 +128,10 @@ pub fn run_conversation(args: ThreadArgs) {
119128 active_idx,
120129 ) ;
121130
131+ let total_size_str = format_size ( total_size_bytes) ;
132+ println ! ( "----------------------------" ) ;
133+ println ! ( "Total Memory Used: {}" , total_size_str) ;
134+
122135 return ;
123136 }
124137
@@ -191,7 +204,7 @@ fn compute_conversation_size(
191204 let convo_path = fur_dir. join ( "threads" ) . join ( format ! ( "{}.json" , tid) ) ;
192205 total += file_size ( & convo_path) ;
193206
194- // Add all messages JSON
207+ // Add all messages + markdowns
195208 total += get_message_file_sizes ( fur_dir, msg_ids) ;
196209
197210 total
@@ -201,16 +214,25 @@ fn get_message_file_sizes(fur_dir: &Path, msg_ids: &[String]) -> u64 {
201214 let mut total = 0 ;
202215
203216 for mid in msg_ids {
204- // message JSON
205217 let msg_path = fur_dir. join ( "messages" ) . join ( format ! ( "{}.json" , mid) ) ;
206218 total += file_size ( & msg_path) ;
207219
208- // check for markdown pointer inside JSON
220+ // Parse JSON to find ONLY message["markdown"]
209221 if let Ok ( content) = fs:: read_to_string ( & msg_path) {
210222 if let Ok ( json) = serde_json:: from_str :: < Value > ( & content) {
211- if let Some ( markdown_rel) = json[ "markdown" ] . as_str ( ) {
212- let md_path = fur_dir. join ( markdown_rel) ;
213- total += file_size ( & md_path) ;
223+
224+ if let Some ( md_raw) = json[ "markdown" ] . as_str ( ) {
225+
226+ // CASE 1: absolute path -> use as-is
227+ let md_path = Path :: new ( md_raw) ;
228+ if md_path. is_absolute ( ) {
229+ total += file_size ( md_path) ;
230+ continue ;
231+ }
232+
233+ // CASE 2: relative path -> resolve relative to project root
234+ let project_root_path = Path :: new ( "." ) . join ( md_raw) ;
235+ total += file_size ( & project_root_path) ;
214236 }
215237 }
216238 }
@@ -219,6 +241,14 @@ fn get_message_file_sizes(fur_dir: &Path, msg_ids: &[String]) -> u64 {
219241 total
220242}
221243
222- fn file_size ( path : & PathBuf ) -> u64 {
244+ fn file_size ( path : & Path ) -> u64 {
223245 fs:: metadata ( path) . map ( |m| m. len ( ) ) . unwrap_or ( 0 )
224246}
247+
248+ pub fn format_size ( bytes : u64 ) -> String {
249+ if bytes < 1_048_576 {
250+ format ! ( "{} KB" , ( bytes as f64 / 1024.0 ) . round( ) as u64 )
251+ } else {
252+ format ! ( "{:.2} MB" , bytes as f64 / ( 1024.0 * 1024.0 ) )
253+ }
254+ }
0 commit comments