@@ -6,8 +6,8 @@ import { ChatMessage, ToolResult, ToolResultStatus, ToolUse } from '@amzn/codewh
66import { randomUUID } from '../../shared/crypto'
77import { getLogger } from '../../shared/logger/logger'
88
9- // Maximum number of messages to keep in history
10- const MaxConversationHistoryLength = 100
9+ // Maximum number of characters to keep in history
10+ const MaxConversationHistoryCharacters = 600_000
1111
1212/**
1313 * ChatHistoryManager handles the storage and manipulation of chat history
@@ -118,22 +118,68 @@ export class ChatHistoryManager {
118118 this . clearRecentHistory ( )
119119 }
120120
121- if ( this . history . length <= MaxConversationHistoryLength ) {
122- return
121+ // Check if we need to trim based on character count
122+ const totalCharacters = this . calculateHistoryCharacterCount ( )
123+ if ( totalCharacters > MaxConversationHistoryCharacters ) {
124+ this . logger . debug (
125+ `History size (${ totalCharacters } chars) exceeds limit of ${ MaxConversationHistoryCharacters } chars`
126+ )
127+ // Keep removing messages from the beginning until we're under the limit
128+ while (
129+ this . calculateHistoryCharacterCount ( ) > MaxConversationHistoryCharacters &&
130+ this . history . length > 2
131+ ) {
132+ // Find the next valid user message to start from
133+ const indexToTrim = this . findIndexToTrim ( )
134+ if ( indexToTrim !== undefined && indexToTrim > 0 ) {
135+ this . logger . debug (
136+ `Removing the first ${ indexToTrim } elements in the history due to character count limit`
137+ )
138+ this . history . splice ( 0 , indexToTrim )
139+ } else {
140+ // If we can't find a valid starting point, remove the oldest message
141+ this . logger . debug ( 'Removing oldest message to reduce character count' )
142+ this . history . shift ( )
143+ }
144+ }
123145 }
146+ }
124147
125- const indexToTrim = this . findIndexToTrim ( )
126- if ( indexToTrim !== undefined ) {
127- this . logger . debug ( `Removing the first ${ indexToTrim } elements in the history` )
128- this . history . splice ( 0 , indexToTrim )
129- } else {
130- this . logger . debug ( 'No valid starting user message found in the history, clearing' )
131- this . history = [ ]
148+ private calculateHistoryCharacterCount ( ) : number {
149+ let count = 0
150+ for ( const message of this . history ) {
151+ // Count characters in user messages
152+ if ( message . userInputMessage ?. content ) {
153+ count += message . userInputMessage . content . length
154+ }
155+
156+ // Count characters in assistant messages
157+ if ( message . assistantResponseMessage ?. content ) {
158+ count += message . assistantResponseMessage . content . length
159+ }
160+
161+ try {
162+ // Count characters in tool uses and results
163+ if ( message . assistantResponseMessage ?. toolUses ) {
164+ for ( const toolUse of message . assistantResponseMessage . toolUses ) {
165+ count += JSON . stringify ( toolUse ) . length
166+ }
167+ }
168+
169+ if ( message . userInputMessage ?. userInputMessageContext ?. toolResults ) {
170+ for ( const toolResult of message . userInputMessage . userInputMessageContext . toolResults ) {
171+ count += JSON . stringify ( toolResult ) . length
172+ }
173+ }
174+ } catch ( error : any ) {
175+ this . logger . error ( `Error calculating character count for tool uses/results: ${ error . message } ` )
176+ }
132177 }
178+ return count
133179 }
134180
135181 private findIndexToTrim ( ) : number | undefined {
136- for ( let i = 1 ; i < this . history . length ; i ++ ) {
182+ for ( let i = 2 ; i < this . history . length ; i ++ ) {
137183 const message = this . history [ i ]
138184 if ( this . isValidUserMessageWithoutToolResults ( message ) ) {
139185 return i
0 commit comments