@@ -510,6 +510,10 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
510510 this . _persistSummaryOnTurn ( bgResult , promptContext , this . _lastRenderTokenCount ) ;
511511 this . _sendBackgroundCompactionTelemetry ( 'preRender' , 'applied' , contextRatio , promptContext ) ;
512512 summaryAppliedThisIteration = true ;
513+ } else {
514+ this . logService . warn ( `[Agent] background compaction state was Completed but consumeAndReset returned no result` ) ;
515+ this . _sendBackgroundCompactionTelemetry ( 'preRender' , 'noResult' , contextRatio , promptContext ) ;
516+ this . _recordBackgroundCompactionFailure ( promptContext , 'preRender' ) ;
513517 }
514518 }
515519
@@ -531,8 +535,14 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
531535 this . _sendBackgroundCompactionTelemetry ( 'preRenderBlocked' , 'applied' , contextRatio , promptContext ) ;
532536 summaryAppliedThisIteration = true ;
533537 } else {
534- this . logService . debug ( `[Agent] background compaction finished but produced no usable result` ) ;
538+ this . logService . debug ( `[Agent] background compaction finished but produced no usable result — will attempt foreground summarization if budget exceeded ` ) ;
535539 this . _sendBackgroundCompactionTelemetry ( 'preRenderBlocked' , 'noResult' , contextRatio , promptContext ) ;
540+ this . _recordBackgroundCompactionFailure ( promptContext , 'preRenderBlocked' ) ;
541+ // Don't attempt a foreground fallback here — the main render below
542+ // will either succeed (context estimate was pessimistic) or throw
543+ // BudgetExceededError, which the catch block handles with foreground
544+ // summarization. Short-circuiting here would skip the main render
545+ // unnecessarily when it might still fit.
536546 }
537547 }
538548
@@ -582,8 +592,10 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
582592
583593 this . logService . debug ( `[Agent] ${ reason } , triggering summarization` ) ;
584594 try {
585- const renderer = PromptRenderer . create ( this . instantiationService , endpoint , this . prompt , {
595+ const renderer = PromptRenderer . create ( this . instantiationService , this . endpoint , this . prompt , {
586596 ...renderProps ,
597+ endpoint : this . endpoint ,
598+ promptContext : this . _buildSummarizationPromptContext ( renderProps . promptContext ) ,
587599 triggerSummarize : true ,
588600 } ) ;
589601 return await renderer . render ( progress , token ) ;
@@ -692,6 +704,7 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
692704 } else {
693705 this . logService . debug ( `[Agent] background compaction produced no usable result after budget exceeded — falling back to synchronous summarization` ) ;
694706 this . _sendBackgroundCompactionTelemetry ( budgetExceededTrigger , 'noResult' , contextRatio , promptContext ) ;
707+ this . _recordBackgroundCompactionFailure ( promptContext , budgetExceededTrigger ) ;
695708 // Background compaction failed — fall back to synchronous summarization
696709 result = await renderWithSummarization ( `budget exceeded(${ e . message } ), background compaction failed` ) ;
697710 }
@@ -758,12 +771,19 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
758771 result = await reRenderer . render ( progress , token ) ;
759772 this . _lastRenderTokenCount = result . tokenCount ;
760773 } else {
761- this . logService . debug ( `[Agent] post-render background compaction finished but produced no usable result` ) ;
774+ this . logService . debug ( `[Agent] post-render background compaction finished but produced no usable result — falling back to foreground summarization ` ) ;
762775 this . _sendBackgroundCompactionTelemetry ( 'postRenderBlocked' , 'noResult' , postRenderRatio , promptContext ) ;
776+ this . _recordBackgroundCompactionFailure ( promptContext , 'postRenderBlocked' ) ;
777+ try {
778+ result = await renderWithSummarization ( 'post-render background compaction noResult fallback' ) ;
779+ this . _lastRenderTokenCount = result . tokenCount ;
780+ } catch ( e ) {
781+ this . logService . error ( e , `[Agent] post-render foreground summarization fallback also failed — using original render result` ) ;
782+ }
763783 }
764784 } else if ( postRenderRatio >= 0.80 && ( backgroundSummarizer . state === BackgroundSummarizationState . Idle || backgroundSummarizer . state === BackgroundSummarizationState . Failed ) ) {
765785 // At ≥ 80% with no running compaction (or a previous failure) — kick off background work.
766- this . _startBackgroundSummarization ( backgroundSummarizer , props , endpoint , token , postRenderRatio ) ;
786+ this . _startBackgroundSummarization ( backgroundSummarizer , props , token , postRenderRatio ) ;
767787 }
768788 }
769789
@@ -831,7 +851,6 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
831851 private _startBackgroundSummarization (
832852 backgroundSummarizer : BackgroundSummarizer ,
833853 props : AgentPromptProps ,
834- endpoint : IChatEndpoint ,
835854 token : vscode . CancellationToken ,
836855 contextRatio : number ,
837856 ) : void {
@@ -846,8 +865,10 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
846865 toolCallResults : props . promptContext . toolCallResults ? { ...props . promptContext . toolCallResults } : undefined ,
847866 }
848867 } ;
849- const bgRenderer = PromptRenderer . create ( this . instantiationService , endpoint , this . prompt , {
868+ const bgRenderer = PromptRenderer . create ( this . instantiationService , this . endpoint , this . prompt , {
850869 ...snapshotProps ,
870+ endpoint : this . endpoint ,
871+ promptContext : this . _buildSummarizationPromptContext ( snapshotProps . promptContext ) ,
851872 triggerSummarize : true ,
852873 summarizationSource : 'background' ,
853874 } ) ;
@@ -957,6 +978,48 @@ export class AgentIntentInvocation extends EditCodeIntentInvocation implements I
957978 ) ) ;
958979 }
959980
981+ /**
982+ * Build a promptContext for summarization that filters availableTools to
983+ * non-deferred tools when Anthropic tool search is enabled. Deferred tool
984+ * schemas are unnecessary in the summarization prompt (which uses
985+ * tool_choice: 'none') and can push the prompt over the token budget.
986+ */
987+ private _buildSummarizationPromptContext ( promptContext : IBuildPromptContext ) : IBuildPromptContext {
988+ if ( ! promptContext . tools ?. availableTools ) {
989+ return promptContext ;
990+ }
991+ const toolSearchEnabled = isAnthropicToolSearchEnabled ( this . endpoint , this . configurationService ) ;
992+ if ( ! toolSearchEnabled ) {
993+ return promptContext ;
994+ }
995+ const nonDeferredTools = promptContext . tools . availableTools . filter ( t => this . toolDeferralService . isNonDeferredTool ( t . name ) ) ;
996+ return {
997+ ...promptContext ,
998+ tools : {
999+ ...promptContext . tools ,
1000+ availableTools : nonDeferredTools ,
1001+ } ,
1002+ } ;
1003+ }
1004+
1005+ /**
1006+ * Record a background compaction failure on the current turn's metadata,
1007+ * matching how foreground compaction records its failures.
1008+ */
1009+ private _recordBackgroundCompactionFailure ( promptContext : IBuildPromptContext , trigger : string ) : void {
1010+ const turn = promptContext . conversation ?. getLatestTurn ( ) ;
1011+ turn ?. setMetadata ( new SummarizedConversationHistoryMetadata (
1012+ '' , // no toolCallRoundId for failures
1013+ '' , // no summary text for failures
1014+ {
1015+ model : this . endpoint . model ,
1016+ source : 'background' ,
1017+ outcome : `noResult_${ trigger } ` ,
1018+ contextLengthBefore : this . _lastRenderTokenCount ,
1019+ } ,
1020+ ) ) ;
1021+ }
1022+
9601023 private _sendBackgroundCompactionTelemetry (
9611024 trigger : string ,
9621025 outcome : string ,
0 commit comments