mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
fix: clamp context token display to model context window size
Providers like DeepSeek with 1M context windows can report input_tokens that, when combined with output_tokens, exceed the declared context window — causing the UI to show >100% usage. Add an optional contextWindow parameter to calculateCurrentContextTokenTotal that clamps the result to the window size. Pass it from analyzeContext and sessionService where the window size is already available. Backward compatible: callers that omit the parameter keep existing behavior. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ffef5de9ef
commit
1aa0774cbf
@ -967,7 +967,7 @@ export class SessionService {
|
||||
output_tokens: latest.outputTokens,
|
||||
cache_read_input_tokens: latest.cacheReadInputTokens,
|
||||
cache_creation_input_tokens: latest.cacheCreationInputTokens,
|
||||
})
|
||||
}, rawMaxTokens)
|
||||
const percentage = rawMaxTokens > 0 ? Math.round((totalTokens / rawMaxTokens) * 100) : 0
|
||||
const categories: TranscriptContextEstimate['categories'] = [
|
||||
{ name: 'Input tokens', tokens: latest.inputTokens, color: '#8f3217' },
|
||||
|
||||
@ -19,4 +19,38 @@ describe('calculateCurrentContextTokenTotal', () => {
|
||||
output_tokens: 0,
|
||||
})).toBe(29_000)
|
||||
})
|
||||
|
||||
test('clamps to contextWindow when total would exceed it', () => {
|
||||
// DeepSeek scenario: input_tokens already near 1M limit, adding output pushes over
|
||||
expect(calculateCurrentContextTokenTotal(990_000, {
|
||||
input_tokens: 995_000,
|
||||
cache_creation_input_tokens: 0,
|
||||
cache_read_input_tokens: 0,
|
||||
output_tokens: 8_000,
|
||||
}, 1_000_000)).toBe(1_000_000)
|
||||
})
|
||||
|
||||
test('does not clamp when total is within contextWindow', () => {
|
||||
expect(calculateCurrentContextTokenTotal(26_000, {
|
||||
input_tokens: 24_000,
|
||||
cache_creation_input_tokens: 1_000,
|
||||
cache_read_input_tokens: 1_000,
|
||||
output_tokens: 3_000,
|
||||
}, 200_000)).toBe(29_000)
|
||||
})
|
||||
|
||||
test('without contextWindow arg behaves as before — no clamping', () => {
|
||||
// Passing no contextWindow should not clamp, preserving backward compatibility
|
||||
expect(calculateCurrentContextTokenTotal(990_000, {
|
||||
input_tokens: 995_000,
|
||||
cache_creation_input_tokens: 0,
|
||||
cache_read_input_tokens: 0,
|
||||
output_tokens: 8_000,
|
||||
})).toBe(1_003_000)
|
||||
})
|
||||
|
||||
test('returns estimatedTokens when currentUsage is null', () => {
|
||||
expect(calculateCurrentContextTokenTotal(50_000, null)).toBe(50_000)
|
||||
expect(calculateCurrentContextTokenTotal(50_000, null, 200_000)).toBe(50_000)
|
||||
})
|
||||
})
|
||||
|
||||
@ -1202,9 +1202,12 @@ export async function analyzeContextUsage(
|
||||
// Use the larger of the local estimate and the latest API-reported context.
|
||||
// This keeps the context meter from dropping when a response completes and
|
||||
// the output tokens become part of the next turn's context.
|
||||
// Clamp to contextWindow so providers whose input_tokens already approach the
|
||||
// limit (e.g. DeepSeek with 1M context) don't push the display over 100%.
|
||||
const finalTotalTokens = calculateCurrentContextTokenTotal(
|
||||
totalIncludingReserved,
|
||||
apiUsage,
|
||||
contextWindow,
|
||||
)
|
||||
|
||||
// Pre-calculate grid based on model context window and terminal width
|
||||
|
||||
@ -170,6 +170,10 @@ export function calculateContextPercentages(
|
||||
* immediately after the model finishes responding. The local estimate is kept
|
||||
* as a lower bound because it includes system/tool/message material that some
|
||||
* provider usage payloads under-report.
|
||||
*
|
||||
* Pass `contextWindow` to clamp the result to the model's context window size.
|
||||
* This prevents display values from exceeding 100% for providers (e.g. DeepSeek)
|
||||
* whose input_tokens already approach the window limit before output is added.
|
||||
*/
|
||||
export function calculateCurrentContextTokenTotal(
|
||||
estimatedTokens: number,
|
||||
@ -179,6 +183,7 @@ export function calculateCurrentContextTokenTotal(
|
||||
cache_creation_input_tokens: number
|
||||
cache_read_input_tokens: number
|
||||
} | null,
|
||||
contextWindow?: number,
|
||||
): number {
|
||||
if (!currentUsage) return estimatedTokens
|
||||
|
||||
@ -188,7 +193,8 @@ export function calculateCurrentContextTokenTotal(
|
||||
currentUsage.cache_read_input_tokens +
|
||||
(currentUsage.output_tokens ?? 0)
|
||||
|
||||
return Math.max(estimatedTokens, totalFromAPI)
|
||||
const total = Math.max(estimatedTokens, totalFromAPI)
|
||||
return contextWindow !== undefined ? Math.min(total, contextWindow) : total
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user