personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add Generate and Cogitate cost rollups to tokens summary card

The tokens app header now shows per-type cost breakdowns. The backend
aggregates by the existing `type` field (generate/cogitate) during its
single-pass loop, and the frontend displays two new summary items.
Entries without a type field are silently excluded from the type totals.

Files changed:
- apps/tokens/routes.py — by_type accumulator and API response key
- apps/tokens/workspace.html — two new summary items + JS population
- tests/fixtures/journal/tokens/20250823.jsonl — additional typed entries

+46
+23
apps/tokens/routes.py
··· 79 79 } 80 80 ) 81 81 82 + by_type: Dict[str, Dict[str, Any]] = defaultdict( 83 + lambda: { 84 + "requests": 0, 85 + "tokens": 0, 86 + "cost": 0.0, 87 + } 88 + ) 89 + 82 90 # Token type totals 83 91 token_types = { 84 92 "input": {"tokens": 0, "cost": 0.0}, ··· 156 164 by_segment[segment]["tokens"] += total_entry_tokens 157 165 by_segment[segment]["cost"] += entry_cost 158 166 by_segment[segment]["models"].add(model) 167 + 168 + # Update type breakdown (generate vs cogitate) 169 + entry_type = entry.get("type") 170 + if entry_type: 171 + by_type[entry_type]["requests"] += 1 172 + by_type[entry_type]["tokens"] += total_entry_tokens 173 + by_type[entry_type]["cost"] += entry_cost 159 174 160 175 # Update token type breakdown 161 176 token_types["input"]["tokens"] += input_tokens ··· 295 310 "by_token_type": token_types, 296 311 "by_context": context_list, 297 312 "by_segment": segment_list, 313 + "by_type": { 314 + t: { 315 + "requests": d["requests"], 316 + "tokens": d["tokens"], 317 + "cost": round(d["cost"], 6), 318 + } 319 + for t, d in by_type.items() 320 + }, 298 321 } 299 322 300 323
+13
apps/tokens/workspace.html
··· 22 22 <div class="summary-label">Avg/Segment</div> 23 23 <div class="summary-value" id="segment-avg-cost">-</div> 24 24 </div> 25 + <div class="summary-item"> 26 + <div class="summary-label">Generate</div> 27 + <div class="summary-value" id="generate-cost">$0.00</div> 28 + </div> 29 + <div class="summary-item"> 30 + <div class="summary-label">Cogitate</div> 31 + <div class="summary-value" id="cogitate-cost">$0.00</div> 32 + </div> 25 33 </div> 26 34 27 35 <!-- By Provider --> ··· 394 402 } else { 395 403 segmentAvgEl.textContent = '-'; 396 404 } 405 + 406 + // Update type breakdown costs 407 + const byType = data.by_type || {}; 408 + document.getElementById('generate-cost').textContent = formatCost((byType.generate || {}).cost || 0); 409 + document.getElementById('cogitate-cost').textContent = formatCost((byType.cogitate || {}).cost || 0); 397 410 398 411 // Render provider table 399 412 renderProviderTable(data.by_provider);
+10
tests/fixtures/journal/tokens/20250823.jsonl
··· 239 239 {"timestamp": 1755994639.0864036, "model": "gemini-2.5-flash", "context": "tests.test_gemini_generate.test_gemini_generate_with_client_reuse:186", "usage": {"input_tokens": 0, "output_tokens": 0, "cached_tokens": 0, "reasoning_tokens": 0, "total_tokens": 0}} 240 240 {"timestamp": 1755994639.090262, "model": "gemini-2.5-flash", "context": "tests.test_gemini_generate.test_gemini_generate_with_multimodal_parts:214", "usage": {"input_tokens": 0, "output_tokens": 0, "cached_tokens": 0, "reasoning_tokens": 0, "total_tokens": 0}} 241 241 {"timestamp": 1755994639.094211, "model": "gemini-2.5-flash", "context": "tests.test_gemini_generate.test_gemini_generate_with_content_objects:246", "usage": {"input_tokens": 0, "output_tokens": 0, "cached_tokens": 0, "reasoning_tokens": 0, "total_tokens": 0}} 242 + {"timestamp": 1755983201.112, "model": "gpt-5", "context": "think.detect_created.classify_new_file", "type": "generate", "usage": {"input_tokens": 900, "output_tokens": 300, "total_tokens": 1200}} 243 + {"timestamp": 1755983215.558, "model": "gemini-2.5-flash", "context": "think.detect_transcript.detect", "type": "generate", "usage": {"input_tokens": 1400, "output_tokens": 400, "cached_tokens": 100, "reasoning_tokens": 80, "total_tokens": 1800}} 244 + {"timestamp": 1755983240.904, "model": "claude-sonnet-4-5-20250929", "context": "think.muse.generate_daily_summary", "type": "generate", "usage": {"input_tokens": 2200, "output_tokens": 900, "total_tokens": 3100}} 245 + {"timestamp": 1755983262.447, "model": "gemini-2.5-flash-lite", "context": "think.detect_transcript.detect", "type": "generate", "usage": {"input_tokens": 300, "output_tokens": 80, "total_tokens": 380}} 246 + {"timestamp": 1755983289.771, "model": "gpt-5", "context": "think.detect_created.classify_new_file", "type": "generate", "usage": {"input_tokens": 650, "output_tokens": 220, "total_tokens": 870}} 247 + {"timestamp": 1755983310.216, "model": "gemini-2.5-flash", "context": "think.detect_transcript.detect", "type": "generate", "usage": {"input_tokens": 1200, "output_tokens": 350, "cached_tokens": 250, "reasoning_tokens": 120, "total_tokens": 1550}} 248 + {"timestamp": 1755983384.638, "model": "gemini-2.5-flash", "context": "muse.system.meetings", "type": "cogitate", "usage": {"input_tokens": 7600, "output_tokens": 2400, "cached_tokens": 1500, "reasoning_tokens": 900, "total_tokens": 10000}} 249 + {"timestamp": 1755983432.185, "model": "claude-sonnet-4-5-20250929", "context": "muse.system.digest", "type": "cogitate", "usage": {"input_tokens": 9800, "output_tokens": 2800, "total_tokens": 12600}} 250 + {"timestamp": 1755983479.593, "model": "gpt-5", "context": "muse.system.entities", "type": "cogitate", "usage": {"input_tokens": 6400, "output_tokens": 2100, "reasoning_tokens": 500, "total_tokens": 8500}} 251 + {"timestamp": 1755983525.049, "model": "gemini-2.5-flash", "context": "muse.system.review", "type": "cogitate", "usage": {"input_tokens": 4300, "output_tokens": 1500, "cached_tokens": 600, "reasoning_tokens": 300, "total_tokens": 5800}} 242 252 {"timestamp": 1755983785.656, "model": "gemini-2.5-flash", "context": "muse.system.meetings", "segment": "143022_300", "type": "cogitate", "usage": {"input_tokens": 5200, "output_tokens": 1800, "total_tokens": 7000, "cached_tokens": 1000, "reasoning_tokens": 500}} 243 253 {"timestamp": 1755983800.123, "model": "claude-sonnet-4-5-20250929", "context": "muse.system.digest", "type": "cogitate", "usage": {"input_tokens": 12000, "output_tokens": 3500, "total_tokens": 15500}} 244 254 {"timestamp": 1755983850.456, "model": "gemini-2.5-flash", "context": "think.detect_transcript.detect", "type": "generate", "usage": {"input_tokens": 800, "output_tokens": 200, "total_tokens": 1000}}