@@ -634,6 +634,50 @@ export class ChatDatabase {
634634 }
635635 }
636636
637+ /**
638+ * Replace history with summary/dummyResponse pair within a specified tab.
639+ *
640+ * This method manages chat messages by creating a new history with compacted summary and dummy response pairs
641+ */
642+ replaceHistory ( tabId : string , tabType : TabType , conversationId : string , messages : Message [ ] ) {
643+ if ( this . isInitialized ( ) ) {
644+ const clientType = this . #features. lsp . getClientInitializeParams ( ) ?. clientInfo ?. name || 'unknown'
645+ const tabCollection = this . #db. getCollection < Tab > ( TabCollection )
646+
647+ this . #features. logging . log (
648+ `Update history with new messages: tabId=${ tabId } , tabType=${ tabType } , conversationId=${ conversationId } `
649+ )
650+
651+ const oldHistoryId = this . getOrCreateHistoryId ( tabId )
652+ // create a new historyId to start fresh
653+ const historyId = this . createHistoryId ( tabId )
654+
655+ const tabData = historyId ? tabCollection . findOne ( { historyId } ) : undefined
656+ const tabTitle = tabData ?. title || 'Amazon Q Chat'
657+ messages = messages . map ( msg => this . formatChatHistoryMessage ( msg ) )
658+ this . #features. logging . log ( `Overriding tab with new historyId=${ historyId } ` )
659+ tabCollection . insert ( {
660+ historyId,
661+ updatedAt : new Date ( ) ,
662+ isOpen : true ,
663+ tabType : tabType ,
664+ title : tabTitle ,
665+ conversations : [
666+ {
667+ conversationId,
668+ clientType,
669+ updatedAt : new Date ( ) ,
670+ messages : messages ,
671+ } ,
672+ ] ,
673+ } )
674+
675+ if ( oldHistoryId ) {
676+ tabCollection . findAndRemove ( { historyId : oldHistoryId } )
677+ }
678+ }
679+ }
680+
637681 formatChatHistoryMessage ( message : Message ) : Message {
638682 if ( message . type === ( 'prompt' as ChatItemType ) ) {
639683 let hasToolResults = false
@@ -663,11 +707,16 @@ export class ChatDatabase {
663707 */
664708 fixAndGetHistory (
665709 tabId : string ,
710+ conversationId : string ,
666711 newUserMessage : ChatMessage ,
667- pinnedContextMessages : ChatMessage [ ] ,
668- newUserInputCount ?: number
712+ pinnedContextMessages : ChatMessage [ ]
669713 ) : MessagesWithCharacterCount {
670- let messagesWithCount : MessagesWithCharacterCount = { messages : [ ] , count : 0 }
714+ let newUserInputCount = this . calculateNewMessageCharacterCount ( newUserMessage , pinnedContextMessages )
715+ let messagesWithCount : MessagesWithCharacterCount = {
716+ history : [ ] ,
717+ historyCount : 0 ,
718+ currentCount : newUserInputCount ,
719+ }
671720 if ( ! this . isInitialized ( ) ) {
672721 return messagesWithCount
673722 }
@@ -683,32 +732,32 @@ export class ChatDatabase {
683732 // 3. Fix new user prompt: Ensure lastMessage in history toolUse and newMessage toolResult relationship is valid
684733 this . validateAndFixNewMessageToolResults ( allMessages , newUserMessage )
685734
686- if ( ! newUserInputCount ) {
687- newUserInputCount = this . calculateNewMessageCharacterCount ( newUserMessage , pinnedContextMessages )
688- }
689-
690735 // 4. NOTE: Keep this trimming logic at the end of the preprocess.
691736 // Make sure max characters ≤ remaining Character Budget, must be put at the end of preprocessing
692- messagesWithCount = this . trimMessagesToMaxLength ( allMessages , newUserInputCount )
693- allMessages = messagesWithCount . messages
737+ messagesWithCount = this . trimMessagesToMaxLength ( allMessages , newUserInputCount , tabId , conversationId )
738+
694739 // Edge case: If the history is empty and the next message contains tool results, then we have to just abandon them.
695740 if (
696- allMessages . length === 0 &&
741+ messagesWithCount . history . length === 0 &&
697742 newUserMessage . userInputMessage ?. userInputMessageContext ?. toolResults ?. length &&
698743 newUserMessage . userInputMessage ?. userInputMessageContext ?. toolResults ?. length > 0
699744 ) {
700745 this . #features. logging . warn ( 'History overflow: abandoning dangling toolResults.' )
701746 newUserMessage . userInputMessage . userInputMessageContext . toolResults = [ ]
702747 newUserMessage . userInputMessage . content = 'The conversation history has overflowed, clearing state'
748+ // Update character count for current message
749+ this . #features. logging . debug ( `Updating input character with pinnedContext` )
750+ messagesWithCount . currentCount = this . calculateNewMessageCharacterCount (
751+ newUserMessage ,
752+ pinnedContextMessages
753+ )
703754 }
704755 }
705756
706757 // Prepend pinned context fake message pair to beginning of history
707758 if ( pinnedContextMessages . length === 2 ) {
708- messagesWithCount . messages = [
709- ...pinnedContextMessages . map ( msg => chatMessageToMessage ( msg ) ) ,
710- ...allMessages ,
711- ]
759+ const pinnedMessages = pinnedContextMessages . map ( msg => chatMessageToMessage ( msg ) )
760+ messagesWithCount . history = [ ...pinnedMessages , ...messagesWithCount . history ]
712761 }
713762
714763 return messagesWithCount
@@ -740,11 +789,20 @@ export class ChatDatabase {
740789 return ! ! ctx && ( ! ctx . toolResults || ctx . toolResults . length === 0 ) && message . body !== ''
741790 }
742791
743- private trimMessagesToMaxLength ( messages : Message [ ] , newUserInputCount : number ) : MessagesWithCharacterCount {
792+ private trimMessagesToMaxLength (
793+ messages : Message [ ] ,
794+ newUserInputCount : number ,
795+ tabId : string ,
796+ conversationId : string
797+ ) : MessagesWithCharacterCount {
744798 let historyCharacterCount = this . calculateMessagesCharacterCount ( messages )
745799 const maxHistoryCharacterSize = Math . max ( 0 , MaxOverallCharacters - newUserInputCount )
746- this . #features. logging . debug ( `Current remaining character budget: ${ maxHistoryCharacterSize } ` )
800+ let trimmedHistory = false
801+ this . #features. logging . debug (
802+ `Current history character count: ${ historyCharacterCount } , remaining history character budget: ${ maxHistoryCharacterSize } `
803+ )
747804 while ( historyCharacterCount > maxHistoryCharacterSize && messages . length > 2 ) {
805+ trimmedHistory = true
748806 // Find the next valid user message to start from
749807 const indexToTrim = this . findIndexToTrim ( messages )
750808 if ( indexToTrim !== undefined && indexToTrim > 0 ) {
@@ -756,13 +814,20 @@ export class ChatDatabase {
756814 this . #features. logging . debug (
757815 'Could not find a valid point to trim, reset history to reduce character count'
758816 )
759- return { messages : [ ] , count : 0 }
817+ this . replaceHistory ( tabId , 'cwc' , conversationId , [ ] )
818+ return { history : [ ] , historyCount : 0 , currentCount : newUserInputCount }
760819 }
761820 historyCharacterCount = this . calculateMessagesCharacterCount ( messages )
821+ this . #features. logging . debug ( `History character count post trimming: ${ historyCharacterCount } ` )
822+ }
823+
824+ if ( trimmedHistory ) {
825+ this . replaceHistory ( tabId , 'cwc' , conversationId , messages )
762826 }
763827 return {
764- messages,
765- count : historyCharacterCount ,
828+ history : messages ,
829+ historyCount : historyCharacterCount ,
830+ currentCount : newUserInputCount ,
766831 }
767832 }
768833
0 commit comments