Skip to content

feat(cost): persist billed compaction usage on summaries - #45

Merged
Blankeos merged 2 commits into
mainfrom
feat/compaction-usage-cost
Sep 3, 2026
Merged

feat(cost): persist billed compaction usage on summaries#45
Blankeos merged 2 commits into
mainfrom
feat/compaction-usage-cost

Conversation

@Blankeos

@Blankeos Blankeos commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Capture provider TokenUsage from the compaction stream, price it with the models.dev catalog, and store it on the summary message so stats and the session footer include compaction cost without inflating context tokens.

Capture provider TokenUsage from the compaction stream, price it with
the models.dev catalog, and store it on the summary message so stats
and the session footer include compaction cost without inflating
context tokens.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 3, 2026

Copy link
Copy Markdown

Deploying crabcode with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3095acc
Status: ✅  Deploy successful!
Preview URL: https://67819024.crabcode.pages.dev
Branch Preview URL: https://feat-compaction-usage-cost.crabcode.pages.dev

View logs

Persisting usage parts was overwriting tokens_used with billed prompt
buckets, so reloaded summaries inflated the model window. Store the
summary text estimate instead and count context from content.
@Blankeos

Blankeos commented Sep 3, 2026

Copy link
Copy Markdown
Owner Author

PR Review

feat/compaction-usage-cost → main
PR: #45feat(cost): persist billed compaction usage on summaries

Merge confidence: 5/5

Was 3/5. The persist/reload inflation path is fixed (3095acc) and covered by round-trip tests.


GitHub comment body

Compaction streams now keep provider TokenUsage, price it from the models.dev catalog, and attach a usage part on the synthetic summary so stats + the session footer include compaction cost without treating those tokens as model context.

Follow-up 3095acc keeps billed buckets on the usage part. Compaction summaries persist tokens_used as the summary-text estimate, and message_context_tokens always counts summary content — so reload no longer inflates the window.

No schema migration needed.


What changed

2 commits, 6 files:

File Role
src/llm/client.rs CompactionSummary { text, usage }; accumulate ChunkType::Usage
src/session/compaction.rs attach_summary_usage; context tokens from summary text only
src/app.rs Price via discovery.get_model_pricing at compact spawn
src/stats.rs Assert summary usage parts roll into totals
src/persistence/conversions.rs Summaries keep context tokens_used, not billed buckets

Intent: billed compaction cost in stats/footer without treating those tokens as model context — including after DB reload.


Regressions

None remaining from the original 3/5 finding.

Fixed in 3095acc:

  • Persistence: compaction summaries write tokens_used from the text estimate, not usage.tokens().
  • Context: message_context_tokens always uses summary content, never billed prompt size.
  • Tests: in-memory attach + persist/reload round-trip (summary_usage_is_persisted_without_inflating_context_tokens, compaction_summary_keeps_context_token_count_not_billed_usage).

Non-blocking:

  • Cost is catalog estimate, $0 if discovery/pricing is missing; tokens still attach.
  • apply_compaction_stream_chunk ignores ResponseCompleted.usage; aisdk already forwards that as ChunkType::Usage. OK.
  • Summary usage is hidden in the chat UI (summaries are skipped). Footer cost still sums usage_cost().
  • Usage parts are not sent to the model (convert_messages uses user content).

Migrations

No. Reuses existing messages.parts JSON (type: "usage") and tokens_used. Schema v1–v3 unchanged. Old sessions simply have no compaction usage (no backfill).

replace_messages already recomputes sessions.total_cost from parts, so session cost totals pick this up without a migration.


Merge checklist

  • Related unit tests (passed)
    • compaction_stream_accumulates_usage_and_text
    • summary_usage_is_persisted_without_inflating_context_tokens (now includes persist/reload)
    • empty_summary_usage_is_not_attached
    • compaction_summary_usage_counts_toward_totals
    • usage_parts_set_tokens_used_from_billed_buckets
    • compaction_summary_keeps_context_token_count_not_billed_usage
  • cargo fmt on touched files
  • Persist/reload test: apply_soft_compactionattach_summary_usagepersistence::Message::fromSessionMessage::try_fromtotal_context_tokens unchanged
  • Fix so billed usage does not become context token_count
  • Optional smoke: footer after compact — context % drops, $ rises
  • Optional smoke: restart, reopen session — context % does not jump
  • Optional: crabcode stats on a compacted session includes the summary usage row
  • GH checks skipped (local tests are the gate)

Confidence bumps

Item Score
Original review (in-memory only) 3/5
Persist/reload test + tokens_used/token_count fix (3095acc) 5/5

Optional smoke of footer/restart would not raise the score further.

@Blankeos
Blankeos merged commit d5047a9 into main Sep 3, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant