Skip to content

Conversation

@ethanndickson
Copy link
Member

@ethanndickson ethanndickson commented Dec 10, 2025

Summary

Introduces persistent cumulative cost tracking via session-usage.json, eliminating O(n) message iteration for cost calculation. Usage is accumulated on stream-end and persisted to disk, making costs immune to message deletion and compaction.

Schema

interface SessionUsageFile {
  byModel: Record<string, ChatUsageDisplay>;
  lastRequest?: {
    model: string;
    usage: ChatUsageDisplay;
    timestamp: number;
  };
  version: 1;
}

interface ChatUsageDisplay {
  input: { tokens: number; cost_usd?: number };
  output: { tokens: number; cost_usd?: number };
  cached: { tokens: number; cost_usd?: number };
  cacheCreate: { tokens: number; cost_usd?: number };
  reasoning: { tokens: number; cost_usd?: number };
  model?: string;
  hasUnknownCosts?: boolean;
}

File location: ~/.mux/sessions/{workspaceId}/session-usage.json

Implementation

Backend (SessionUsageService):

  • recordUsage() - Called on stream-end, atomically updates the file under workspace file lock
  • getSessionUsage() - Returns current usage, rebuilding from messages if file is missing/corrupted
  • copyUsageFile() - Copies usage file on workspace fork
  • Rebuild scans all messages to recreate usage data when needed

Frontend (WorkspaceStore):

  • Mirrors accumulation locally on stream-end events for instant UI updates
  • sessionUsage map stores per-workspace usage data
  • usageStore triggers React re-renders when usage changes
  • Loads persisted usage via IPC on workspace initialization

oRPC endpoint: workspace.getSessionUsage

Dead Code Removal

Removes historicalUsage field from MuxMetadata type and compaction logic, plus unused collectUsageHistory() function and _messages parameter in compaction handler (~280 lines total). These were redundant since session-usage.json now tracks cumulative costs independently of message history.

Bug Fix

Fixes a bug where using multiple different models in a session, then compacting, would cause costs to be under-reported if the session-usage.json file needed to be rebuilt (e.g., on upgrade when file is missing). The rebuild logic now reads historicalUsage from legacy compaction summaries and stores it under a "historical" key, ensuring pre-compaction costs are included in session totals.

Note for reviewing agents

Accounting for session-usage.json being missing or corrupted is completely out of scope

Future Steps

This JSON-file approach is a good intermediate solution. Eventually, we plan to migrate usage tracking to a SQLite database with per-step granularity (instead of per-stream/message), enabling:

  • Cost breakdown queries by time range, model, or workspace
  • Usage insights and analytics (e.g., "most expensive conversations", "cost trends over time")
  • More efficient queries without loading entire usage history into memory

The current design keeps the door open for this migration—the byModel structure maps cleanly to database rows, and the rebuild-from-messages fallback demonstrates the data is recoverable from chat history if schema changes are needed.


Generated with mux

@ethanndickson ethanndickson force-pushed the cumulative-session-usage-json branch from 0e02b48 to d2adb51 Compare December 10, 2025 06:54
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Member Author

@ethanndickson ethanndickson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Introduces SessionUsageService that persists per-model usage to
~/.mux/sessions/{workspaceId}/session-usage.json. Costs are accumulated
on stream-end and immune to message deletion/truncation/editing.

- SessionUsageService with recordUsage(), getSessionUsage(), rebuild
- Frontend WorkspaceStore mirrors accumulation for instant UI updates
- CostsTab displays sessionTotal from persisted data
- workspace.getSessionUsage oRPC endpoint
- Copies session-usage.json on workspace fork
- Rebuilds from messages if file missing/corrupted
Now that session-usage.json accumulates costs on every stream-end,
historicalUsage in compaction summaries is redundant. The new system
makes costs immune to compaction without needing this field.

- Remove historicalUsage from MuxMetadata type and schema
- Remove historicalUsage calculation from compactionHandler
- Remove historicalUsage handling from sessionUsageService rebuild
- Remove historicalUsage handling from collectUsageHistory
- Remove related tests
@ethanndickson ethanndickson force-pushed the cumulative-session-usage-json branch from 073f0c8 to e843e22 Compare December 12, 2025 01:18
@ethanndickson ethanndickson force-pushed the cumulative-session-usage-json branch from e843e22 to 503fc83 Compare December 12, 2025 01:20
@ethanndickson
Copy link
Member Author

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Keep them coming!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson ethanndickson added this pull request to the merge queue Dec 12, 2025
@ethanndickson ethanndickson removed this pull request from the merge queue due to a manual request Dec 12, 2025
@ethanndickson ethanndickson added this pull request to the merge queue Dec 12, 2025
Merged via the queue into main with commit df06795 Dec 12, 2025
18 of 20 checks passed
@ethanndickson ethanndickson deleted the cumulative-session-usage-json branch December 12, 2025 03:11
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