1010import pytz
1111
1212from usage_analyzer .api import analyze_usage
13- from check_dependency import test_node , test_npx
1413
1514# All internal calculations use UTC, display timezone is configurable
1615UTC_TZ = pytz .UTC
1716
17+ # Notification persistence configuration
18+ NOTIFICATION_MIN_DURATION = 5 # seconds - minimum time to display notifications
19+
20+ # Global notification state tracker
21+ notification_states = {
22+ 'switch_to_custom' : {'triggered' : False , 'timestamp' : None },
23+ 'exceed_max_limit' : {'triggered' : False , 'timestamp' : None },
24+ 'tokens_will_run_out' : {'triggered' : False , 'timestamp' : None }
25+ }
26+
27+ def update_notification_state (notification_type , condition_met , current_time ):
28+ """Update notification state and return whether to show notification."""
29+ state = notification_states [notification_type ]
30+
31+ if condition_met :
32+ if not state ['triggered' ]:
33+ # First time triggering - record timestamp
34+ state ['triggered' ] = True
35+ state ['timestamp' ] = current_time
36+ return True
37+ else :
38+ if state ['triggered' ]:
39+ # Check if minimum duration has passed
40+ elapsed = (current_time - state ['timestamp' ]).total_seconds ()
41+ if elapsed >= NOTIFICATION_MIN_DURATION :
42+ # Reset state after minimum duration
43+ state ['triggered' ] = False
44+ state ['timestamp' ] = None
45+ return False
46+ else :
47+ # Still within minimum duration - keep showing
48+ return True
49+ return False
50+
1851# Terminal handling for Unix-like systems
1952try :
2053 import termios
@@ -221,20 +254,20 @@ def parse_args():
221254
222255
223256def get_token_limit (plan , blocks = None ):
257+ # TODO calculate old based on limits
258+ limits = {"pro" : 44000 , "max5" : 220000 , "max20" : 880000 }
259+
224260 """Get token limit based on plan type."""
225261 if plan == "custom_max" and blocks :
226- # Find the highest token count from all previous blocks
227262 max_tokens = 0
228263 for block in blocks :
229264 if not block .get ("isGap" , False ) and not block .get ("isActive" , False ):
230265 tokens = block .get ("totalTokens" , 0 )
231266 if tokens > max_tokens :
232267 max_tokens = tokens
233- # Return the highest found, or default to pro if none found
234- return max_tokens if max_tokens > 0 else 7000
268+ return max_tokens if max_tokens > 0 else limits ["pro" ]
235269
236- limits = {"pro" : 7000 , "max5" : 35000 , "max20" : 140000 }
237- return limits .get (plan , 7000 )
270+ return limits .get (plan , 44000 )
238271
239272
240273def setup_terminal ():
@@ -277,8 +310,6 @@ def flush_input():
277310
278311def main ():
279312 """Main monitoring loop."""
280- test_node ()
281- test_npx ()
282313 args = parse_args ()
283314
284315 # Define color codes at the beginning to ensure they're available in exception handlers
@@ -393,10 +424,13 @@ def main():
393424
394425 # Extract data from active block
395426 tokens_used = active_block .get ("totalTokens" , 0 )
427+
428+ # Store original limit for notification
429+ original_limit = get_token_limit (args .plan )
396430
397431 # Check if tokens exceed limit and switch to custom_max if needed
398- if tokens_used > token_limit and args .plan == "pro " :
399- # Auto-switch to custom_max when pro limit is exceeded
432+ if tokens_used > token_limit and args .plan != "custom_max " :
433+ # Auto-switch to custom_max when any plan limit is exceeded
400434 new_limit = get_token_limit ("custom_max" , data ["blocks" ])
401435 if new_limit > token_limit :
402436 token_limit = new_limit
@@ -501,18 +535,21 @@ def main():
501535 screen_buffer .append (f"🔄 { white } Token Reset:{ reset } { reset_time_str } " )
502536 screen_buffer .append ("" )
503537
504- # Show notification if we switched to custom_max
505- show_switch_notification = False
506- if tokens_used > 7000 and args .plan == "pro" and token_limit > 7000 :
507- show_switch_notification = True
508-
509- # Notification when tokens exceed max limit
510- show_exceed_notification = tokens_used > token_limit
538+ # Update persistent notifications using current conditions
539+ show_switch_notification = update_notification_state (
540+ 'switch_to_custom' , token_limit > original_limit , current_time
541+ )
542+ show_exceed_notification = update_notification_state (
543+ 'exceed_max_limit' , tokens_used > token_limit , current_time
544+ )
545+ show_tokens_will_run_out = update_notification_state (
546+ 'tokens_will_run_out' , predicted_end_time < reset_time , current_time
547+ )
511548
512- # Show notifications
549+ # Display persistent notifications
513550 if show_switch_notification :
514551 screen_buffer .append (
515- f"🔄 { yellow } Tokens exceeded Pro limit - switched to custom_max ({ token_limit :,} ){ reset } "
552+ f"🔄 { yellow } Tokens exceeded { args . plan . upper () } limit - switched to custom_max ({ token_limit :,} ){ reset } "
516553 )
517554 screen_buffer .append ("" )
518555
@@ -522,8 +559,7 @@ def main():
522559 )
523560 screen_buffer .append ("" )
524561
525- # Warning if tokens will run out before reset
526- if predicted_end_time < reset_time :
562+ if show_tokens_will_run_out :
527563 screen_buffer .append (
528564 f"⚠️ { red } Tokens will run out BEFORE reset!{ reset } "
529565 )
0 commit comments