mirror of
https://github.com/teamchong/pxpipe.git
synced 2026-07-22 02:02:51 +02:00
48f82ffee2
The session hero computed (1 - sent / raw_count_tokens_baseline) — the same cache-blind math just removed from the Details panel. It priced the all-text baseline at full rate, ignoring that most of it would have been cheap cache-reads, so a warm net-loss session showed a big "fewer tokens" win up top while Details/Saved showed a loss. Two panels, one session, opposite signs. - renderSessionSummaryFragment now reads baselineInputWeighted / actualInputWeighted (the same cache-weighted pair as Details + the Saved column) instead of rawActualTokens / rawBaselineTokens. - Headline is input-only; dropped the output-on-both-sides lumping (output is never "sent" and only dampened the %). - Honest labels: "effective tokens … after normal cache discounts"; still no $ assumptions (0.1x/1.25x are token multipliers, not $/Mtok). - types.ts: corrected stale field comments (raw fields are math-drawer only). - +4 hero tests pinning direction to the weighted pair and that output can't move the headline %. 374 tests pass; typecheck + build clean.
54 lines
2.4 KiB
TypeScript
54 lines
2.4 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { renderSessionSummaryFragment } from '../src/dashboard/fragments.js';
|
|
import type { CurrentSessionPayload } from '../src/dashboard/types.js';
|
|
|
|
/**
|
|
* The hero must read the SAME cache-weighted pair as the Details panel + Saved
|
|
* column. The old bug divided raw count_tokens (cache-blind) by sent tokens and
|
|
* could claim a big "fewer tokens" win on a session the Saved column showed as a
|
|
* net loss. These pin direction to `baselineInputWeighted` vs `actualInputWeighted`.
|
|
*/
|
|
function payload(p: Partial<CurrentSessionPayload>): CurrentSessionPayload {
|
|
return { sessionId: 's', baselineMeasuredCount: 1, rawOutputTokens: 139, ...p };
|
|
}
|
|
|
|
describe('renderSessionSummaryFragment hero', () => {
|
|
it('shows "fewer tokens" when the weighted image beat weighted text', () => {
|
|
const html = renderSessionSummaryFragment(
|
|
payload({ baselineInputWeighted: 7000, actualInputWeighted: 1800 }),
|
|
);
|
|
expect(html).toContain('fewer tokens');
|
|
expect(html).not.toContain('more tokens');
|
|
expect(html).toContain('74%'); // 1 - 1800/7000
|
|
});
|
|
|
|
it('flips to "more tokens" on a warm net-loss session (matches Saved "-")', () => {
|
|
// The exact trap: raw text (e.g. 7.2k) would look like a huge win, but the
|
|
// cache-weighted text baseline (1,546) is below what imaging actually sent (1,863).
|
|
const html = renderSessionSummaryFragment(
|
|
payload({ baselineInputWeighted: 1546, actualInputWeighted: 1863 }),
|
|
);
|
|
expect(html).toContain('more tokens');
|
|
expect(html).not.toContain('fewer tokens');
|
|
expect(html).toContain('hero-neg'); // red styling on a loss
|
|
});
|
|
|
|
it('never lumps output into the headline ratio', () => {
|
|
// Same input pair, wildly different output — headline % must not move.
|
|
const a = renderSessionSummaryFragment(
|
|
payload({ baselineInputWeighted: 2000, actualInputWeighted: 1000, rawOutputTokens: 10 }),
|
|
);
|
|
const b = renderSessionSummaryFragment(
|
|
payload({ baselineInputWeighted: 2000, actualInputWeighted: 1000, rawOutputTokens: 9000 }),
|
|
);
|
|
expect(a).toContain('50%');
|
|
expect(b).toContain('50%');
|
|
});
|
|
|
|
it('renders the warming-up state with no measured requests', () => {
|
|
const html = renderSessionSummaryFragment(payload({ baselineMeasuredCount: 0 }));
|
|
expect(html).toContain('Warming up');
|
|
expect(html).not.toContain('fewer tokens');
|
|
});
|
|
});
|