From 7680e25059ed9996b9feb26b6578cb2e65c4e313 Mon Sep 17 00:00:00 2001 From: JeremyDev87 Date: Fri, 20 Mar 2026 18:11:27 +0900 Subject: [PATCH] fix(tui): correct computeThroughput timestamp unit from ms to seconds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ActivitySample.timestamp is stored in seconds by the reducer (use-dashboard-state.ts:236), but computeThroughput divided by 60000 assuming milliseconds — causing throughput to display 1000x too high. - Change divisor from 60000 to 60 in computeThroughput - Update test data to use second-based timestamps (60000→60, 30000→30) - Add reverse-order timestamp guard test Closes #697 --- .../src/tui/components/live.pure.spec.ts | 16 ++++++++++++---- apps/mcp-server/src/tui/components/live.pure.ts | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/mcp-server/src/tui/components/live.pure.spec.ts b/apps/mcp-server/src/tui/components/live.pure.spec.ts index b6e07e2..02f56c3 100644 --- a/apps/mcp-server/src/tui/components/live.pure.spec.ts +++ b/apps/mcp-server/src/tui/components/live.pure.spec.ts @@ -152,7 +152,7 @@ describe('tui/components/live.pure', () => { it('1분 동안 5회 호출 → "5.0/min"', () => { const samples: ActivitySample[] = [ { timestamp: 0, toolCalls: 0 }, - { timestamp: 60000, toolCalls: 5 }, + { timestamp: 60, toolCalls: 5 }, ]; expect(computeThroughput(samples)).toBe('5.0/min'); }); @@ -160,7 +160,7 @@ describe('tui/components/live.pure', () => { it('30초 동안 3회 호출 → "6.0/min"', () => { const samples: ActivitySample[] = [ { timestamp: 0, toolCalls: 0 }, - { timestamp: 30000, toolCalls: 3 }, + { timestamp: 30, toolCalls: 3 }, ]; expect(computeThroughput(samples)).toBe('6.0/min'); }); @@ -168,12 +168,20 @@ describe('tui/components/live.pure', () => { it('여러 샘플의 총합으로 계산', () => { const samples: ActivitySample[] = [ { timestamp: 0, toolCalls: 1 }, - { timestamp: 30000, toolCalls: 2 }, - { timestamp: 60000, toolCalls: 3 }, + { timestamp: 30, toolCalls: 2 }, + { timestamp: 60, toolCalls: 3 }, ]; // 총 toolCalls = 1+2+3 = 6, 기간 = 60초 = 1분 → 6.0/min expect(computeThroughput(samples)).toBe('6.0/min'); }); + + it('역순 타임스탬프 → "0.0/min" (가드)', () => { + const samples: ActivitySample[] = [ + { timestamp: 60, toolCalls: 2 }, + { timestamp: 0, toolCalls: 3 }, + ]; + expect(computeThroughput(samples)).toBe('0.0/min'); + }); }); describe('formatTimeWithSeconds', () => { diff --git a/apps/mcp-server/src/tui/components/live.pure.ts b/apps/mcp-server/src/tui/components/live.pure.ts index f67ee0d..41cde18 100644 --- a/apps/mcp-server/src/tui/components/live.pure.ts +++ b/apps/mcp-server/src/tui/components/live.pure.ts @@ -57,7 +57,7 @@ export function computeThroughput(samples: ActivitySample[]): string { if (samples.length <= 1) return '0.0/min'; const first = samples[0]; const last = samples[samples.length - 1]; - const durationMin = (last.timestamp - first.timestamp) / 60000; + const durationMin = (last.timestamp - first.timestamp) / 60; if (durationMin <= 0) return '0.0/min'; const totalCalls = samples.reduce((sum, s) => sum + s.toolCalls, 0); return `${(totalCalls / durationMin).toFixed(1)}/min`;