@@ -70,6 +70,63 @@ function handleContentDisplay(
7070 }
7171}
7272
73+ // Helper function to refresh chat history from service
74+ function refreshChatHistoryFromService (
75+ chatHistory : ChatHistoryItem [ ] ,
76+ isCompacting : boolean ,
77+ ) : ChatHistoryItem [ ] {
78+ const chatHistorySvc = services . chatHistory ;
79+ if (
80+ typeof chatHistorySvc ?. isReady === "function" &&
81+ chatHistorySvc . isReady ( )
82+ ) {
83+ try {
84+ // use chat history from params when isCompacting is true
85+ // otherwise use the full history
86+ if ( ! isCompacting ) {
87+ return chatHistorySvc . getHistory ( ) ;
88+ }
89+ } catch { }
90+ }
91+ return chatHistory ;
92+ }
93+
94+ // Helper function to handle auto-continuation after compaction
95+ function handleAutoContinuation (
96+ compactionOccurred : boolean ,
97+ shouldContinue : boolean ,
98+ chatHistory : ChatHistoryItem [ ] ,
99+ ) : { shouldAutoContinue : boolean ; chatHistory : ChatHistoryItem [ ] } {
100+ if ( ! compactionOccurred || shouldContinue ) {
101+ return { shouldAutoContinue : false , chatHistory } ;
102+ }
103+
104+ logger . debug (
105+ "Auto-compaction occurred during this turn - automatically continuing session" ,
106+ ) ;
107+
108+ // Add a continuation message to the history
109+ const chatHistorySvc = services . chatHistory ;
110+ if (
111+ typeof chatHistorySvc ?. isReady === "function" &&
112+ chatHistorySvc . isReady ( )
113+ ) {
114+ chatHistorySvc . addUserMessage ( "continue" ) ;
115+ chatHistory = chatHistorySvc . getHistory ( ) ;
116+ } else {
117+ chatHistory . push ( {
118+ message : {
119+ role : "user" ,
120+ content : "continue" ,
121+ } ,
122+ contextItems : [ ] ,
123+ } ) ;
124+ }
125+
126+ logger . debug ( "Added continuation message after compaction" ) ;
127+ return { shouldAutoContinue : true , chatHistory } ;
128+ }
129+
73130// Helper function to process a single chunk
74131interface ProcessChunkOptions {
75132 chunk : any ;
@@ -379,22 +436,11 @@ export async function streamChatResponse(
379436
380437 let fullResponse = "" ;
381438 let finalResponse = "" ;
439+ let compactionOccurredThisTurn = false ; // Track if compaction happened during this conversation turn
382440
383441 while ( true ) {
384442 // If ChatHistoryService is available, refresh local chatHistory view
385- const chatHistorySvc = services . chatHistory ;
386- if (
387- typeof chatHistorySvc ?. isReady === "function" &&
388- chatHistorySvc . isReady ( )
389- ) {
390- try {
391- // use chat history from params when isCompacting is true
392- // otherwise use the full history
393- if ( ! isCompacting ) {
394- chatHistory = chatHistorySvc . getHistory ( ) ;
395- }
396- } catch { }
397- }
443+ chatHistory = refreshChatHistoryFromService ( chatHistory , isCompacting ) ;
398444 logger . debug ( "Starting conversation iteration" ) ;
399445
400446 logger . debug ( "debug1 streamChatResponse history" , { chatHistory } ) ;
@@ -414,6 +460,9 @@ export async function streamChatResponse(
414460 systemMessage,
415461 } ) ;
416462 chatHistory = preCompactionResult . chatHistory ;
463+ if ( preCompactionResult . wasCompacted ) {
464+ compactionOccurredThisTurn = true ;
465+ }
417466
418467 // Recompute tools on each iteration to handle mode changes during streaming
419468 const tools = await getRequestTools ( isHeadless ) ;
@@ -467,17 +516,25 @@ export async function streamChatResponse(
467516 }
468517
469518 // After tool execution, validate that we haven't exceeded context limit
470- chatHistory = await handlePostToolValidation ( toolCalls , chatHistory , {
471- model,
472- llmApi,
473- isCompacting,
474- isHeadless,
475- callbacks,
476- systemMessage,
477- } ) ;
519+ const postToolResult = await handlePostToolValidation (
520+ toolCalls ,
521+ chatHistory ,
522+ {
523+ model,
524+ llmApi,
525+ isCompacting,
526+ isHeadless,
527+ callbacks,
528+ systemMessage,
529+ } ,
530+ ) ;
531+ chatHistory = postToolResult . chatHistory ;
532+ if ( postToolResult . wasCompacted ) {
533+ compactionOccurredThisTurn = true ;
534+ }
478535
479536 // Normal auto-compaction check at 80% threshold
480- chatHistory = await handleNormalAutoCompaction (
537+ const compactionResult = await handleNormalAutoCompaction (
481538 chatHistory ,
482539 shouldContinue ,
483540 {
@@ -489,9 +546,28 @@ export async function streamChatResponse(
489546 systemMessage,
490547 } ,
491548 ) ;
549+ chatHistory = compactionResult . chatHistory ;
550+ if ( compactionResult . wasCompacted ) {
551+ compactionOccurredThisTurn = true ;
552+ }
553+
554+ // If compaction happened during this turn and we're about to stop,
555+ // automatically send a continuation message to keep the agent going
556+ const autoContinueResult = handleAutoContinuation (
557+ compactionOccurredThisTurn ,
558+ shouldContinue ,
559+ chatHistory ,
560+ ) ;
561+ chatHistory = autoContinueResult . chatHistory ;
562+ const shouldAutoContinue = autoContinueResult . shouldAutoContinue ;
563+
564+ // Reset flag to avoid infinite continuation
565+ if ( shouldAutoContinue ) {
566+ compactionOccurredThisTurn = false ;
567+ }
492568
493- // Check if we should continue
494- if ( ! shouldContinue ) {
569+ // Check if we should continue (skip break if auto-continuing after compaction)
570+ if ( ! shouldContinue && ! shouldAutoContinue ) {
495571 break ;
496572 }
497573 }
0 commit comments