Skip to content

Commit e686e4e

Browse files
committed
add session statistics to pruning notifications
1 parent c636534 commit e686e4e

File tree

2 files changed

+56
-11
lines changed

2 files changed

+56
-11
lines changed

lib/janitor.ts

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from "zod"
22
import type { Logger } from "./logger"
3-
import type { StateManager } from "./state"
3+
import type { StateManager, SessionStats } from "./state"
44
import { buildAnalysisPrompt } from "./prompt"
55
import { selectModel, extractModelFromSession } from "./model-selector"
66
import { estimateTokensBatch, formatTokenCount } from "./tokenizer"
@@ -268,12 +268,16 @@ export class Janitor {
268268
// Calculate token savings once (used by both notification and log)
269269
const tokensSaved = await this.calculateTokensSaved(finalNewlyPrunedIds, toolOutputs)
270270

271+
// Accumulate session stats (for showing cumulative totals in UI)
272+
const sessionStats = await this.stateManager.addStats(sessionID, finalNewlyPrunedIds.length, tokensSaved)
273+
271274
if (this.pruningMode === "auto") {
272275
await this.sendAutoModeNotification(
273276
sessionID,
274277
deduplicatedIds,
275278
deduplicationDetails,
276-
tokensSaved
279+
tokensSaved,
280+
sessionStats
277281
)
278282
} else {
279283
await this.sendSmartModeNotification(
@@ -282,7 +286,8 @@ export class Janitor {
282286
deduplicationDetails,
283287
llmPrunedIds,
284288
toolMetadata,
285-
tokensSaved
289+
tokensSaved,
290+
sessionStats
286291
)
287292
}
288293

@@ -451,14 +456,20 @@ export class Janitor {
451456
private async sendMinimalNotification(
452457
sessionID: string,
453458
totalPruned: number,
454-
tokensSaved: number
459+
tokensSaved: number,
460+
sessionStats: SessionStats
455461
) {
456462
if (totalPruned === 0) return
457463

458464
const tokensFormatted = formatTokenCount(tokensSaved)
459465
const toolText = totalPruned === 1 ? 'tool' : 'tools'
460466

461-
const message = `🧹 DCP: Saved ~${tokensFormatted} tokens (${totalPruned} ${toolText} pruned)`
467+
let message = `🧹 DCP: Saved ~${tokensFormatted} tokens (${totalPruned} ${toolText} pruned)`
468+
469+
// Add session totals if there's been more than one pruning run
470+
if (sessionStats.totalToolsPruned > totalPruned) {
471+
message += ` │ Session: ${sessionStats.totalToolsPruned} tools, ~${formatTokenCount(sessionStats.totalTokensSaved)} tokens`
472+
}
462473

463474
await this.sendIgnoredMessage(sessionID, message)
464475
}
@@ -470,7 +481,8 @@ export class Janitor {
470481
sessionID: string,
471482
deduplicatedIds: string[],
472483
deduplicationDetails: Map<string, any>,
473-
tokensSaved: number
484+
tokensSaved: number,
485+
sessionStats: SessionStats
474486
) {
475487
if (deduplicatedIds.length === 0) return
476488

@@ -479,15 +491,21 @@ export class Janitor {
479491

480492
// Send minimal notification if configured
481493
if (this.pruningSummary === 'minimal') {
482-
await this.sendMinimalNotification(sessionID, deduplicatedIds.length, tokensSaved)
494+
await this.sendMinimalNotification(sessionID, deduplicatedIds.length, tokensSaved, sessionStats)
483495
return
484496
}
485497

486498
// Otherwise send detailed notification
487499
const tokensFormatted = formatTokenCount(tokensSaved)
488500

489501
const toolText = deduplicatedIds.length === 1 ? 'tool' : 'tools'
490-
let message = `🧹 DCP: Saved ~${tokensFormatted} tokens (${deduplicatedIds.length} duplicate ${toolText} removed)\n`
502+
let message = `🧹 DCP: Saved ~${tokensFormatted} tokens (${deduplicatedIds.length} duplicate ${toolText} removed)`
503+
504+
// Add session totals if there's been more than one pruning run
505+
if (sessionStats.totalToolsPruned > deduplicatedIds.length) {
506+
message += ` │ Session: ${sessionStats.totalToolsPruned} tools, ~${formatTokenCount(sessionStats.totalTokensSaved)} tokens`
507+
}
508+
message += '\n'
491509

492510
// Group by tool type
493511
const grouped = new Map<string, Array<{count: number, key: string}>>()
@@ -530,7 +548,8 @@ export class Janitor {
530548
deduplicationDetails: Map<string, any>,
531549
llmPrunedIds: string[],
532550
toolMetadata: Map<string, any>,
533-
tokensSaved: number
551+
tokensSaved: number,
552+
sessionStats: SessionStats
534553
) {
535554
const totalPruned = deduplicatedIds.length + llmPrunedIds.length
536555
if (totalPruned === 0) return
@@ -540,14 +559,20 @@ export class Janitor {
540559

541560
// Send minimal notification if configured
542561
if (this.pruningSummary === 'minimal') {
543-
await this.sendMinimalNotification(sessionID, totalPruned, tokensSaved)
562+
await this.sendMinimalNotification(sessionID, totalPruned, tokensSaved, sessionStats)
544563
return
545564
}
546565

547566
// Otherwise send detailed notification
548567
const tokensFormatted = formatTokenCount(tokensSaved)
549568

550-
let message = `🧹 DCP: Saved ~${tokensFormatted} tokens (${totalPruned} tool${totalPruned > 1 ? 's' : ''} pruned)\n`
569+
let message = `🧹 DCP: Saved ~${tokensFormatted} tokens (${totalPruned} tool${totalPruned > 1 ? 's' : ''} pruned)`
570+
571+
// Add session totals if there's been more than one pruning run
572+
if (sessionStats.totalToolsPruned > totalPruned) {
573+
message += ` │ Session: ${sessionStats.totalToolsPruned} tools, ~${formatTokenCount(sessionStats.totalTokensSaved)} tokens`
574+
}
575+
message += '\n'
551576

552577
// Section 1: Deduplicated tools
553578
if (deduplicatedIds.length > 0 && deduplicationDetails) {

lib/state.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
// lib/state.ts
22

3+
export interface SessionStats {
4+
totalToolsPruned: number
5+
totalTokensSaved: number
6+
}
7+
38
export class StateManager {
49
private state: Map<string, string[]> = new Map()
10+
private stats: Map<string, SessionStats> = new Map()
511

612
async get(sessionID: string): Promise<string[]> {
713
return this.state.get(sessionID) ?? []
@@ -10,4 +16,18 @@ export class StateManager {
1016
async set(sessionID: string, prunedIds: string[]): Promise<void> {
1117
this.state.set(sessionID, prunedIds)
1218
}
19+
20+
async getStats(sessionID: string): Promise<SessionStats> {
21+
return this.stats.get(sessionID) ?? { totalToolsPruned: 0, totalTokensSaved: 0 }
22+
}
23+
24+
async addStats(sessionID: string, toolsPruned: number, tokensSaved: number): Promise<SessionStats> {
25+
const current = await this.getStats(sessionID)
26+
const updated: SessionStats = {
27+
totalToolsPruned: current.totalToolsPruned + toolsPruned,
28+
totalTokensSaved: current.totalTokensSaved + tokensSaved
29+
}
30+
this.stats.set(sessionID, updated)
31+
return updated
32+
}
1333
}

0 commit comments

Comments
 (0)