4.6 KiB
4.6 KiB
Token Tracking Fixes - Summary
Issues Fixed
1. Plan Messages Now Use 1x Multiplier
Location: chat/server.js:4013
- Problem: Plan messages were using
getModelTier(model || providerName)which could return 'plus' or 'pro' tier, causing plan tokens to be counted at 2x or 3x multiplier - Fix: Changed to
getModelTier(model || providerName, 'free')to force plan messages to use 'free' tier (1x multiplier) - Impact: Plan messages (OpenRouter, Mistral, Google, Groq, NVIDIA) now always counted at 1x multiplier regardless of the model used
2. Missing Tier Information Defaults to 1x Usage
Location: chat/server.js:2508-2523
- Problem: Models without configured tiers could have inconsistent tier detection
- Fix: Enhanced
getModelTier()function with:- Optional
forceTierparameter to override tier when needed - Better validation to check if tier is in
VALID_TIERSbefore using it - Default to 'free' (1x) if tier is not configured
- Optional
- Impact: All messages with missing tier info now consistently use 1x multiplier
3. Both Plan and OpenCode Tokens Counted in Overall Usage
Status: ✅ Already Working
- Location:
chat/public/builder.js:356-390 - Explanation: Builder's usage meter uses 'aggregate' tier which sums up usage across all tiers (free, plus, pro)
- Result: Plan tokens (from OpenRouter etc.) and OpenCode tokens are both included in the total usage display
4. Enhanced Debugging
Location: chat/server.js:2640
- Enhancement: Added source tracking to
recordUserTokens()logging - New Log Format:
[USAGE] recording tokens for user=${userId} tier=${safeTier} raw=${tokens} rounded=${roundedTokens} effective=${effectiveTokens} source=${caller_file} - Benefit: Helps identify where token recording is coming from (plan vs opencode)
Technical Details
Tier Multipliers
TIER_USAGE_MULTIPLIER = {
free: 1, // 1x multiplier
plus: 2, // 2x multiplier
pro: 3 // 3x multiplier
}
Token Recording Flow
Plan Messages (1x multiplier)
- User sends message to
/api/plan handlePlanMessage()processes request- Provider (OpenRouter, Mistral, etc.) generates response
extractTokenUsageFromResult()extracts actual token countrecordUserTokens(userId, 'free', tokensUsed)records at 1x multiplier- Tokens go to
bucket.usage.free
OpenCode Messages (model tier multiplier)
- User sends message to
/api/sessions/{id}/messages processMessage()handles OpenCode executiongetModelTier(message.model)determines tier from model configurationextractTokenUsageFromResult()orestimateTokensFromMessages()gets token countrecordUserTokens(userId, tier, tokensUsed)records at appropriate multiplier- Tokens go to
bucket.usage[tier](free, plus, or pro)
Usage Summary Calculation
// For each tier (free, plus, pro):
const used = bucket.usage[tier];
const limit = getPlanTokenLimits(plan, userId)[tier];
const remaining = limit - used;
const percent = (used / limit) * 100;
Testing Checklist
- Create a plan message and verify it's counted at 1x multiplier
- Create an OpenCode message and verify it's counted at model's configured tier
- Check that both plan and OpenCode tokens appear in the aggregate usage meter
- Verify logs show proper tier assignment for each message type
- Test with a model that has no tier configured (should default to 1x)
- Test with a model that has 'plus' or 'pro' tier configured
How to Verify Token Tracking
Check Server Logs
Look for these log patterns:
[PLAN] Recording tokens for successful plan: user=xxx tokens=1000 provider=openrouter model=gpt-4o
[USAGE] recording tokens for user=xxx tier=free raw=1000 rounded=1000 effective=1000 source=handlePlanMessage
[USAGE] processMessage: recording tokens user=xxx tier=plus raw=500 rounded=500 effective=1000 source=processMessage
[USAGE] Persisted token usage. New total for xxx/free: 15000
[USAGE] Persisted token usage. New total for xxx/plus: 2000
Check Client Usage Meter
Open browser DevTools Console and look for:
[USAGE] Usage summary loaded:
{
month: "2025-01",
plan: "hobby",
tiers: {
free: { used: 15000, limit: 50000, remaining: 35000, percent: 30, ... },
plus: { used: 2000, limit: 2500000, remaining: 2498000, percent: 0, ... },
pro: { used: 0, limit: 5000000, remaining: 5000000, percent: 0, ... }
}
}
Files Modified
chat/server.js- EnhancedgetModelTier()function, fixed plan message recording, enhanced loggingchat/public/builder.js- Already had aggregate tier support (no changes needed)