Commit e74e229
authored
🤖 fix: preserve cost history across message compaction (#612)
## Problem
Message compaction ( command) was destroying all historical cost data,
causing displayed costs to be dramatically lower than actual API spend.
This was especially noticeable in long chats with multiple compactions.
### Root Cause
When compaction runs:
1. It creates a single summary message
2. Calls `replaceChatHistory()` which deletes all previous messages
3. Cost calculation only reads from current messages
4. Result: All accumulated costs from deleted messages are lost forever
**Example:**
```
Chat with 3 messages → bash.53 accumulated
Run /compact → Summary costs bash.05
Displayed total: bash.05 ❌ (lost bash.48!)
```
Multiple compactions = multiple cost resets, making long chats appear
nearly free.
## Solution
Store cumulative historical costs in the summary message metadata,
creating a self-documenting chain that preserves costs across
compactions.
### Implementation
1. **Added `historicalUsage` field** to `MuxMetadata`
- Stores cumulative `ChatUsageDisplay` from all pre-compaction messages
- Only present on compaction summary messages
2. **Updated `performCompaction()`** to calculate and store totals
- Calls `getWorkspaceUsage()` before replacing history
- Sums all current costs with `sumUsageHistory()`
- Stores in summary message metadata
3. **Updated `getWorkspaceUsage()`** to include historical costs
- Checks each message for `historicalUsage` field
- Prepends historical costs to current usage array
- Totals now include both historical and current costs
### Cost Chain Example
```
Before 1st compact:
[Msg A: bash.15] [Msg B: bash.20] [Msg C: bash.18]
Total: bash.53
After 1st compact:
[Summary with historicalUsage=bash.53]
Displayed: bash.53 + bash.05 (summary) = bash.58 ✅
Continue chatting:
[Summary: historical=bash.53, own=bash.05] [Msg D: bash.10] [Msg E: bash.12]
Total: bash.80
After 2nd compact:
[Summary2 with historicalUsage=bash.80]
Displayed: bash.80 + bash.04 (summary) = bash.84 ✅
```
## Testing
Manually tested:
- ✅ Fresh workspace → compact → costs preserved
- ✅ Multiple compactions → costs chain correctly
- ✅ Old sessions without `historicalUsage` → backwards compatible
- ✅ Typechecks pass
## Changes
- `src/types/message.ts`: Add `historicalUsage` field (+1 line)
- `src/stores/WorkspaceStore.ts`: Calculate and include historical costs
(+36 lines)
- **Total: 37 LoC**
_Generated with `mux`_1 parent b291885 commit e74e229
2 files changed
+38
-12
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
| |||
405 | 406 | | |
406 | 407 | | |
407 | 408 | | |
| 409 | + | |
408 | 410 | | |
409 | 411 | | |
410 | | - | |
411 | | - | |
412 | | - | |
413 | | - | |
414 | | - | |
415 | | - | |
416 | | - | |
417 | | - | |
418 | | - | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
419 | 429 | | |
420 | | - | |
421 | | - | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
422 | 433 | | |
423 | 434 | | |
424 | 435 | | |
425 | 436 | | |
426 | | - | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
427 | 444 | | |
428 | 445 | | |
429 | 446 | | |
| |||
606 | 623 | | |
607 | 624 | | |
608 | 625 | | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
609 | 632 | | |
610 | 633 | | |
611 | 634 | | |
| |||
621 | 644 | | |
622 | 645 | | |
623 | 646 | | |
| 647 | + | |
624 | 648 | | |
625 | 649 | | |
626 | 650 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
44 | 45 | | |
45 | 46 | | |
46 | 47 | | |
| 48 | + | |
47 | 49 | | |
48 | 50 | | |
49 | 51 | | |
| |||
0 commit comments