@@ -7,13 +7,59 @@ const ANTHROPIC_ACTUAL_LIMIT =
77 process . env . VERTEX_ANTHROPIC_1M_CONTEXT === "true"
88 ? 1_000_000
99 : 200_000
10- const CONTEXT_WARNING_THRESHOLD = 0.70
1110
12- const CONTEXT_REMINDER = `${ createSystemDirective ( SystemDirectiveTypes . CONTEXT_WINDOW_MONITOR ) }
11+ const PROGRESSIVE_WARNING_THRESHOLDS = [ 0.50 , 0.60 , 0.70 , 0.80 ] as const
12+
13+ type ThresholdLevel = ( typeof PROGRESSIVE_WARNING_THRESHOLDS ) [ number ]
14+
15+ const ANSI = {
16+ RESET : "\x1b[0m" ,
17+ BOLD : "\x1b[1m" ,
18+ BLUE : "\x1b[34m" ,
19+ YELLOW : "\x1b[33m" ,
20+ ORANGE : "\x1b[38;5;208m" ,
21+ RED : "\x1b[31m" ,
22+ BG_BLUE : "\x1b[44m" ,
23+ BG_YELLOW : "\x1b[43m" ,
24+ BG_ORANGE : "\x1b[48;5;208m" ,
25+ BG_RED : "\x1b[41m" ,
26+ WHITE : "\x1b[37m" ,
27+ } as const
28+
29+ const THRESHOLD_CONFIG : Record < ThresholdLevel , { emoji : string ; urgency : string ; color : string ; bgColor : string } > = {
30+ 0.50 : { emoji : "📊" , urgency : "INFO" , color : ANSI . BLUE , bgColor : ANSI . BG_BLUE } ,
31+ 0.60 : { emoji : "📈" , urgency : "NOTICE" , color : ANSI . YELLOW , bgColor : ANSI . BG_YELLOW } ,
32+ 0.70 : { emoji : "⚠️" , urgency : "WARNING" , color : ANSI . ORANGE , bgColor : ANSI . BG_ORANGE } ,
33+ 0.80 : { emoji : "🚨" , urgency : "CRITICAL" , color : ANSI . RED , bgColor : ANSI . BG_RED } ,
34+ }
35+
36+ function createContextReminder ( threshold : ThresholdLevel ) : string {
37+ const { emoji, urgency, color, bgColor } = THRESHOLD_CONFIG [ threshold ]
38+ const baseReminder = createSystemDirective ( SystemDirectiveTypes . CONTEXT_WINDOW_MONITOR )
39+
40+ const coloredHeader = `${ bgColor } ${ ANSI . WHITE } ${ ANSI . BOLD } ${ emoji } [${ urgency } ] ${ ANSI . RESET } ${ color } `
41+
42+ if ( threshold >= 0.80 ) {
43+ return `${ baseReminder }
44+
45+ ${ coloredHeader } Context window is running LOW!
46+ Consider wrapping up current task or preparing for session handoff.
47+ Prioritize completing critical work before context limit is reached.${ ANSI . RESET } `
48+ }
49+
50+ if ( threshold >= 0.70 ) {
51+ return `${ baseReminder }
52+
53+ ${ coloredHeader } Context window usage is getting high.
54+ Continue working but be mindful of context consumption.
55+ Consider summarizing progress if approaching complex tasks.${ ANSI . RESET } `
56+ }
1357
14- You are using Anthropic Claude with 1M context window.
15- You have plenty of context remaining - do NOT rush or skip tasks.
16- Complete your work thoroughly and methodically.`
58+ return `${ baseReminder }
59+
60+ ${ coloredHeader } Context window checkpoint.
61+ You have sufficient context remaining - continue working normally.${ ANSI . RESET } `
62+ }
1763
1864interface AssistantMessageInfo {
1965 role : "assistant"
@@ -31,16 +77,14 @@ interface MessageWrapper {
3177}
3278
3379export function createContextWindowMonitorHook ( ctx : PluginInput ) {
34- const remindedSessions = new Set < string > ( )
80+ const notifiedThresholdsPerSession = new Map < string , Set < ThresholdLevel > > ( )
3581
3682 const toolExecuteAfter = async (
3783 input : { tool : string ; sessionID : string ; callID : string } ,
3884 output : { title : string ; output : string ; metadata : unknown }
3985 ) => {
4086 const { sessionID } = input
4187
42- if ( remindedSessions . has ( sessionID ) ) return
43-
4488 try {
4589 const response = await ctx . client . session . messages ( {
4690 path : { id : sessionID } ,
@@ -57,27 +101,39 @@ export function createContextWindowMonitorHook(ctx: PluginInput) {
57101 const lastAssistant = assistantMessages [ assistantMessages . length - 1 ]
58102 if ( lastAssistant . providerID !== "anthropic" ) return
59103
60- // Use only the last assistant message's input tokens
61- // This reflects the ACTUAL current context window usage (post-compaction)
62104 const lastTokens = lastAssistant . tokens
63105 const totalInputTokens = ( lastTokens ?. input ?? 0 ) + ( lastTokens ?. cache ?. read ?? 0 )
64-
65106 const actualUsagePercentage = totalInputTokens / ANTHROPIC_ACTUAL_LIMIT
66107
67- if ( actualUsagePercentage < CONTEXT_WARNING_THRESHOLD ) return
108+ if ( ! notifiedThresholdsPerSession . has ( sessionID ) ) {
109+ notifiedThresholdsPerSession . set ( sessionID , new Set ( ) )
110+ }
111+ const sessionNotified = notifiedThresholdsPerSession . get ( sessionID ) !
68112
69- remindedSessions . add ( sessionID )
113+ let thresholdToNotify : ThresholdLevel | null = null
114+ for ( const threshold of PROGRESSIVE_WARNING_THRESHOLDS ) {
115+ if ( actualUsagePercentage >= threshold && ! sessionNotified . has ( threshold ) ) {
116+ thresholdToNotify = threshold
117+ }
118+ }
119+
120+ if ( thresholdToNotify === null ) return
70121
122+ sessionNotified . add ( thresholdToNotify )
123+
124+ const { color } = THRESHOLD_CONFIG [ thresholdToNotify ]
71125 const displayUsagePercentage = totalInputTokens / ANTHROPIC_DISPLAY_LIMIT
72126 const usedPct = ( displayUsagePercentage * 100 ) . toFixed ( 1 )
73127 const remainingPct = ( ( 1 - displayUsagePercentage ) * 100 ) . toFixed ( 1 )
74128 const usedTokens = totalInputTokens . toLocaleString ( )
75129 const limitTokens = ANTHROPIC_DISPLAY_LIMIT . toLocaleString ( )
76130
77- output . output += `\n\n${ CONTEXT_REMINDER }
78- [Context Status: ${ usedPct } % used (${ usedTokens } /${ limitTokens } tokens), ${ remainingPct } % remaining]`
131+ const reminder = createContextReminder ( thresholdToNotify )
132+
133+ output . output += `\n\n${ reminder }
134+ ${ color } [Context Status: ${ usedPct } % used (${ usedTokens } /${ limitTokens } tokens), ${ remainingPct } % remaining]${ ANSI . RESET } `
79135 } catch {
80- // Graceful degradation - do not disrupt tool execution
136+ // Graceful degradation
81137 }
82138 }
83139
@@ -87,7 +143,7 @@ export function createContextWindowMonitorHook(ctx: PluginInput) {
87143 if ( event . type === "session.deleted" ) {
88144 const sessionInfo = props ?. info as { id ?: string } | undefined
89145 if ( sessionInfo ?. id ) {
90- remindedSessions . delete ( sessionInfo . id )
146+ notifiedThresholdsPerSession . delete ( sessionInfo . id )
91147 }
92148 }
93149 }
0 commit comments