mirror of
https://github.com/Tencent/teamai-cli.git
synced 2026-10-02 03:14:40 +08:00
Merge pull request #477 from STiFLeR7/fix/session-trends-success-delta-473
fix(metrics): claw back sessionsSucceeded when a resumed session later fails
This commit is contained in:
@@ -61,6 +61,29 @@ describe('daily session trends', () => {
|
||||
expect(second.delta['2026-09-03']).toMatchObject({ pricedRequests: 1, costMicros: 150, sessionsEnded: 0 });
|
||||
});
|
||||
|
||||
it('claws back sessionsSucceeded when a resumed session later fails (#473)', () => {
|
||||
const succeeded = new Map([
|
||||
['s1', { date: '2026-09-02', prompts: 1, durationMs: 60_000, succeeded: 1 as const, corrected: 0 as const, requestDaily: {} }],
|
||||
]);
|
||||
const first = computeDailyStatsDelta(succeeded, {});
|
||||
expect(first.delta['2026-09-02']).toMatchObject({ sessionsEnded: 1, sessionsSucceeded: 1 });
|
||||
const merged = mergeDailyStats(undefined, first.delta);
|
||||
expect(merged['2026-09-02']).toMatchObject({ sessionsEnded: 1, sessionsSucceeded: 1 });
|
||||
|
||||
const interrupted = new Map([
|
||||
['s1', { ...succeeded.get('s1')!, succeeded: 0 as const, corrected: 1 as const }],
|
||||
]);
|
||||
const second = computeDailyStatsDelta(interrupted, first.nextReported);
|
||||
expect(second.delta['2026-09-02']).toMatchObject({ sessionsEnded: 0, sessionsSucceeded: -1, sessionsCorrected: 1 });
|
||||
const remerged = mergeDailyStats(merged, second.delta);
|
||||
expect(remerged['2026-09-02']).toMatchObject({ sessionsEnded: 1, sessionsSucceeded: 0 });
|
||||
|
||||
// A later, unrelated re-report of the same now-failed state must not
|
||||
// double-subtract: the delta settles back to 0 once the baseline catches up.
|
||||
const third = computeDailyStatsDelta(interrupted, second.nextReported);
|
||||
expect(third.delta['2026-09-02']).toMatchObject({ sessionsEnded: 0, sessionsSucceeded: 0 });
|
||||
});
|
||||
|
||||
it('compares the latest seven UTC days with the prior seven days', () => {
|
||||
const daily: Record<string, DailyUserStats> = {
|
||||
'2026-08-27': { sessionsEnded: 10, sessionsSucceeded: 5, promptTurns: 80, durationMs: 600_000, sessionsCorrected: 4, pricedRequests: 10, costMicros: 1_000_000, cacheReadTokens: 20, cacheEligibleInputTokens: 100 },
|
||||
|
||||
@@ -104,8 +104,12 @@ export function computeDailyStatsDelta(
|
||||
const bucket = delta[date] ?? emptyDaily();
|
||||
if (!previous) {
|
||||
bucket.sessionsEnded += 1;
|
||||
bucket.sessionsSucceeded += snapshot.succeeded;
|
||||
}
|
||||
// Signed, not positiveDelta: unlike the monotonic counters below, a
|
||||
// session can flip from succeeded to failed on a later report (resumed
|
||||
// after an interruption/correction), and that must claw back the earlier
|
||||
// sessionsSucceeded increment, not just skip adding a new one (#473).
|
||||
bucket.sessionsSucceeded += snapshot.succeeded - (previous?.succeeded ?? 0);
|
||||
bucket.promptTurns += positiveDelta(snapshot.prompts, previous?.prompts);
|
||||
bucket.durationMs += positiveDelta(snapshot.durationMs, previous?.durationMs);
|
||||
bucket.sessionsCorrected += positiveDelta(snapshot.corrected, previous?.corrected);
|
||||
|
||||
+4
-1
@@ -298,7 +298,10 @@ async function writeReportedDailySessions(data: ReportedDailySessions): Promise<
|
||||
|
||||
function hasDailyDelta(delta: ReturnType<typeof computeDailyStatsDelta>['delta']): boolean {
|
||||
return Object.values(delta).some((bucket) =>
|
||||
bucket.sessionsEnded > 0 || bucket.sessionsSucceeded > 0 || bucket.promptTurns > 0
|
||||
// sessionsSucceeded can be negative (a resumed session that later failed
|
||||
// claws back an earlier increment), so it must not be checked with the
|
||||
// same "> 0" as the other, purely monotonic counters (#473).
|
||||
bucket.sessionsEnded > 0 || bucket.sessionsSucceeded !== 0 || bucket.promptTurns > 0
|
||||
|| bucket.durationMs > 0 || bucket.sessionsCorrected > 0 || bucket.pricedRequests > 0
|
||||
|| bucket.costMicros > 0 || bucket.cacheReadTokens > 0 || bucket.cacheEligibleInputTokens > 0,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user