1+ import re
12import shutil
23import sys
34
5+ from datetime import datetime
46from pathlib import Path
57from queue import Queue
6- from typing import TYPE_CHECKING
78
89from memos .configs .mem_cube import GeneralMemCubeConfig
910from memos .configs .mem_os import MOSConfig
1213from memos .mem_cube .general import GeneralMemCube
1314from memos .mem_os .main import MOS
1415from memos .mem_scheduler .general_scheduler import GeneralScheduler
15-
16-
17- if TYPE_CHECKING :
18- from memos .mem_scheduler .schemas .message_schemas import (
19- ScheduleLogForWebItem ,
20- )
16+ from memos .mem_scheduler .schemas .general_schemas import (
17+ ADD_LABEL ,
18+ ANSWER_LABEL ,
19+ MEM_ARCHIVE_LABEL ,
20+ MEM_ORGANIZE_LABEL ,
21+ MEM_UPDATE_LABEL ,
22+ QUERY_LABEL ,
23+ )
24+ from memos .mem_scheduler .schemas .message_schemas import ScheduleLogForWebItem
25+ from memos .mem_scheduler .utils .filter_utils import transform_name_to_key
2126
2227
2328FILE_PATH = Path (__file__ ).absolute ()
@@ -70,6 +75,91 @@ def init_task():
7075 return conversations , questions
7176
7277
78+ def _truncate_with_rules (text : str ) -> str :
79+ has_cjk = bool (re .search (r"[\u4e00-\u9fff]" , text ))
80+ limit = 32 if has_cjk else 64
81+ normalized = text .strip ().replace ("\n " , " " )
82+ if len (normalized ) <= limit :
83+ return normalized
84+ return normalized [:limit ] + "..."
85+
86+
87+ def _format_title (ts : datetime , title_text : str ) -> str :
88+ return f"{ ts .astimezone ().strftime ('%H:%M:%S' )} { title_text } "
89+
90+
91+ def _cube_display_from (mem_cube_id : str ) -> str :
92+ if "public" in (mem_cube_id or "" ).lower ():
93+ return "PublicMemCube"
94+ return "UserMemCube"
95+
96+
97+ _TYPE_SHORT = {
98+ "LongTermMemory" : "LTM" ,
99+ "UserMemory" : "User" ,
100+ "WorkingMemory" : "Working" ,
101+ "ActivationMemory" : "Activation" ,
102+ "ParameterMemory" : "Parameter" ,
103+ "TextMemory" : "Text" ,
104+ "UserInput" : "Input" ,
105+ "NotApplicable" : "NA" ,
106+ }
107+
108+
109+ def _format_entry (item : ScheduleLogForWebItem ) -> tuple [str , str ]:
110+ cube_display = getattr (item , "memcube_name" , None ) or _cube_display_from (item .mem_cube_id )
111+ label = item .label
112+ content = item .log_content or ""
113+ memcube_content = getattr (item , "memcube_log_content" , None ) or []
114+ memory_len = getattr (item , "memory_len" , None ) or len (memcube_content ) or 1
115+
116+ def _first_content () -> str :
117+ if memcube_content :
118+ return memcube_content [0 ].get ("content" , "" ) or content
119+ return content
120+
121+ if label in ("addMessage" , QUERY_LABEL , ANSWER_LABEL ):
122+ target_cube = cube_display .replace ("MemCube" , "" )
123+ title = _format_title (item .timestamp , f"addMessages to { target_cube } MemCube" )
124+ return title , _truncate_with_rules (_first_content ())
125+
126+ if label in ("addMemory" , ADD_LABEL ):
127+ title = _format_title (item .timestamp , f"{ cube_display } added { memory_len } memories" )
128+ return title , _truncate_with_rules (_first_content ())
129+
130+ if label in ("updateMemory" , MEM_UPDATE_LABEL ):
131+ title = _format_title (item .timestamp , f"{ cube_display } updated { memory_len } memories" )
132+ return title , _truncate_with_rules (_first_content ())
133+
134+ if label in ("archiveMemory" , MEM_ARCHIVE_LABEL ):
135+ title = _format_title (item .timestamp , f"{ cube_display } archived { memory_len } memories" )
136+ return title , _truncate_with_rules (_first_content ())
137+
138+ if label in ("mergeMemory" , MEM_ORGANIZE_LABEL ):
139+ title = _format_title (item .timestamp , f"{ cube_display } merged { memory_len } memories" )
140+ merged = [c for c in memcube_content if c .get ("type" ) == "merged" ]
141+ post = [c for c in memcube_content if c .get ("type" ) == "postMerge" ]
142+ parts = []
143+ if merged :
144+ parts .append ("Merged: " + " | " .join (c .get ("content" , "" ) for c in merged ))
145+ if post :
146+ parts .append ("Result: " + " | " .join (c .get ("content" , "" ) for c in post ))
147+ detail = " " .join (parts ) if parts else _first_content ()
148+ return title , _truncate_with_rules (detail )
149+
150+ if label == "scheduleMemory" :
151+ title = _format_title (item .timestamp , f"{ cube_display } scheduled { memory_len } memories" )
152+ if memcube_content :
153+ return title , _truncate_with_rules (memcube_content [0 ].get ("content" , "" ))
154+ key = transform_name_to_key (content )
155+ from_short = _TYPE_SHORT .get (item .from_memory_type , item .from_memory_type )
156+ to_short = _TYPE_SHORT .get (item .to_memory_type , item .to_memory_type )
157+ return title , _truncate_with_rules (f"[{ from_short } →{ to_short } ] { key } : { content } " )
158+
159+ title = _format_title (item .timestamp , f"{ cube_display } event" )
160+ return title , _truncate_with_rules (_first_content ())
161+
162+
73163def show_web_logs (mem_scheduler : GeneralScheduler ):
74164 """Display all web log entries from the scheduler's log queue.
75165
@@ -84,24 +174,25 @@ def show_web_logs(mem_scheduler: GeneralScheduler):
84174
85175 # Create a temporary queue to preserve the original queue contents
86176 temp_queue = Queue ()
87- log_count = 0
177+ collected : list [ ScheduleLogForWebItem ] = []
88178
89179 while not mem_scheduler ._web_log_message_queue .empty ():
90180 log_item : ScheduleLogForWebItem = mem_scheduler ._web_log_message_queue .get ()
181+ collected .append (log_item )
91182 temp_queue .put (log_item )
92- log_count += 1
93-
94- # Print log entry details
95- print (f"\n Log Entry #{ log_count } :" )
96- print (f'- "{ log_item .label } " log: { log_item } ' )
97183
184+ for idx , log_item in enumerate (sorted (collected , key = lambda x : x .timestamp , reverse = True ), 1 ):
185+ title , content = _format_entry (log_item )
186+ print (f"\n Log Entry #{ idx } :" )
187+ print (title )
188+ print (content )
98189 print ("-" * 50 )
99190
100191 # Restore items back to the original queue
101192 while not temp_queue .empty ():
102193 mem_scheduler ._web_log_message_queue .put (temp_queue .get ())
103194
104- print (f"\n Total { log_count } web log entries displayed." )
195+ print (f"\n Total { len ( collected ) } web log entries displayed." )
105196 print ("=" * 110 + "\n " )
106197
107198
0 commit comments