personal memory agent
0
fork

Configure Feed

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

tokens: restructure summary type breakdown in header

Replace flat Generate/Cogitate cost items with a two-row summary table in the tokens header card.

- Preserve the top-row overall summary metrics (Daily Total, Total Tokens, Requests, Avg/Segment)
- Add per-type columns for Cost, Tokens, Requests, and Avg/Req
- Update renderDashboard() to populate all per-type fields with zero-data fallbacks
- Remove redundant summary-type label classes and unreliable table padding-top styling

+98 -28
+98 -28
apps/tokens/workspace.html
··· 6 6 <div class="dashboard-content" id="dashboard" style="display: none;"> 7 7 <!-- Daily Summary Card --> 8 8 <div class="summary-card"> 9 - <div class="summary-item"> 10 - <div class="summary-label">Daily Total</div> 11 - <div class="summary-value" id="total-cost">$0.00</div> 9 + <div class="summary-row"> 10 + <div class="summary-item"> 11 + <div class="summary-label">Daily Total</div> 12 + <div class="summary-value" id="total-cost">$0.00</div> 13 + </div> 14 + <div class="summary-item"> 15 + <div class="summary-label">Total Tokens</div> 16 + <div class="summary-value" id="total-tokens">0</div> 17 + </div> 18 + <div class="summary-item"> 19 + <div class="summary-label">Requests</div> 20 + <div class="summary-value" id="total-requests">0</div> 21 + </div> 22 + <div class="summary-item"> 23 + <div class="summary-label">Avg/Segment</div> 24 + <div class="summary-value" id="segment-avg-cost">-</div> 25 + </div> 12 26 </div> 13 - <div class="summary-item"> 14 - <div class="summary-label">Total Tokens</div> 15 - <div class="summary-value" id="total-tokens">0</div> 16 - </div> 17 - <div class="summary-item"> 18 - <div class="summary-label">Requests</div> 19 - <div class="summary-value" id="total-requests">0</div> 20 - </div> 21 - <div class="summary-item"> 22 - <div class="summary-label">Avg/Segment</div> 23 - <div class="summary-value" id="segment-avg-cost">-</div> 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> 27 + <table class="summary-type-table"> 28 + <thead> 29 + <tr> 30 + <th></th> 31 + <th>Cost</th> 32 + <th>Tokens</th> 33 + <th>Requests</th> 34 + <th>Avg/Req</th> 35 + </tr> 36 + </thead> 37 + <tbody> 38 + <tr> 39 + <td>Generate</td> 40 + <td id="generate-cost">$0.00</td> 41 + <td id="generate-tokens">0</td> 42 + <td id="generate-requests">0</td> 43 + <td id="generate-avg">-</td> 44 + </tr> 45 + <tr> 46 + <td>Cogitate</td> 47 + <td id="cogitate-cost">$0.00</td> 48 + <td id="cogitate-tokens">0</td> 49 + <td id="cogitate-requests">0</td> 50 + <td id="cogitate-avg">-</td> 51 + </tr> 52 + </tbody> 53 + </table> 33 54 </div> 34 55 35 56 <!-- By Provider --> ··· 173 194 174 195 .summary-card { 175 196 display: flex; 176 - gap: 2em; 177 - justify-content: center; 197 + flex-direction: column; 198 + align-items: center; 178 199 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 179 200 color: white; 180 201 border-radius: 12px; ··· 183 204 box-shadow: 0 4px 15px rgba(0,0,0,0.1); 184 205 } 185 206 207 + .summary-row { 208 + display: flex; 209 + gap: 2em; 210 + justify-content: center; 211 + width: 100%; 212 + } 213 + 186 214 .summary-item { 187 215 text-align: center; 188 216 } ··· 198 226 font-weight: bold; 199 227 } 200 228 229 + .summary-type-table { 230 + width: 100%; 231 + border-collapse: collapse; 232 + margin-top: 1.5em; 233 + border-top: 1px solid rgba(255,255,255,0.2); 234 + } 235 + 236 + .summary-type-table th { 237 + text-align: right; 238 + font-size: 0.75em; 239 + opacity: 0.7; 240 + padding: 0.3em 1em; 241 + font-weight: normal; 242 + } 243 + 244 + .summary-type-table th:first-child { 245 + text-align: left; 246 + } 247 + 248 + .summary-type-table td { 249 + text-align: right; 250 + font-size: 1.3em; 251 + font-weight: bold; 252 + padding: 0.3em 1em; 253 + } 254 + 255 + .summary-type-table td:first-child { 256 + text-align: left; 257 + font-size: 0.9em; 258 + font-weight: 600; 259 + opacity: 0.9; 260 + } 261 + 201 262 .breakdown-section { 202 263 margin-bottom: 3em; 203 264 } ··· 403 464 segmentAvgEl.textContent = '-'; 404 465 } 405 466 406 - // Update type breakdown costs 467 + // Update type breakdown rows 407 468 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); 469 + ['generate', 'cogitate'].forEach(type => { 470 + const d = byType[type] || {}; 471 + const cost = d.cost || 0; 472 + const tokens = d.tokens || 0; 473 + const requests = d.requests || 0; 474 + const avg = requests > 0 ? cost / requests : 0; 475 + document.getElementById(`${type}-cost`).textContent = formatCost(cost); 476 + document.getElementById(`${type}-tokens`).textContent = formatNumber(tokens); 477 + document.getElementById(`${type}-requests`).textContent = formatNumber(requests); 478 + document.getElementById(`${type}-avg`).textContent = requests > 0 ? formatCost(avg) : '-'; 479 + }); 410 480 411 481 // Render provider table 412 482 renderProviderTable(data.by_provider);