Browse Source

tweak stats command to show avg & median # of tokens per session

Aiden Cline 2 months ago
parent
commit
d914a08896
1 changed files with 23 additions and 1 deletions
  1. 23 1
      packages/opencode/src/cli/cmd/stats.ts

+ 23 - 1
packages/opencode/src/cli/cmd/stats.ts

@@ -26,6 +26,8 @@ interface SessionStats {
   }
   }
   days: number
   days: number
   costPerDay: number
   costPerDay: number
+  tokensPerSession: number
+  medianTokensPerSession: number
 }
 }
 
 
 export const StatsCommand = cmd({
 export const StatsCommand = cmd({
@@ -116,6 +118,8 @@ async function aggregateSessionStats(days?: number, projectFilter?: string): Pro
     },
     },
     days: 0,
     days: 0,
     costPerDay: 0,
     costPerDay: 0,
+    tokensPerSession: 0,
+    medianTokensPerSession: 0,
   }
   }
 
 
   if (filteredSessions.length > 1000) {
   if (filteredSessions.length > 1000) {
@@ -129,6 +133,8 @@ async function aggregateSessionStats(days?: number, projectFilter?: string): Pro
   let earliestTime = Date.now()
   let earliestTime = Date.now()
   let latestTime = 0
   let latestTime = 0
 
 
+  const sessionTotalTokens: number[] = []
+
   const BATCH_SIZE = 20
   const BATCH_SIZE = 20
   for (let i = 0; i < filteredSessions.length; i += BATCH_SIZE) {
   for (let i = 0; i < filteredSessions.length; i += BATCH_SIZE) {
     const batch = filteredSessions.slice(i, i + BATCH_SIZE)
     const batch = filteredSessions.slice(i, i + BATCH_SIZE)
@@ -164,6 +170,7 @@ async function aggregateSessionStats(days?: number, projectFilter?: string): Pro
         messageCount: messages.length,
         messageCount: messages.length,
         sessionCost,
         sessionCost,
         sessionTokens,
         sessionTokens,
+        sessionTotalTokens: sessionTokens.input + sessionTokens.output + sessionTokens.reasoning,
         sessionToolUsage,
         sessionToolUsage,
         earliestTime: session.time.created,
         earliestTime: session.time.created,
         latestTime: session.time.updated,
         latestTime: session.time.updated,
@@ -175,6 +182,7 @@ async function aggregateSessionStats(days?: number, projectFilter?: string): Pro
     for (const result of batchResults) {
     for (const result of batchResults) {
       earliestTime = Math.min(earliestTime, result.earliestTime)
       earliestTime = Math.min(earliestTime, result.earliestTime)
       latestTime = Math.max(latestTime, result.latestTime)
       latestTime = Math.max(latestTime, result.latestTime)
+      sessionTotalTokens.push(result.sessionTotalTokens)
 
 
       stats.totalMessages += result.messageCount
       stats.totalMessages += result.messageCount
       stats.totalCost += result.sessionCost
       stats.totalCost += result.sessionCost
@@ -197,6 +205,16 @@ async function aggregateSessionStats(days?: number, projectFilter?: string): Pro
   }
   }
   stats.days = actualDays
   stats.days = actualDays
   stats.costPerDay = stats.totalCost / actualDays
   stats.costPerDay = stats.totalCost / actualDays
+  const totalTokens = stats.totalTokens.input + stats.totalTokens.output + stats.totalTokens.reasoning
+  stats.tokensPerSession = filteredSessions.length > 0 ? totalTokens / filteredSessions.length : 0
+  sessionTotalTokens.sort((a, b) => a - b)
+  const mid = Math.floor(sessionTotalTokens.length / 2)
+  stats.medianTokensPerSession =
+    sessionTotalTokens.length === 0
+      ? 0
+      : sessionTotalTokens.length % 2 === 0
+        ? (sessionTotalTokens[mid - 1] + sessionTotalTokens[mid]) / 2
+        : sessionTotalTokens[mid]
 
 
   return stats
   return stats
 }
 }
@@ -227,8 +245,12 @@ export function displayStats(stats: SessionStats, toolLimit?: number) {
   console.log("├────────────────────────────────────────────────────────┤")
   console.log("├────────────────────────────────────────────────────────┤")
   const cost = isNaN(stats.totalCost) ? 0 : stats.totalCost
   const cost = isNaN(stats.totalCost) ? 0 : stats.totalCost
   const costPerDay = isNaN(stats.costPerDay) ? 0 : stats.costPerDay
   const costPerDay = isNaN(stats.costPerDay) ? 0 : stats.costPerDay
+  const tokensPerSession = isNaN(stats.tokensPerSession) ? 0 : stats.tokensPerSession
   console.log(renderRow("Total Cost", `$${cost.toFixed(2)}`))
   console.log(renderRow("Total Cost", `$${cost.toFixed(2)}`))
-  console.log(renderRow("Cost/Day", `$${costPerDay.toFixed(2)}`))
+  console.log(renderRow("Avg Cost/Day", `$${costPerDay.toFixed(2)}`))
+  console.log(renderRow("Avg Tokens/Session", formatNumber(Math.round(tokensPerSession))))
+  const medianTokensPerSession = isNaN(stats.medianTokensPerSession) ? 0 : stats.medianTokensPerSession
+  console.log(renderRow("Median Tokens/Session", formatNumber(Math.round(medianTokensPerSession))))
   console.log(renderRow("Input", formatNumber(stats.totalTokens.input)))
   console.log(renderRow("Input", formatNumber(stats.totalTokens.input)))
   console.log(renderRow("Output", formatNumber(stats.totalTokens.output)))
   console.log(renderRow("Output", formatNumber(stats.totalTokens.output)))
   console.log(renderRow("Cache Read", formatNumber(stats.totalTokens.cache.read)))
   console.log(renderRow("Cache Read", formatNumber(stats.totalTokens.cache.read)))