@@ -40,6 +40,32 @@ export async function estimateTokenCount(
4040 return apiHandler . countTokens ( content )
4141}
4242
43+ /**
44+ * Computes the percentage of the context budget consumed by the prior context.
45+ *
46+ * Default: divide by the full context window. Opt-in (vscode-lm) divides by available input
47+ * (window minus reserved output); an unknown/unlimited reserve (maxTokens -1) falls back to the
48+ * full window. Shared by `willManageContext` and `manageContext` so the two stay in lockstep.
49+ */
50+ function computeContextPercent ( {
51+ prevContextTokens,
52+ contextWindow,
53+ maxTokens,
54+ useAvailableInputForContextPercent,
55+ } : {
56+ prevContextTokens : number
57+ contextWindow : number
58+ maxTokens ?: number | null
59+ useAvailableInputForContextPercent ?: boolean
60+ } ) : number {
61+ if ( ! useAvailableInputForContextPercent ) {
62+ return ( 100 * prevContextTokens ) / contextWindow
63+ }
64+ const reservedForOutput = maxTokens && maxTokens > 0 ? maxTokens : 0
65+ const availableInputTokens = contextWindow - reservedForOutput
66+ return availableInputTokens > 0 ? ( 100 * prevContextTokens ) / availableInputTokens : 100
67+ }
68+
4369/**
4470 * Result of truncation operation, includes the truncation ID for UI events.
4571 */
@@ -200,16 +226,12 @@ export function willManageContext({
200226 // Invalid values fall back to global setting (effectiveThreshold already set)
201227 }
202228
203- // Default: divide by the full context window. Opt-in (vscode-lm) divides by available input
204- // (window minus reserved output); an unknown/unlimited reserve (-1) falls back to the full window.
205- let contextPercent : number
206- if ( useAvailableInputForContextPercent ) {
207- const reservedForOutput = maxTokens && maxTokens > 0 ? maxTokens : 0
208- const availableInputTokens = contextWindow - reservedForOutput
209- contextPercent = availableInputTokens > 0 ? ( 100 * prevContextTokens ) / availableInputTokens : 100
210- } else {
211- contextPercent = ( 100 * prevContextTokens ) / contextWindow
212- }
229+ const contextPercent = computeContextPercent ( {
230+ prevContextTokens,
231+ contextWindow,
232+ maxTokens,
233+ useAvailableInputForContextPercent,
234+ } )
213235 return contextPercent >= effectiveThreshold || prevContextTokens > allowedTokens
214236}
215237
@@ -328,16 +350,12 @@ export async function manageContext({
328350 // If no specific threshold is found for the profile, fall back to global setting
329351
330352 if ( autoCondenseContext ) {
331- // Default: divide by the full context window. Opt-in (vscode-lm) divides by available input
332- // (window minus reserved output); an unknown/unlimited reserve (-1) falls back to the full window.
333- let contextPercent : number
334- if ( useAvailableInputForContextPercent ) {
335- const reservedForOutput = maxTokens && maxTokens > 0 ? maxTokens : 0
336- const availableInputTokens = contextWindow - reservedForOutput
337- contextPercent = availableInputTokens > 0 ? ( 100 * prevContextTokens ) / availableInputTokens : 100
338- } else {
339- contextPercent = ( 100 * prevContextTokens ) / contextWindow
340- }
353+ const contextPercent = computeContextPercent ( {
354+ prevContextTokens,
355+ contextWindow,
356+ maxTokens,
357+ useAvailableInputForContextPercent,
358+ } )
341359 if ( contextPercent >= effectiveThreshold || prevContextTokens > allowedTokens ) {
342360 // Attempt to intelligently condense the context
343361 const result = await summarizeConversation ( {
0 commit comments