feat(tui): add profile view toggle to Hourly tab#395
feat(tui): add profile view toggle to Hourly tab#395christian-taillon wants to merge 19 commits intojunhoyeo:mainfrom
Conversation
|
@christian-taillon is attempting to deploy a commit to the Inevitable Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
5 issues found across 18 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="crates/tokscale-core/src/sessions/mod.rs">
<violation number="1" location="crates/tokscale-core/src/sessions/mod.rs:39">
P2: Adding a required field to `UnifiedMessage` breaks deserialization of previously cached data (bincode-serialized `CachedSourceStore` includes `Vec<UnifiedMessage>`). Without a default or schema bump, older cache files become unreadable after this change.</violation>
</file>
<file name="crates/tokscale-cli/src/tui/ui/hourly_profile.rs">
<violation number="1" location="crates/tokscale-cli/src/tui/ui/hourly_profile.rs:77">
P2: `hourly.len()` counts hourly buckets, but the UI labels it as days. This will overstate the day count (e.g., 48 hours shown as 48 days). Consider using unique date count or change the label to hours.</violation>
</file>
<file name="crates/tokscale-cli/src/tui/cache.rs">
<violation number="1" location="crates/tokscale-cli/src/tui/cache.rs:57">
P2: Cache schema was expanded but schema version was not bumped, allowing old cache files to be treated as fresh and suppressing reload of new hourly/count fields.</violation>
</file>
<file name="crates/tokscale-cli/src/tui/app.rs">
<violation number="1" location="crates/tokscale-cli/src/tui/app.rs:418">
P2: apply_tab_sort_defaults sets Date sorting only for the Hourly tab and never resets cost sorting when leaving it. Because the function runs on every tab switch, visiting Hourly leaves `sort_field` as Date for Models/Agents/Daily, which changes those tabs’ ordering away from the intended cost sort (the comment says “other tabs keep cost sort”).</violation>
</file>
<file name="crates/tokscale-cli/src/main.rs">
<violation number="1" location="crates/tokscale-cli/src/main.rs:2083">
P2: The new Hourly subcommand defines `--light` and passes `json || light` into `run_hourly_report`, but the function ignores `_light_or_json` and the handler always runs the CLI report. This makes `--light` ineffective and prevents `tokscale hourly` from falling back to the TUI tab when available.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| agents: Vec<CachedAgentUsage>, | ||
| daily: Vec<CachedDailyUsage>, | ||
| #[serde(default)] | ||
| hourly: Vec<CachedHourlyUsage>, |
There was a problem hiding this comment.
P2: Cache schema was expanded but schema version was not bumped, allowing old cache files to be treated as fresh and suppressing reload of new hourly/count fields.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/tokscale-cli/src/tui/cache.rs, line 57:
<comment>Cache schema was expanded but schema version was not bumped, allowing old cache files to be treated as fresh and suppressing reload of new hourly/count fields.</comment>
<file context>
@@ -53,6 +53,8 @@ struct CachedUsageData {
agents: Vec<CachedAgentUsage>,
daily: Vec<CachedDailyUsage>,
+ #[serde(default)]
+ hourly: Vec<CachedHourlyUsage>,
graph: Option<CachedGraphData>,
total_tokens: u64,
</file context>
…oggle Support hour-granularity token consumption tracking: - Core: HourlyUsage/HourlyReport structs, get_hourly_report() with local timezone support (derives hour slot from UnifiedMessage.timestamp) - CLI: `tokscale hourly` subcommand with full client/date filters, table and JSON output, Source column showing which tool was used - TUI: dedicated Hourly tab (sort, scroll, striped rows, current-hour highlight) mirroring Daily tab patterns - Overview: press 'h' to toggle bar chart between daily/hourly granularity Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add "Cache%" column to hourly table showing cache hit multiplier - Calculate cache efficiency as cache_read / (input + cache_write) - Display "∞" for infinite ratio (cache reads, zero paid input) - Display "—" for no cache activity - Update cache calculation logic in app state - Enhance hourly and daily UI models with ratio formatting Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Distinguish genuine human input from API message count (Msgs). Detect user→assistant boundaries in Claude Code JSONL, filtering out tool_result and system messages that also use type:"user". Turn/Msgs ratio reveals agent depth per interaction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Propagate turn_count and message_count through TUI data structs, cache layer, and renderers (both narrow and full-width layouts). Also add turnCount/messageCount to daily JSON export. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rly tab The Hourly subcommand was missing the --kilo CLI arg (added upstream in junhoyeo#353) and omitted kilo from its ClientFlags initializer. Add both. Also fix the kilocode help text in the Hourly command (was "Show only Kilo usage", should match other commands: "Show only KiloCode usage"). Update TUI tab tests to reflect the new Hourly tab inserted between Daily and Stats: test_tab_all now expects 6 tabs, and tab_next/tab_prev/backtab key-switch tests include the Hourly→Stats and Stats→Hourly transitions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…stence on Hourly tab Two bugs identified in code review: 1. lib.rs: HourlyUsage.clients and .models were populated via HashSet iteration, producing non-deterministic ordering in JSON output and display. Sort both vecs before returning. 2. tui/app.rs: set_sort() called reset_selection() which forced sort_field back to Date/Descending whenever the user pressed c/t on the Hourly tab. Extract the per-tab sort default into apply_tab_sort_defaults() and call it only from tab-switch handlers (Tab, BackTab, Left, Right), not from reset_selection. This lets Cost and Tokens sorting persist while the user is on the Hourly tab. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Display cost per million tokens alongside absolute cost in all models report table variants (model-only, client,model, client,provider,model). Helps compare model efficiency at a glance — higher token usage with lower Cost/1M means better cache utilization or a cheaper model. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add HourlyViewMode enum (Table/Profile) with 'v' key to toggle - Create hourly_profile.rs with time-of-day and weekday breakdowns - Add aggregation helpers: aggregate_by_period, aggregate_by_weekday, find_peak_hour - Update footer to show [v:profile] hint on Hourly tab - Add unit tests for HourlyViewMode toggle behavior
Remove total_cost fields from PeriodBucket and WeekdayBucket that were calculated but never displayed in profile view.
- Wide terminals (>100 chars): 30-char bars - Medium terminals (80-100 chars): 24-char bars - Narrow terminals (<80 chars): 18-char bars - Consistent bar width for both period and weekday sections
Calculate bar width dynamically based on terminal width: - Bar width = inner.width - 36 (overhead for labels, etc.) - Clamp between 20-80 chars for reasonable display - Uses most of the available horizontal space
b5a1b6f to
e81a82b
Compare
Dependency NoteThis PR builds on top of #359 (feat: add hourly usage report). That PR should be merged first. I've tested #359 extensively and experienced no bugs - any issues I reported earlier were false positives. The hourly tab foundation is solid and ready to merge. Testing Summary for #359:
|
Older cached message entries without is_turn_start will now deserialize safely with the field defaulting to false, ensuring backward compatibility with existing caches.
The summary line was incorrectly showing the count of hourly data points as days. Changed to hours to accurately reflect the data being displayed.
…ht handling - Add missing --crush flag to Hourly command definition and handler - Add missing use_env_roots field to ReportOptions in run_hourly_report - Remove unused _light_or_json parameter from run_hourly_report - Ignore --light flag in Hourly command (was misleading, now a no-op) The --light flag for Hourly was being passed but never used, creating misleading behavior. It now behaves consistently with the actual implementation.
Review Outcome Summary (cubic findings)All findings from @cubic have been assessed and addressed: Fixed
False Positive
Already Fixed
ValidationResult: 470 passed (core), 74 passed (cli) All changes are minimal and scoped to the reported findings. |
@christian-taillon The fixes for cache compatibility, labels, and the CLI signature look solid and address the concerns accurately. Regarding the TUI JSON cache versioning: I suggested versioning because On sort persistence: I see the logic in One small detail in These updates effectively resolve the issues I flagged. For more details on how I handle memory and learnings, you can check out the Cubic documentation on learnings. |
There was a problem hiding this comment.
1 issue found across 4 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="crates/tokscale-cli/src/main.rs">
<violation number="1" location="crates/tokscale-cli/src/main.rs:2359">
P1: Hourly report ignores `--home` because report options are hardcoded to `home_dir: None` and env roots.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
Good catch! The |
|
Maintainers, I want to be clear, I built off #395 which I think is a good feature. Happy to do a round or two of rebasing for other PRs - I do reccomend @crhan's PR be merged. Happy to do another round of conflict resolution - I do intend to use this feature long term so please let me know if you'd like changes pre-merge. |
Summary
Adds a profile view toggle to the Hourly tab in Tokscale TUI, allowing users to switch between a detailed table view and an aggregated profile view showing usage patterns by time-of-day and day-of-week. Also includes several enhancements to the hourly report feature.
Changes
Core Feature: Profile View Toggle
HourlyViewModeenum (Table/Profile) with 'v' key to toggle viewsProfile View Enhancements
Additional Hourly Report Improvements
Testing
How to Use
Summary by cubic
Adds a profile view toggle to the TUI Hourly tab so you can switch between the table and an aggregated profile of usage by time-of-day and weekday. Also ships hour-level reporting across core, CLI, and TUI, plus cache efficiency and turn/message insights.
New Features
hourlysubcommand with filters/JSON and a Source column, and a new TUI tab.Bug Fixes
hourly(--kilo,--crush,--home); make--lighta no-op; fix report options.is_turn_start.Written for commit 2802c9c. Summary will update on new commits.