mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-27 01:24:46 +00:00
fix(tui): recompute stale context usage ratio from status update token counts (#3164)
v2 engine status events carry contextTokens/maxContextTokens but never contextUsage, so appState.contextUsage was only refreshed by getStatus pulls and then went stale while the token counts kept updating live. The /usage panel and footer render the ratio as a bar but recompute the percentage text from the counts, so a stale ratio showed as a bar that disagreed with the percentage (e.g. bar ~74% next to "18% (180k / 1M)" after compaction or a model switch). Recompute the ratio from the post-patch token counts whenever a status update touches contextTokens or maxContextTokens without carrying an explicit contextUsage. v1 events carry the ratio and are unaffected. Co-authored-by: kimi-agent-bot <kimi-agent-bot@users.noreply.github.com>
This commit is contained in:
parent
6595955b31
commit
41a75adfc7
3 changed files with 100 additions and 1 deletions
5
.changeset/stale-context-usage-ratio.md
Normal file
5
.changeset/stale-context-usage-ratio.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@moonshot-ai/kimi-code": patch
|
||||
---
|
||||
|
||||
Fix the context usage bar in /usage and the footer showing a stale percentage after the context size or model changes.
|
||||
|
|
@ -712,9 +712,20 @@ export class SessionEventHandler {
|
|||
this.host.state.appState.swarmMode &&
|
||||
this.host.state.swarmModeEntry === 'task';
|
||||
const patch: Partial<AppState> = {};
|
||||
if (event.contextUsage !== undefined) patch.contextUsage = event.contextUsage;
|
||||
if (event.contextTokens !== undefined) patch.contextTokens = event.contextTokens;
|
||||
if (event.maxContextTokens !== undefined) patch.maxContextTokens = event.maxContextTokens;
|
||||
if (event.contextUsage !== undefined) {
|
||||
patch.contextUsage = event.contextUsage;
|
||||
} else if (event.contextTokens !== undefined || event.maxContextTokens !== undefined) {
|
||||
// v2 status events carry contextTokens/maxContextTokens but never
|
||||
// contextUsage. Recompute the ratio from the post-patch token counts so
|
||||
// it cannot go stale and drift from them — the footer and the /usage
|
||||
// panel bar render this ratio while their texts recompute from the
|
||||
// counts, so a stale ratio shows as a bar/percentage mismatch.
|
||||
const tokens = patch.contextTokens ?? this.host.state.appState.contextTokens;
|
||||
const max = patch.maxContextTokens ?? this.host.state.appState.maxContextTokens;
|
||||
patch.contextUsage = max > 0 ? tokens / max : 0;
|
||||
}
|
||||
if (event.planMode !== undefined) patch.planMode = event.planMode;
|
||||
if (event.swarmMode !== undefined) patch.swarmMode = event.swarmMode;
|
||||
if (event.towerMode !== undefined) patch.towerMode = event.towerMode;
|
||||
|
|
|
|||
|
|
@ -5596,6 +5596,89 @@ command = "vim"
|
|||
expect(stripSgr(renderTranscript(driver))).toContain('LLM not set');
|
||||
});
|
||||
|
||||
it('recomputes contextUsage when a status update carries contextTokens without it', async () => {
|
||||
const { driver } = await makeDriver();
|
||||
driver.state.appState.contextTokens = 0;
|
||||
driver.state.appState.maxContextTokens = 1_000_000;
|
||||
driver.state.appState.contextUsage = 0.74;
|
||||
|
||||
// v2 token-counting events carry contextTokens only; the ratio must be
|
||||
// recomputed or the footer and /usage bar keep showing the stale value.
|
||||
driver.sessionEventHandler.handleEvent(
|
||||
{
|
||||
type: 'agent.status.updated',
|
||||
agentId: 'main',
|
||||
sessionId: 'ses-1',
|
||||
contextTokens: 180_000,
|
||||
} as Event,
|
||||
vi.fn(),
|
||||
);
|
||||
|
||||
expect(driver.state.appState.contextTokens).toBe(180_000);
|
||||
expect(driver.state.appState.contextUsage).toBeCloseTo(0.18);
|
||||
});
|
||||
|
||||
it('recomputes contextUsage when a status update carries maxContextTokens without it', async () => {
|
||||
const { driver } = await makeDriver();
|
||||
driver.state.appState.contextTokens = 180_000;
|
||||
driver.state.appState.maxContextTokens = 256_000;
|
||||
driver.state.appState.contextUsage = 180_000 / 256_000;
|
||||
|
||||
// v2 profile events carry maxContextTokens only (e.g. a model switch).
|
||||
driver.sessionEventHandler.handleEvent(
|
||||
{
|
||||
type: 'agent.status.updated',
|
||||
agentId: 'main',
|
||||
sessionId: 'ses-1',
|
||||
maxContextTokens: 1_000_000,
|
||||
} as Event,
|
||||
vi.fn(),
|
||||
);
|
||||
|
||||
expect(driver.state.appState.maxContextTokens).toBe(1_000_000);
|
||||
expect(driver.state.appState.contextUsage).toBeCloseTo(0.18);
|
||||
});
|
||||
|
||||
it('keeps an explicit contextUsage from status updates instead of recomputing', async () => {
|
||||
const { driver } = await makeDriver();
|
||||
driver.state.appState.contextTokens = 100;
|
||||
driver.state.appState.maxContextTokens = 1_000_000;
|
||||
driver.state.appState.contextUsage = 0;
|
||||
|
||||
driver.sessionEventHandler.handleEvent(
|
||||
{
|
||||
type: 'agent.status.updated',
|
||||
agentId: 'main',
|
||||
sessionId: 'ses-1',
|
||||
contextTokens: 180_000,
|
||||
maxContextTokens: 1_000_000,
|
||||
contextUsage: 0.42,
|
||||
} as Event,
|
||||
vi.fn(),
|
||||
);
|
||||
|
||||
expect(driver.state.appState.contextUsage).toBe(0.42);
|
||||
});
|
||||
|
||||
it('zeroes contextUsage when a recomputation has no known context window', async () => {
|
||||
const { driver } = await makeDriver();
|
||||
driver.state.appState.contextTokens = 180_000;
|
||||
driver.state.appState.maxContextTokens = 0;
|
||||
driver.state.appState.contextUsage = 0.74;
|
||||
|
||||
driver.sessionEventHandler.handleEvent(
|
||||
{
|
||||
type: 'agent.status.updated',
|
||||
agentId: 'main',
|
||||
sessionId: 'ses-1',
|
||||
contextTokens: 190_000,
|
||||
} as Event,
|
||||
vi.fn(),
|
||||
);
|
||||
|
||||
expect(driver.state.appState.contextUsage).toBe(0);
|
||||
});
|
||||
|
||||
it('applies the effective thinking effort from status updates', async () => {
|
||||
const { driver } = await makeDriver();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue