{
+ let extra = snapshot.usage(&account.id)?.extra_usage.as_ref()?;
+ if !extra.enabled || account.auth == AuthKind::ApiKey {
+ return None;
+ }
+ let value = extra
+ .used_percent
+ .map(|percent| format::percent_label(Some(percent)))
+ .or(extra.balance_usd.map(format::money_usd))
+ .or(extra.spent_usd.map(format::money_usd))
+ .unwrap_or_else(|| "On".into());
+ let color = pressure_color(format::pressure(extra.used_percent), cx);
+ let title = if account.on_threshold == OnThreshold::Spill {
+ "Extra · spills"
+ } else {
+ "Extra usage"
+ };
+ Some(
+ v_flex()
+ .w_24()
+ .flex_shrink_0()
+ .gap_1()
+ .child(muted(title, cx))
+ .child(div().text_sm().text_color(color).child(value)),
+ )
+}
+
+impl AccountsPage {
+ fn account_row(
+ &self,
+ snapshot: &DashboardSnapshot,
+ account: &Account,
+ now: DateTime
,
+ busy: bool,
+ window: &mut Window,
+ cx: &mut Context,
+ ) -> impl IntoElement {
+ let state = snapshot.state(account.provider);
+ let active =
+ state.and_then(|state| state.active_account_id.as_deref()) == Some(account.id.as_str());
+ let just_switched = active
+ && state
+ .and_then(|state| state.switched_at.as_deref())
+ .and_then(format::parse_time)
+ .is_some_and(|at| (now - at).num_seconds() < RECENT_SWITCH_SECONDS);
+ let usage = snapshot.usage(&account.id);
+ let credits = usage
+ .and_then(|usage| usage.reset_credits.as_ref())
+ .filter(|credits| credits.available > 0);
+ let extra_enabled = usage
+ .and_then(|usage| usage.extra_usage.as_ref())
+ .is_some_and(|extra| extra.enabled)
+ && account.auth != AuthKind::ApiKey;
+
+ let mut details: Vec = Vec::new();
+ if let Some(plan) = format::plan_label(account.plan.as_deref()) {
+ details.push(Tag::secondary().small().child(plan).into_any_element());
+ }
+ if account.auth == AuthKind::ApiKey {
+ details.push(Tag::secondary().small().child("API key").into_any_element());
+ }
+ if let Some(credits) = credits {
+ let tag = if credits.applicable > 0 {
+ Tag::success()
+ } else {
+ Tag::secondary()
+ };
+ details.push(
+ tag.small()
+ .child(format!(
+ "{} reset{}",
+ credits.available,
+ if credits.available == 1 { "" } else { "s" }
+ ))
+ .into_any_element(),
+ );
+ }
+ if let Some(badge) = format::health_badge(account.health) {
+ let tag = match badge.pressure {
+ Pressure::Bad => Tag::danger(),
+ Pressure::Warn => Tag::warning(),
+ _ => Tag::secondary(),
+ };
+ details.push(tag.small().child(badge.text).into_any_element());
+ }
+ if just_switched {
+ details.push(
+ Tag::info()
+ .small()
+ .child("Just switched")
+ .into_any_element(),
+ );
+ }
+
+ let windows = format::account_windows(snapshot, account);
+ let meters: AnyElement = if account.auth == AuthKind::ApiKey {
+ let spend = usage
+ .and_then(|usage| usage.measured_spend_usd)
+ .unwrap_or_default();
+ v_flex()
+ .w_32()
+ .gap_1()
+ .child(muted("Spend · 31 days", cx))
+ .child(div().text_sm().child(format::money_usd(spend)))
+ .into_any_element()
+ } else if windows.is_empty() {
+ muted("No limits reported yet", cx).into_any_element()
+ } else {
+ h_flex()
+ .gap_4()
+ .children(
+ windows
+ .iter()
+ .take(WINDOWS_PER_ROW)
+ .map(|usage_window| window_meter(usage_window, now, cx)),
+ )
+ .into_any_element()
+ };
+
+ let store = self.store.clone();
+ let provider = account.provider;
+ let id = account.id.clone();
+ let primary: AnyElement = if account.health.needs_login() {
+ Button::new(SharedString::from(format!("relogin-{id}")))
+ .small()
+ .label("Sign in again")
+ .disabled(busy)
+ .on_click(
+ window.listener_for(&store, move |store, _, _, cx| store.sign_in(provider, cx)),
+ )
+ .into_any_element()
+ } else if active {
+ div().w_16().into_any_element()
+ } else {
+ let target = id.clone();
+ Button::new(SharedString::from(format!("use-{id}")))
+ .small()
+ .outline()
+ .label("Use")
+ .disabled(busy)
+ .on_click(window.listener_for(&store, move |store, _, _, cx| {
+ store.switch(provider, target.clone(), cx)
+ }))
+ .into_any_element()
+ };
+
+ let account_for_menu = account.clone();
+ let has_credits = credits.is_some();
+ let menu_store = store.clone();
+ let more = Button::new(SharedString::from(format!("more-{id}")))
+ .small()
+ .ghost()
+ .icon(Icon::new(IconName::Ellipsis))
+ .disabled(busy)
+ .dropdown_menu(move |menu, window, _| {
+ let account = account_for_menu.clone();
+ let mut menu = menu.min_w(px(200.));
+ if !active && !account.health.needs_login() {
+ let target = account.id.clone();
+ menu = menu.item(PopupMenuItem::new("Use this account").on_click(
+ window.listener_for(&menu_store, move |store, _, _, cx| {
+ store.switch(account.provider, target.clone(), cx)
+ }),
+ ));
+ }
+ if has_credits {
+ let store = menu_store.clone();
+ let account = account.clone();
+ menu = menu.item(PopupMenuItem::new("Reset a window…").on_click(
+ move |_, window, cx| {
+ dialogs::open_reset_credits(store.clone(), account.clone(), window, cx)
+ },
+ ));
+ }
+ if extra_enabled {
+ let spill = account.on_threshold == OnThreshold::Spill;
+ let toggled = Account {
+ on_threshold: if spill {
+ OnThreshold::Switch
+ } else {
+ OnThreshold::Spill
+ },
+ ..account.clone()
+ };
+ menu = menu.item(
+ PopupMenuItem::new("Spill into extra usage at the threshold")
+ .checked(spill)
+ .on_click(window.listener_for(&menu_store, move |store, _, _, cx| {
+ let toggled = toggled.clone();
+ store.perform(
+ "Saving…",
+ async move { crate::ipc::save_account(&toggled).await },
+ |_, _, _| {},
+ cx,
+ )
+ })),
+ );
+ }
+ if account.auth == AuthKind::Oauth {
+ menu = menu.item(PopupMenuItem::new("Sign in again").on_click(
+ window.listener_for(&menu_store, move |store, _, _, cx| {
+ store.sign_in(account.provider, cx)
+ }),
+ ));
+ }
+ let store = menu_store.clone();
+ menu.separator()
+ .item(
+ PopupMenuItem::new("Sign out…").on_click(move |_, window, cx| {
+ dialogs::open_sign_out(store.clone(), account.clone(), window, cx)
+ }),
+ )
+ });
+
+ h_flex()
+ .id(SharedString::from(format!("row-{}", account.id)))
+ .gap_4()
+ .px_4()
+ .py_3()
+ .items_center()
+ .child(
+ div()
+ .w_4()
+ .flex_shrink_0()
+ .flex()
+ .justify_center()
+ .when(active, |this| {
+ this.child(div().size_2().rounded_full().bg(cx.theme().success))
+ }),
+ )
+ .child(
+ v_flex()
+ .flex_1()
+ .min_w_0()
+ .gap_1()
+ .child(
+ div()
+ .text_sm()
+ .truncate()
+ .when(active, |this| this.font_semibold())
+ .child(account.label.clone()),
+ )
+ .child(h_flex().gap_1().flex_wrap().children(details)),
+ )
+ .child(meters)
+ .children(extra_usage_cell(snapshot, account, cx))
+ .child(
+ h_flex()
+ .gap_1()
+ .w_24()
+ .justify_end()
+ .flex_shrink_0()
+ .child(primary)
+ .child(more),
+ )
+ }
+
+ fn provider_section(
+ &self,
+ provider: Provider,
+ window: &mut Window,
+ cx: &mut Context,
+ ) -> impl IntoElement {
+ let store = self.store.read(cx);
+ let snapshot = store.analytics.snapshot.clone();
+ let routed = store.routing.routed.get(provider);
+ let cli_present = store.routing.clis.get(provider);
+ let busy = store.is_busy();
+ let now = Utc::now();
+ let policy = snapshot.state(provider).map(|state| state.policy.clone());
+
+ let status = if !routed {
+ Tag::warning().small().child("Off")
+ } else if let Some(policy) = policy.as_ref().filter(|policy| policy.enabled) {
+ Tag::success()
+ .small()
+ .child(format!("Auto-switch at {}%", policy.threshold_percent))
+ } else {
+ Tag::secondary().small().child("Auto-switch off")
+ };
+
+ let session = snapshot.active_account(provider).and_then(|account| {
+ snapshot
+ .usage(&account.id)?
+ .windows
+ .iter()
+ .find(|window| format::is_five_hour_window(window))
+ .and_then(|window| format::short_reset(window.reset_at.as_deref(), now))
+ .map(|reset| format!("{} · session resets in {reset}", account.label))
+ });
+
+ let accounts = format::ordered_accounts(&snapshot, provider);
+ let rows: Vec = accounts
+ .iter()
+ .enumerate()
+ .map(|(index, account)| {
+ div()
+ .when(index > 0, |this| {
+ this.border_t_1().border_color(cx.theme().border)
+ })
+ .child(self.account_row(&snapshot, account, now, busy, window, cx))
+ .into_any_element()
+ })
+ .collect();
+
+ let entity = self.store.clone();
+ let add = Button::new(SharedString::from(format!("add-{}", provider.cli())))
+ .small()
+ .icon(Icon::new(IconName::Plus))
+ .label("Add account")
+ .disabled(busy)
+ .on_click(move |_, window, cx| {
+ dialogs::open_add_account(entity.clone(), provider, cli_present, window, cx)
+ });
+
+ let turn_on_store = self.store.clone();
+ v_flex()
+ .gap_2()
+ .child(
+ h_flex()
+ .gap_2()
+ .items_center()
+ .child(section_title(provider.title(), cx))
+ .child(status)
+ .child(div().flex_1())
+ .child(add),
+ )
+ .when(!routed, |this| {
+ this.child(
+ h_flex()
+ .gap_3()
+ .px_4()
+ .py_2()
+ .items_center()
+ .rounded(cx.theme().radius)
+ .bg(cx.theme().warning.opacity(0.12))
+ .child(Icon::new(IconName::TriangleAlert).text_color(cx.theme().warning))
+ .child(div().flex_1().text_sm().child(format!(
+ "tokenmaxx is off for {}. It talks straight to the provider with its own login.",
+ provider.cli()
+ )))
+ .child(
+ Button::new(SharedString::from(format!("route-{}", provider.cli())))
+ .small()
+ .label("Turn on")
+ .disabled(busy)
+ .on_click(window.listener_for(&turn_on_store, move |store, _, _, cx| {
+ store.set_routing(RoutingTarget::from(provider), true, cx)
+ })),
+ ),
+ )
+ })
+ .child(
+ v_flex()
+ .rounded(cx.theme().radius_lg)
+ .border_1()
+ .border_color(cx.theme().border)
+ .bg(cx.theme().group_box)
+ .when(rows.is_empty(), |this| {
+ this.child(
+ div().px_4().py_3().child(muted(
+ if cli_present {
+ format!("No {} accounts yet.", provider.title())
+ } else {
+ format!("Install {} to sign in, or add an API key.", provider.cli())
+ },
+ cx,
+ )),
+ )
+ })
+ .children(rows),
+ )
+ .children(session.map(|session| muted(session, cx)))
+ }
+}
+
+impl Render for AccountsPage {
+ fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement {
+ let store = self.store.read(cx);
+ let age = store
+ .analytics
+ .snapshot
+ .usage
+ .iter()
+ .filter_map(|usage| format::parse_time(&usage.observed_at))
+ .max()
+ .map(|observed| format!("Updated {} ago", format::relative_age(observed, Utc::now())));
+ let refreshing = store.busy.as_deref() == Some("Refreshing…");
+ let busy = store.is_busy();
+ let connection = store.connection.clone();
+ let refresh_store = self.store.clone();
+
+ v_flex()
+ .gap_6()
+ .child(page_header(
+ "Accounts",
+ h_flex()
+ .gap_3()
+ .items_center()
+ .children(age.map(|age| muted(age, cx)))
+ .child(
+ Button::new("refresh")
+ .small()
+ .icon(Icon::new(IconName::RefreshCw))
+ .label("Refresh")
+ .loading(refreshing)
+ .disabled(busy)
+ .on_click(
+ window.listener_for(&refresh_store, |store, _, _, cx| {
+ store.refresh(cx)
+ }),
+ ),
+ ),
+ ))
+ .when_some(
+ match connection {
+ Connection::Failed(message) => Some(message),
+ _ => None,
+ },
+ |this, message| this.child(muted(format!("Not connected: {message}"), cx)),
+ )
+ .child(self.provider_section(Provider::Openai, window, cx))
+ .child(self.provider_section(Provider::Anthropic, window, cx))
+ }
+}
diff --git a/gui/src/views/analytics.rs b/gui/src/views/analytics.rs
new file mode 100644
index 0000000..c087641
--- /dev/null
+++ b/gui/src/views/analytics.rs
@@ -0,0 +1,314 @@
+use gpui_kit::component::StyledExt as _;
+use gpui_kit::component::chart::AreaChart;
+use gpui_kit::component::tab::TabBar;
+use gpui_kit::component::{ActiveTheme as _, Sizable as _, h_flex, v_flex};
+use gpui_kit::prelude::FluentBuilder as _;
+use gpui_kit::*;
+
+use crate::format;
+use crate::model::{TIMEFRAMES, TokenBreakdown, TokenTimeframe};
+use crate::store::Store;
+use crate::views::{muted, page_header, section_title};
+
+const DEFAULT_TIMEFRAME: usize = 2;
+const CHART_POINTS: usize = 48;
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+enum View {
+ Chart,
+ Pricing,
+}
+
+pub struct AnalyticsPage {
+ store: Entity,
+ timeframe: usize,
+ view: View,
+}
+
+impl AnalyticsPage {
+ pub fn new(store: Entity, cx: &mut Context) -> Self {
+ cx.observe(&store, |_, _, cx| cx.notify()).detach();
+ Self {
+ store,
+ timeframe: DEFAULT_TIMEFRAME,
+ view: View::Chart,
+ }
+ }
+}
+
+/// Downsamples by keeping each column's peak, so short bursts survive the resampling.
+fn columns(buckets: &[f64], count: usize) -> Vec {
+ if buckets.len() <= count {
+ return buckets.to_vec();
+ }
+ (0..count)
+ .map(|column| {
+ let low = column * buckets.len() / count;
+ let high = ((column + 1) * buckets.len() / count).max(low + 1);
+ buckets[low..high].iter().copied().fold(0.0, f64::max)
+ })
+ .collect()
+}
+
+fn ago_label(milliseconds: f64) -> String {
+ let minutes = (milliseconds / 60_000.0).round();
+ if minutes < 1.0 {
+ "now".into()
+ } else if minutes < 60.0 {
+ format!("{minutes}m")
+ } else if minutes < 48.0 * 60.0 {
+ format!("{}h", (minutes / 60.0).round())
+ } else {
+ format!("{}d", (minutes / 1440.0).round())
+ }
+}
+
+fn stat(title: &'static str, value: String, cx: &App) -> Div {
+ v_flex()
+ .flex_1()
+ .gap_1()
+ .p_4()
+ .rounded(cx.theme().radius_lg)
+ .border_1()
+ .border_color(cx.theme().border)
+ .bg(cx.theme().group_box)
+ .child(muted(title, cx))
+ .child(div().text_xl().font_semibold().child(value))
+}
+
+fn table_row(cells: [String; 5], emphasis: bool, cx: &App) -> Div {
+ let [name, rest @ ..] = cells;
+ h_flex()
+ .px_4()
+ .py_2()
+ .gap_4()
+ .text_sm()
+ .when(emphasis, |this| this.font_semibold())
+ .child(div().flex_1().min_w_0().truncate().child(name))
+ .children(
+ rest.into_iter()
+ .map(|cell| div().w_24().flex_shrink_0().text_right().child(cell)),
+ )
+ .border_t_1()
+ .border_color(cx.theme().border)
+}
+
+fn table_head(titles: [&'static str; 5], cx: &App) -> Div {
+ let [name, rest @ ..] = titles;
+ h_flex()
+ .px_4()
+ .py_2()
+ .gap_4()
+ .text_xs()
+ .text_color(cx.theme().muted_foreground)
+ .child(div().flex_1().child(name))
+ .children(
+ rest.into_iter()
+ .map(|title| div().w_24().flex_shrink_0().text_right().child(title)),
+ )
+}
+
+fn breakdown_row(name: String, breakdown: &TokenBreakdown, cx: &App) -> Div {
+ table_row(
+ [
+ name,
+ format::compact_number(breakdown.input),
+ format::compact_number(breakdown.output),
+ format::compact_number(breakdown.cached + breakdown.cache_creation),
+ format::money_usd(breakdown.cost_usd),
+ ],
+ false,
+ cx,
+ )
+}
+
+fn card(cx: &App) -> Div {
+ v_flex()
+ .rounded(cx.theme().radius_lg)
+ .border_1()
+ .border_color(cx.theme().border)
+ .bg(cx.theme().group_box)
+ .overflow_hidden()
+}
+
+impl AnalyticsPage {
+ fn chart(&self, timeframe: &TokenTimeframe, cx: &App) -> impl IntoElement {
+ let values = columns(&timeframe.buckets, CHART_POINTS);
+ let span = timeframe.bucket_ms * timeframe.buckets.len() as f64;
+ let step = span / values.len().max(1) as f64;
+ let points: Vec<(SharedString, f64)> = values
+ .iter()
+ .enumerate()
+ .map(|(index, value)| {
+ let remaining = span - step * (index + 1) as f64;
+ (SharedString::from(ago_label(remaining)), *value)
+ })
+ .collect();
+ let accent = cx.theme().primary;
+ card(cx)
+ .p_4()
+ .gap_2()
+ .child(section_title("Token throughput · all accounts", cx))
+ .child(
+ div().h_64().child(
+ AreaChart::new(points)
+ .x(|point: &(SharedString, f64)| point.0.clone())
+ .y(|point: &(SharedString, f64)| point.1)
+ .stroke(accent)
+ .fill(accent.opacity(0.2))
+ .tick_margin(CHART_POINTS / 6)
+ .id("throughput"),
+ ),
+ )
+ }
+
+ fn pricing(&self, timeframe: &TokenTimeframe, cx: &App) -> impl IntoElement {
+ let total = table_row(
+ [
+ "Total".into(),
+ format::compact_number(timeframe.total_input),
+ format::compact_number(timeframe.total_output),
+ format::compact_number(timeframe.total_cached + timeframe.total_cache_creation),
+ format::money_usd(timeframe.cost_usd),
+ ],
+ true,
+ cx,
+ );
+ let by_class = table_row(
+ [
+ "Value by class".into(),
+ format::money_usd(timeframe.cost_input),
+ format::money_usd(timeframe.cost_output),
+ format::money_usd(timeframe.cost_cached + timeframe.cost_cache_creation),
+ format::money_usd(timeframe.cost_usd),
+ ],
+ false,
+ cx,
+ );
+ v_flex()
+ .gap_4()
+ .child(
+ card(cx)
+ .child(table_head(
+ ["Provider", "Input", "Output", "Cache", "Value"],
+ cx,
+ ))
+ .children(timeframe.by_provider.iter().map(|breakdown| {
+ let title = crate::model::Provider::title(breakdown.provider);
+ breakdown_row(title.into(), breakdown, cx)
+ }))
+ .child(total)
+ .child(by_class),
+ )
+ .child(
+ card(cx)
+ .child(table_head(
+ ["Model", "Input", "Output", "Cache", "Value"],
+ cx,
+ ))
+ .children(timeframe.models.iter().map(|breakdown| {
+ breakdown_row(
+ breakdown.model.clone().unwrap_or_else(|| "unknown".into()),
+ breakdown,
+ cx,
+ )
+ })),
+ )
+ .child(muted(
+ "Priced at API list rates, for comparison with what a subscription covers.",
+ cx,
+ ))
+ }
+}
+
+impl Render for AnalyticsPage {
+ fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement {
+ let key = TIMEFRAMES[self.timeframe];
+ let analytics = self.store.read(cx).analytics.clone();
+ let timeframe = analytics
+ .timeframe(key)
+ .filter(|timeframe| timeframe.total_tokens > 0.0)
+ .cloned();
+ let now_per_hour = analytics
+ .tokens
+ .as_ref()
+ .map(|tokens| tokens.now_per_hour)
+ .unwrap_or_default();
+
+ let ranges = TabBar::new("timeframe")
+ .segmented()
+ .small()
+ .selected_index(self.timeframe)
+ .on_click(cx.listener(|this, index: &usize, _, cx| {
+ this.timeframe = *index;
+ cx.notify();
+ }))
+ .children(TIMEFRAMES);
+ let views = TabBar::new("view")
+ .segmented()
+ .small()
+ .selected_index(if self.view == View::Chart { 0 } else { 1 })
+ .on_click(cx.listener(|this, index: &usize, _, cx| {
+ this.view = if *index == 0 {
+ View::Chart
+ } else {
+ View::Pricing
+ };
+ cx.notify();
+ }))
+ .children(["Chart", "Pricing"]);
+
+ v_flex()
+ .gap_6()
+ .child(page_header(
+ "Analytics",
+ h_flex().gap_3().child(views).child(ranges),
+ ))
+ .map(|this| match &timeframe {
+ None => this.child(
+ card(cx)
+ .p_6()
+ .items_center()
+ .gap_1()
+ .child(
+ div()
+ .font_semibold()
+ .child(format!("No token usage in the last {key}")),
+ )
+ .child(muted(
+ "Run codex or claude and the throughput shows up here as it streams.",
+ cx,
+ )),
+ ),
+ Some(timeframe) => this
+ .child(
+ h_flex()
+ .gap_4()
+ .child(stat(
+ "Tokens",
+ format::compact_number(timeframe.total_tokens),
+ cx,
+ ))
+ .child(stat(
+ "Value at list price",
+ format::money_usd(timeframe.cost_usd),
+ cx,
+ ))
+ .child(stat(
+ "Peak per hour",
+ format::compact_number(timeframe.peak_per_hour),
+ cx,
+ ))
+ .child(stat(
+ "Now per hour",
+ format::compact_number(now_per_hour),
+ cx,
+ )),
+ )
+ .map(|this| match self.view {
+ View::Chart => this.child(self.chart(timeframe, cx)),
+ View::Pricing => this.child(self.pricing(timeframe, cx)),
+ }),
+ })
+ }
+}
diff --git a/gui/src/views/dialogs.rs b/gui/src/views/dialogs.rs
new file mode 100644
index 0000000..cb65eb7
--- /dev/null
+++ b/gui/src/views/dialogs.rs
@@ -0,0 +1,219 @@
+use gpui_kit::assets::IconName;
+use gpui_kit::component::Disableable as _;
+use gpui_kit::component::button::{Button, ButtonVariants as _};
+use gpui_kit::component::input::{Input, InputState};
+use gpui_kit::component::{ActiveTheme as _, Icon, WindowExt as _, h_flex, v_flex};
+use gpui_kit::*;
+
+use crate::format;
+use crate::ipc;
+use crate::model::{Account, Provider, ResetCode};
+use crate::store::{Store, StoreEvent};
+use crate::terminal;
+use crate::views::muted;
+
+fn footer(buttons: impl IntoIterator- ) -> Div {
+ h_flex().gap_2().justify_end().children(buttons)
+}
+
+fn cancel() -> Button {
+ Button::new("cancel")
+ .label("Cancel")
+ .on_click(|_, window, cx| window.close_dialog(cx))
+}
+
+pub fn open_add_account(
+ store: Entity,
+ provider: Provider,
+ cli_present: bool,
+ window: &mut Window,
+ cx: &mut App,
+) {
+ let key = cx.new(|cx| {
+ InputState::new(window, cx)
+ .masked(true)
+ .placeholder("API key")
+ });
+ let label = cx.new(|cx| InputState::new(window, cx).placeholder("Name shown in tokenmaxx"));
+ let terminal = terminal::resolve(store.read(cx).preferences.terminal.as_deref());
+ window.open_dialog(cx, move |dialog, _, cx| {
+ let sign_in_store = store.clone();
+ let add_store = store.clone();
+ let (key_input, label_input) = (key.clone(), label.clone());
+ let submit = move |_: &ClickEvent, window: &mut Window, cx: &mut App| {
+ let secret = key_input.read(cx).value().trim().to_string();
+ let name = label_input.read(cx).value().trim().to_string();
+ if secret.is_empty() || name.is_empty() {
+ return;
+ }
+ add_store.update(cx, |store, cx| {
+ store.perform(
+ format!("Adding {name}…"),
+ {
+ let name = name.clone();
+ async move { ipc::add_api_key(provider, &secret, &name).await }
+ },
+ move |_, _, cx| cx.emit(StoreEvent::Notice(format!("Added {name}").into())),
+ cx,
+ )
+ });
+ window.close_dialog(cx);
+ };
+ dialog
+ .title(format!("Add a {} account", provider.title()))
+ .w(px(440.))
+ .child(
+ v_flex()
+ .gap_4()
+ .child(
+ v_flex()
+ .gap_2()
+ .child(
+ Button::new("sign-in")
+ .icon(Icon::new(IconName::Terminal))
+ .label(format!("Sign in with {} in {}", provider.cli(), terminal.name))
+ .disabled(!cli_present)
+ .on_click(move |_, window, cx| {
+ sign_in_store.update(cx, |store, cx| store.sign_in(provider, cx));
+ window.close_dialog(cx);
+ }),
+ )
+ .child(muted(
+ if cli_present {
+ "Your subscription login. Finish it in the terminal window; the account appears here when done.".to_string()
+ } else {
+ format!("Install {} first to sign in with a subscription.", provider.cli())
+ },
+ cx,
+ )),
+ )
+ .child(div().h_px().bg(cx.theme().border))
+ .child(
+ v_flex()
+ .gap_2()
+ .child(div().text_sm().font_weight(FontWeight::MEDIUM).child("Or add an API key"))
+ .child(Input::new(&key))
+ .child(Input::new(&label)),
+ ),
+ )
+ .footer(footer([
+ cancel(),
+ Button::new("add-key").primary().label("Add key").on_click(submit),
+ ]))
+ });
+}
+
+pub fn open_sign_out(store: Entity, account: Account, window: &mut Window, cx: &mut App) {
+ window.open_dialog(cx, move |dialog, _, _| {
+ let store = store.clone();
+ let account = account.clone();
+ let name = account.label.clone();
+ dialog
+ .title(format!("Sign out {name}?"))
+ .w(px(420.))
+ .child(format!(
+ "tokenmaxx deletes this {} credential from your Keychain. You can sign in again at any time.",
+ account.provider.title()
+ ))
+ .footer(footer([
+ cancel(),
+ Button::new("sign-out").danger().label("Sign out").on_click(move |_, window, cx| {
+ let id = account.id.clone();
+ let name = account.label.clone();
+ store.update(cx, |store, cx| {
+ store.perform(
+ format!("Signing out {name}…"),
+ async move { ipc::remove_account(&id).await },
+ move |_, _, cx| cx.emit(StoreEvent::Notice(format!("Signed out {name}").into())),
+ cx,
+ )
+ });
+ window.close_dialog(cx);
+ }),
+ ]))
+ });
+}
+
+fn outcome_message(code: ResetCode, windows: u32) -> String {
+ match code {
+ ResetCode::Reset => format!(
+ "Reset {windows} window{}",
+ if windows == 1 { "" } else { "s" }
+ ),
+ ResetCode::NothingToReset => "Nothing to reset; the credit stays banked".into(),
+ ResetCode::NoCredit => "No reset credit is available".into(),
+ ResetCode::AlreadyRedeemed => "That credit was already redeemed".into(),
+ }
+}
+
+pub fn open_reset_credits(
+ store: Entity,
+ account: Account,
+ window: &mut Window,
+ cx: &mut App,
+) {
+ let id = account.id.clone();
+ window
+ .spawn(cx, async move |cx| {
+ let view = match ipc::reset_credits(&id).await {
+ Ok(view) => view,
+ Err(error) => {
+ store.update(cx, |_, cx| cx.emit(StoreEvent::Error(error.to_string().into())));
+ return;
+ }
+ };
+ let soonest = view
+ .credits
+ .iter()
+ .filter_map(|credit| credit.expires_at.as_deref())
+ .filter_map(format::parse_time)
+ .min();
+ cx.update(|window, cx| {
+ window.open_dialog(cx, move |dialog, _, cx| {
+ let store = store.clone();
+ let account = account.clone();
+ let expiry = soonest
+ .map(|at| {
+ format!(
+ "The soonest expires in {}.",
+ format::short_reset(Some(&at.to_rfc3339()), chrono::Utc::now()).unwrap_or_default()
+ )
+ })
+ .unwrap_or_default();
+ dialog
+ .title("Reset a rate-limit window?")
+ .w(px(420.))
+ .child(
+ v_flex()
+ .gap_2()
+ .child(format!(
+ "Spend one of {}'s {} banked reset credits to clear its current Codex windows.",
+ account.label, view.available
+ ))
+ .child(muted(expiry, cx)),
+ )
+ .footer(footer([
+ Button::new("keep").label("Keep it banked").on_click(|_, window, cx| window.close_dialog(cx)),
+ Button::new("reset").primary().label("Reset now").on_click(move |_, window, cx| {
+ let id = account.id.clone();
+ store.update(cx, |store, cx| {
+ store.perform(
+ "Resetting…",
+ async move { ipc::consume_reset(&id).await },
+ |_, outcome, cx| {
+ cx.emit(StoreEvent::Notice(
+ outcome_message(outcome.code, outcome.windows_reset).into(),
+ ))
+ },
+ cx,
+ )
+ });
+ window.close_dialog(cx);
+ }),
+ ]))
+ });
+ })
+ .ok();
+ })
+ .detach();
+}
diff --git a/gui/src/views/mod.rs b/gui/src/views/mod.rs
new file mode 100644
index 0000000..eceac3c
--- /dev/null
+++ b/gui/src/views/mod.rs
@@ -0,0 +1,46 @@
+pub mod accounts;
+pub mod analytics;
+pub mod dialogs;
+pub mod root;
+pub mod settings;
+
+use gpui_kit::component::{ActiveTheme as _, StyledExt as _};
+use gpui_kit::*;
+
+use crate::format::Pressure;
+
+pub fn pressure_color(pressure: Pressure, cx: &App) -> Hsla {
+ let theme = cx.theme();
+ match pressure {
+ Pressure::Unknown => theme.muted_foreground,
+ Pressure::Good => theme.success,
+ Pressure::Warn => theme.warning,
+ Pressure::Bad => theme.danger,
+ }
+}
+
+/// A page's title band: the heading on the leading edge and its commands on the trailing edge.
+pub fn page_header(title: &'static str, trailing: impl IntoElement) -> Div {
+ div()
+ .flex()
+ .items_center()
+ .justify_between()
+ .gap_3()
+ .child(div().text_xl().font_semibold().child(title))
+ .child(trailing)
+}
+
+pub fn section_title(title: impl Into, cx: &App) -> Div {
+ div()
+ .text_sm()
+ .font_semibold()
+ .text_color(cx.theme().foreground)
+ .child(title.into())
+}
+
+pub fn muted(text: impl Into, cx: &App) -> Div {
+ div()
+ .text_xs()
+ .text_color(cx.theme().muted_foreground)
+ .child(text.into())
+}
diff --git a/gui/src/views/root.rs b/gui/src/views/root.rs
new file mode 100644
index 0000000..0c92747
--- /dev/null
+++ b/gui/src/views/root.rs
@@ -0,0 +1,151 @@
+use gpui_kit::assets::IconName;
+use gpui_kit::component::StyledExt as _;
+use gpui_kit::component::notification::Notification;
+use gpui_kit::component::scroll::ScrollableElement as _;
+use gpui_kit::component::sidebar::{Sidebar, SidebarGroup, SidebarMenu, SidebarMenuItem};
+use gpui_kit::component::{
+ ActiveTheme as _, Icon, Root, Theme, ThemeMode, TitleBar, WindowExt as _, h_flex, v_flex,
+};
+use gpui_kit::*;
+
+use crate::prefs::Appearance;
+use crate::store::{Store, StoreEvent};
+use crate::views::accounts::AccountsPage;
+use crate::views::analytics::AnalyticsPage;
+use crate::views::settings::SettingsPage;
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Page {
+ Accounts,
+ Analytics,
+ Settings,
+}
+
+pub struct RootView {
+ store: Entity,
+ page: Page,
+ accounts: Entity,
+ analytics: Entity,
+ settings: Entity,
+ _subscriptions: Vec,
+}
+
+pub fn apply_appearance(appearance: Appearance, window: &mut Window, cx: &mut App) {
+ match appearance {
+ Appearance::Auto => Theme::sync_system_appearance(Some(window), cx),
+ Appearance::Light => Theme::change(ThemeMode::Light, Some(window), cx),
+ Appearance::Dark => Theme::change(ThemeMode::Dark, Some(window), cx),
+ }
+}
+
+impl RootView {
+ pub fn new(
+ store: Entity,
+ page: Page,
+ window: &mut Window,
+ cx: &mut Context,
+ ) -> Self {
+ apply_appearance(store.read(cx).preferences.appearance, window, cx);
+ let subscriptions = vec![
+ cx.subscribe_in(
+ &store,
+ window,
+ |_, store, event: &StoreEvent, window, cx| match event {
+ StoreEvent::Notice(message) => {
+ window.push_notification(Notification::success(message.clone()), cx)
+ }
+ StoreEvent::Error(message) => {
+ window.push_notification(Notification::error(message.clone()), cx)
+ }
+ StoreEvent::PreferencesChanged => {
+ apply_appearance(store.read(cx).preferences.appearance, window, cx)
+ }
+ },
+ ),
+ cx.observe_window_appearance(window, |this, window, cx| {
+ if this.store.read(cx).preferences.appearance == Appearance::Auto {
+ Theme::sync_system_appearance(Some(window), cx);
+ }
+ }),
+ ];
+ Self {
+ accounts: cx.new(|cx| AccountsPage::new(store.clone(), cx)),
+ analytics: cx.new(|cx| AnalyticsPage::new(store.clone(), cx)),
+ settings: cx.new(|cx| SettingsPage::new(store.clone(), window, cx)),
+ store,
+ page,
+ _subscriptions: subscriptions,
+ }
+ }
+
+ pub fn show(&mut self, page: Page, cx: &mut Context) {
+ self.page = page;
+ cx.notify();
+ }
+
+ fn menu_item(
+ &self,
+ page: Page,
+ label: &'static str,
+ icon: IconName,
+ cx: &mut Context,
+ ) -> SidebarMenuItem {
+ SidebarMenuItem::new(label)
+ .icon(Icon::new(icon))
+ .active(self.page == page)
+ .on_click(cx.listener(move |this, _, _, cx| this.show(page, cx)))
+ }
+}
+
+impl Render for RootView {
+ fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement {
+ let content: AnyView = match self.page {
+ Page::Accounts => self.accounts.clone().into(),
+ Page::Analytics => self.analytics.clone().into(),
+ Page::Settings => self.settings.clone().into(),
+ };
+ let busy = self.store.read(cx).busy.clone();
+ v_flex()
+ .size_full()
+ .bg(cx.theme().background)
+ .text_color(cx.theme().foreground)
+ .child(
+ TitleBar::new().child(
+ h_flex()
+ .flex_1()
+ .justify_between()
+ .pr_3()
+ .child(div().text_sm().font_semibold().child("tokenmaxx"))
+ .children(busy.map(|busy| {
+ div()
+ .text_xs()
+ .text_color(cx.theme().muted_foreground)
+ .child(busy)
+ })),
+ ),
+ )
+ .child(
+ h_flex()
+ .flex_1()
+ .min_h_0()
+ .child(Sidebar::new("navigation").w(px(200.)).child(
+ SidebarGroup::new("tokenmaxx").child(SidebarMenu::new().children([
+ self.menu_item(Page::Accounts, "Accounts", IconName::Users, cx),
+ self.menu_item(Page::Analytics, "Analytics", IconName::ChartArea, cx),
+ self.menu_item(Page::Settings, "Settings", IconName::Settings, cx),
+ ])),
+ ))
+ .child(
+ div().flex_1().min_w_0().h_full().child(
+ div()
+ .id("content")
+ .size_full()
+ .overflow_y_scrollbar()
+ .child(div().p_6().max_w(px(960.)).child(content)),
+ ),
+ ),
+ )
+ .children(Root::render_dialog_layer(window, cx))
+ .children(Root::render_notification_layer(window, cx))
+ }
+}
diff --git a/gui/src/views/settings.rs b/gui/src/views/settings.rs
new file mode 100644
index 0000000..3c6d82b
--- /dev/null
+++ b/gui/src/views/settings.rs
@@ -0,0 +1,491 @@
+use gpui_kit::component::Disableable as _;
+use gpui_kit::component::button::Button;
+use gpui_kit::component::menu::{DropdownMenu as _, PopupMenuItem};
+use gpui_kit::component::slider::{Slider, SliderEvent, SliderState};
+use gpui_kit::component::switch::Switch;
+use gpui_kit::component::tab::TabBar;
+use gpui_kit::component::{ActiveTheme as _, Sizable as _, h_flex, v_flex};
+use gpui_kit::prelude::FluentBuilder as _;
+use gpui_kit::*;
+use serde_json::json;
+
+use crate::cli::CommandLineTool;
+use crate::format;
+use crate::model::{Provider, RoutingTarget};
+use crate::prefs::{Appearance, Preferences, Presence};
+use crate::store::Store;
+use crate::terminal;
+use crate::views::{muted, page_header, section_title};
+
+const MINUTE: f32 = 60_000.0;
+
+struct PolicySliders {
+ threshold: Entity,
+ cooldown: Entity,
+}
+
+pub struct SettingsPage {
+ store: Entity,
+ sliders: [PolicySliders; 2],
+ _subscriptions: Vec,
+}
+
+fn slot(provider: Provider) -> usize {
+ match provider {
+ Provider::Openai => 0,
+ Provider::Anthropic => 1,
+ }
+}
+
+impl SettingsPage {
+ pub fn new(store: Entity, window: &mut Window, cx: &mut Context) -> Self {
+ let sliders = Provider::ALL.map(|_| PolicySliders {
+ threshold: cx.new(|_| {
+ SliderState::new()
+ .min(10.)
+ .max(100.)
+ .step(5.)
+ .default_value(90.)
+ }),
+ cooldown: cx.new(|_| {
+ SliderState::new()
+ .min(0.)
+ .max(60.)
+ .step(1.)
+ .default_value(5.)
+ }),
+ });
+ let mut subscriptions = vec![cx.observe_in(&store, window, |this, _, window, cx| {
+ this.sync_sliders(window, cx);
+ cx.notify();
+ })];
+ for provider in Provider::ALL {
+ let PolicySliders {
+ threshold,
+ cooldown,
+ } = &sliders[slot(provider)];
+ subscriptions.push(
+ cx.subscribe(threshold, move |this, _, event: &SliderEvent, cx| {
+ if let SliderEvent::Release(value) = event {
+ let percent = value.start().round();
+ this.store.update(cx, |store, cx| {
+ store.set_policy(provider, json!({ "thresholdPercent": percent }), cx)
+ });
+ }
+ }),
+ );
+ subscriptions.push(
+ cx.subscribe(cooldown, move |this, _, event: &SliderEvent, cx| {
+ if let SliderEvent::Release(value) = event {
+ let milliseconds = (value.start().round() * MINUTE) as u64;
+ this.store.update(cx, |store, cx| {
+ store.set_policy(
+ provider,
+ json!({ "minimumDwellMilliseconds": milliseconds }),
+ cx,
+ )
+ });
+ }
+ }),
+ );
+ }
+ let mut page = Self {
+ store,
+ sliders,
+ _subscriptions: subscriptions,
+ };
+ page.sync_sliders(window, cx);
+ page
+ }
+
+ fn sync_sliders(&mut self, window: &mut Window, cx: &mut Context) {
+ let snapshot = self.store.read(cx).analytics.snapshot.clone();
+ for provider in Provider::ALL {
+ let Some(policy) = snapshot.state(provider).map(|state| &state.policy) else {
+ continue;
+ };
+ let sliders = &self.sliders[slot(provider)];
+ let threshold = policy.threshold_percent as f32;
+ let cooldown = policy.minimum_dwell_milliseconds as f32 / MINUTE;
+ sliders.threshold.update(cx, |state, cx| {
+ if state.value().start() != threshold {
+ state.set_value(threshold, window, cx);
+ }
+ });
+ sliders.cooldown.update(cx, |state, cx| {
+ if state.value().start() != cooldown {
+ state.set_value(cooldown, window, cx);
+ }
+ });
+ }
+ }
+}
+
+fn row(
+ title: impl Into,
+ description: Option,
+ control: impl IntoElement,
+ cx: &App,
+) -> Div {
+ h_flex()
+ .gap_4()
+ .px_4()
+ .py_3()
+ .items_center()
+ .child(
+ v_flex()
+ .flex_1()
+ .min_w_0()
+ .gap_1()
+ .child(div().text_sm().child(title.into()))
+ .children(description.map(|description| muted(description, cx))),
+ )
+ .child(control)
+}
+
+fn group(title: impl Into, rows: Vec
, cx: &App) -> Div {
+ v_flex().gap_2().child(section_title(title, cx)).child(
+ v_flex()
+ .rounded(cx.theme().radius_lg)
+ .border_1()
+ .border_color(cx.theme().border)
+ .bg(cx.theme().group_box)
+ .children(rows.into_iter().enumerate().map(|(index, row)| {
+ row.when(index > 0, |this| {
+ this.border_t_1().border_color(cx.theme().border)
+ })
+ })),
+ )
+}
+
+fn slider_control(state: &Entity
, label: String, disabled: bool) -> Div {
+ h_flex()
+ .gap_3()
+ .w_64()
+ .child(div().flex_1().child(Slider::new(state).disabled(disabled)))
+ .child(div().w_12().text_sm().text_right().child(label))
+}
+
+impl SettingsPage {
+ fn provider_group(
+ &self,
+ provider: Provider,
+ window: &mut Window,
+ cx: &mut Context,
+ ) -> Div {
+ let store = self.store.read(cx);
+ let busy = store.is_busy();
+ let routed = store.routing.routed.get(provider);
+ let snapshot = &store.analytics.snapshot;
+ let Some(policy) = snapshot.state(provider).map(|state| state.policy.clone()) else {
+ return div();
+ };
+ let windows = format::provider_windows(snapshot, provider);
+ let sliders = &self.sliders[slot(provider)];
+ let threshold = sliders.threshold.read(cx).value().start().round();
+ let cooldown = (sliders.cooldown.read(cx).value().start().round() * MINUTE) as u64;
+ let entity = self.store.clone();
+
+ let mut rows = vec![
+ row(
+ "Route through tokenmaxx",
+ Some(
+ format!(
+ "{} sends requests through the local proxy, which picks the account.",
+ provider.cli()
+ )
+ .into(),
+ ),
+ Switch::new(SharedString::from(format!("routing-{}", provider.cli())))
+ .checked(routed)
+ .disabled(busy)
+ .on_click(
+ window.listener_for(&entity, move |store, checked: &bool, _, cx| {
+ store.set_routing(RoutingTarget::from(provider), *checked, cx)
+ }),
+ ),
+ cx,
+ ),
+ row(
+ "Switch accounts automatically",
+ Some(
+ "Moves to the account with the most room when the active one fills up.".into(),
+ ),
+ Switch::new(SharedString::from(format!("auto-{}", provider.cli())))
+ .checked(policy.enabled)
+ .disabled(busy)
+ .on_click(
+ window.listener_for(&entity, move |store, checked: &bool, _, cx| {
+ let changes = if *checked {
+ json!({ "enabled": true, "authorizationConfirmed": true })
+ } else {
+ json!({ "enabled": false })
+ };
+ store.set_policy(provider, changes, cx)
+ }),
+ ),
+ cx,
+ ),
+ row(
+ "Switch at",
+ Some("Measured against the active account's fullest rate-limit window.".into()),
+ slider_control(&sliders.threshold, format!("{threshold}%"), busy),
+ cx,
+ ),
+ row(
+ "Cooldown",
+ Some(
+ "Minimum time on an account before a threshold switch. Hard limits ignore it."
+ .into(),
+ ),
+ slider_control(&sliders.cooldown, format::minutes_label(cooldown), busy),
+ cx,
+ ),
+ ];
+ for usage_window in windows {
+ let hidden = policy.hidden_window_ids.contains(&usage_window.id);
+ let all_hidden = policy.hidden_window_ids.clone();
+ let id = usage_window.id.clone();
+ rows.push(row(
+ format!(
+ "Show the {} limit",
+ format::short_window(&usage_window.label)
+ ),
+ Some(usage_window.label.clone().into()),
+ Switch::new(SharedString::from(format!(
+ "window-{}-{}",
+ provider.cli(),
+ usage_window.id
+ )))
+ .checked(!hidden)
+ .disabled(busy)
+ .on_click(window.listener_for(
+ &entity,
+ move |store, checked: &bool, _, cx| {
+ let next: Vec = if *checked {
+ all_hidden
+ .iter()
+ .filter(|known| **known != id)
+ .cloned()
+ .collect()
+ } else {
+ all_hidden.iter().cloned().chain([id.clone()]).collect()
+ };
+ store.set_policy(provider, json!({ "hiddenWindowIds": next }), cx)
+ },
+ )),
+ cx,
+ ));
+ }
+ group(provider.title(), rows, cx)
+ }
+
+ fn app_group(&self, cx: &mut Context) -> Div {
+ let store = self.store.read(cx);
+ let preferences = store.preferences.clone();
+ let terminals = store.terminals.clone();
+ let entity = self.store.clone();
+
+ let appearance_index = match preferences.appearance {
+ Appearance::Auto => 0,
+ Appearance::Light => 1,
+ Appearance::Dark => 2,
+ };
+ let presence_index = match preferences.presence {
+ Presence::MenuBarAndDock => 0,
+ Presence::MenuBar => 1,
+ Presence::Dock => 2,
+ };
+ let update = |change: fn(&mut Preferences, usize)| {
+ let entity = entity.clone();
+ move |index: &usize, _: &mut Window, cx: &mut App| {
+ entity.update(cx, |store, cx| {
+ let mut preferences = store.preferences.clone();
+ change(&mut preferences, *index);
+ store.set_preferences(preferences, cx)
+ })
+ }
+ };
+ let current_terminal = terminal::resolve(preferences.terminal.as_deref());
+ let terminal_label = if preferences.terminal.is_none() {
+ format!("Automatic ({})", current_terminal.name)
+ } else {
+ current_terminal.name.to_string()
+ };
+ let menu_store = entity.clone();
+ let chosen = preferences.terminal.clone();
+
+ group(
+ "App",
+ vec![
+ row(
+ "Appearance",
+ None,
+ TabBar::new("appearance")
+ .segmented()
+ .small()
+ .selected_index(appearance_index)
+ .on_click(update(|preferences, index| {
+ preferences.appearance =
+ [Appearance::Auto, Appearance::Light, Appearance::Dark][index]
+ }))
+ .children(["Auto", "Light", "Dark"]),
+ cx,
+ ),
+ row(
+ "Show tokenmaxx in",
+ Some(
+ "Closing the window keeps tokenmaxx running in the menu bar or Dock."
+ .into(),
+ ),
+ TabBar::new("presence")
+ .segmented()
+ .small()
+ .selected_index(presence_index)
+ .on_click(update(|preferences, index| {
+ preferences.presence =
+ [Presence::MenuBarAndDock, Presence::MenuBar, Presence::Dock][index]
+ }))
+ .children(["Menu bar and Dock", "Menu bar", "Dock"]),
+ cx,
+ ),
+ row(
+ "Terminal for sign-in",
+ Some("Subscription logins run codex or claude interactively there.".into()),
+ Button::new("terminal")
+ .small()
+ .outline()
+ .label(terminal_label)
+ .dropdown_menu(move |menu, window, _| {
+ let options = std::iter::once((None, "Automatic")).chain(
+ terminals.iter().map(|terminal| {
+ (Some(terminal.bundle_id.to_string()), terminal.name)
+ }),
+ );
+ options.fold(menu, |menu, (bundle_id, name)| {
+ let checked = bundle_id == chosen;
+ menu.item(PopupMenuItem::new(name).checked(checked).on_click(
+ window.listener_for(&menu_store, move |store, _, _, cx| {
+ let preferences = Preferences {
+ terminal: bundle_id.clone(),
+ ..store.preferences.clone()
+ };
+ store.set_preferences(preferences, cx)
+ }),
+ ))
+ })
+ }),
+ cx,
+ ),
+ ],
+ cx,
+ )
+ }
+
+ fn system_group(&self, window: &mut Window, cx: &mut Context) -> Div {
+ let store = self.store.read(cx);
+ let busy = store.is_busy();
+ let pi = store.routing.pi;
+ let entity = self.store.clone();
+ let runtime = store.runtime.clone();
+ let version = runtime
+ .as_ref()
+ .map(|runtime| runtime.version.clone())
+ .unwrap_or_else(|| "…".into());
+ let latest = store.latest.clone();
+
+ let pi_control: AnyElement = if pi.present {
+ Switch::new("pi")
+ .checked(pi.routed)
+ .disabled(busy)
+ .on_click(
+ window.listener_for(&entity, |store, checked: &bool, _, cx| {
+ store.set_routing(RoutingTarget::Pi, *checked, cx)
+ }),
+ )
+ .into_any_element()
+ } else {
+ muted("Not installed", cx).into_any_element()
+ };
+
+ let button = |id: &'static str,
+ label: &'static str,
+ action: fn(&mut Store, &mut Context)| {
+ Button::new(id)
+ .small()
+ .label(label)
+ .disabled(busy)
+ .on_click(window.listener_for(&entity, move |store, _, _, cx| action(store, cx)))
+ .into_any_element()
+ };
+ let (tool_description, tool_control): (String, AnyElement) = match runtime
+ .as_ref()
+ .map(|runtime| (&runtime.tool, runtime))
+ {
+ None => ("Checking your PATH…".into(), div().into_any_element()),
+ Some((CommandLineTool::Bundled, _)) => (
+ "tokenmaxx in your terminal is this app's own copy.".into(),
+ muted("Installed", cx).into_any_element(),
+ ),
+ Some((CommandLineTool::Shared { path }, runtime)) => (
+ format!(
+ "The app runs your installed tokenmaxx v{} at {path}, so both share one daemon.",
+ runtime.version
+ ),
+ muted("Shared", cx).into_any_element(),
+ ),
+ Some((CommandLineTool::Outdated { path, version }, runtime)) => (
+ format!(
+ "{path} is {}, older than this app's v{}. Until it is updated, the app runs its own copy and each restarts the daemon on its version.",
+ version
+ .as_deref()
+ .map(|version| format!("v{version}"))
+ .unwrap_or_else(|| "an older version".into()),
+ runtime.bundled_version
+ ),
+ button("update-cli", "Update", Store::update_command_line_tool),
+ ),
+ Some((CommandLineTool::Missing, _)) => (
+ "Use tokenmaxx from any terminal, sharing this app's accounts.".into(),
+ button("install-cli", "Install", Store::install_command_line_tool),
+ ),
+ };
+
+ group(
+ "System",
+ vec![
+ row(
+ "Route pi through tokenmaxx",
+ Some("Adds tokenmaxx providers to pi's models.json.".into()),
+ pi_control,
+ cx,
+ ),
+ row(
+ "Command-line tool",
+ Some(tool_description.into()),
+ tool_control,
+ cx,
+ ),
+ row(
+ "Version",
+ latest.map(|latest| format!("v{latest} is available at tokenmaxx.sh").into()),
+ div().text_sm().child(format!("v{version}")),
+ cx,
+ ),
+ ],
+ cx,
+ )
+ }
+}
+
+impl Render for SettingsPage {
+ fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement {
+ v_flex()
+ .gap_6()
+ .child(page_header("Settings", div()))
+ .child(self.provider_group(Provider::Openai, window, cx))
+ .child(self.provider_group(Provider::Anthropic, window, cx))
+ .child(self.app_group(cx))
+ .child(self.system_group(window, cx))
+ }
+}
diff --git a/gui/tests/fixtures/blitz.json b/gui/tests/fixtures/blitz.json
new file mode 100644
index 0000000..901e7b3
--- /dev/null
+++ b/gui/tests/fixtures/blitz.json
@@ -0,0 +1,1411 @@
+{
+ "snapshot": {
+ "accounts": [
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "b31c07d2",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000001",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_1",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:b31c07d2"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "9f4ae815",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000002",
+ "identity": "ship@rubriclabs.com",
+ "label": "ship@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_2",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:9f4ae815"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "7c91e0b6",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000006",
+ "identity": "ops@rubriclabs.com",
+ "label": "ops@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_6",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:7c91e0b6"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "c8d2f6a1",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000003",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/3",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "4e7b93c5",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000004",
+ "identity": "research@rubriclabs.com",
+ "label": "research@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/4",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "a25d18f4",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000005",
+ "identity": "zero@rubriclabs.com",
+ "label": "zero@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/5",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "d48f2a91",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000007",
+ "identity": "design@rubriclabs.com",
+ "label": "design@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/7",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "61e7c3b0",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000008",
+ "identity": "agents@rubriclabs.com",
+ "label": "agents@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/8",
+ "provider": "anthropic",
+ "secretReference": null
+ }
+ ],
+ "providers": [
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000001",
+ "generation": 2,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "openai",
+ "thresholdPercent": 90
+ },
+ "provider": "openai",
+ "switchedAt": null
+ },
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000008",
+ "generation": 6,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "anthropic",
+ "thresholdPercent": 90
+ },
+ "provider": "anthropic",
+ "switchedAt": "2026-07-15T15:53:00.000Z"
+ }
+ ],
+ "sampledAt": "2026-07-15T16:41:48.000Z",
+ "usage": [
+ {
+ "accountId": "00000000-0000-4000-8000-000000000001",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-20T04:13:12.000Z",
+ "usedPercent": 76
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000002",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-19T18:08:24.000Z",
+ "usedPercent": 22
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000006",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-20T04:13:12.000Z",
+ "usedPercent": 11
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000003",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "session",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T21:24:00.000Z",
+ "usedPercent": 4
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-20T14:18:00.000Z",
+ "usedPercent": 48
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000004",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "session",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T17:38:00.000Z",
+ "usedPercent": 92
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-20T04:13:12.000Z",
+ "usedPercent": 39
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000005",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "session",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T18:43:00.000Z",
+ "usedPercent": 92
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-19T18:08:24.000Z",
+ "usedPercent": 31
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000007",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "session",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T19:48:00.000Z",
+ "usedPercent": 92
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-18T21:58:48.000Z",
+ "usedPercent": 21
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000008",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "session",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T20:53:00.000Z",
+ "usedPercent": 71
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-20T14:18:00.000Z",
+ "usedPercent": 11
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ }
+ ]
+ },
+ "tokens": {
+ "nowPerHour": 282903528,
+ "timeframes": [
+ {
+ "bucketMs": 30000,
+ "buckets": [
+ 0,
+ 1873881,
+ 0,
+ 2273617,
+ 2148729,
+ 2632952,
+ 3156528,
+ 1347101,
+ 1412728,
+ 1519664,
+ 2328201,
+ 1266931,
+ 0,
+ 1153231,
+ 521115,
+ 0,
+ 1414592,
+ 268986,
+ 1499492,
+ 944147,
+ 2786525,
+ 2324463,
+ 2650957,
+ 1575558,
+ 110322,
+ 10906,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 281020,
+ 45026,
+ 1274392,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 234053,
+ 250721,
+ 681165,
+ 3116273,
+ 2563644,
+ 2301864,
+ 2889248,
+ 2471845,
+ 2203651,
+ 1418455,
+ 3146434,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1014589,
+ 0,
+ 1003433,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1213197,
+ 1789251,
+ 1885029,
+ 2429365,
+ 0,
+ 0,
+ 0,
+ 0,
+ 567892,
+ 0,
+ 0,
+ 0,
+ 949873,
+ 0,
+ 1246740,
+ 2484754,
+ 3939659,
+ 2060908,
+ 3834507,
+ 1951447,
+ 1698763,
+ 2773564,
+ 1931649,
+ 1102989,
+ 1641564,
+ 0,
+ 132409
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 843750,
+ "cached": 39571875,
+ "costUsd": 36.60525,
+ "input": 1265625,
+ "output": 506250,
+ "tokens": 42187500,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 1031250,
+ "cached": 48365625,
+ "costUsd": 14.166796875,
+ "input": 1546875,
+ "output": 618750,
+ "tokens": 51562500,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 4.3828125,
+ "costCached": 22.490015624999998,
+ "costInput": 7.1929687499999995,
+ "costOutput": 16.70625,
+ "costUsd": 50.772046875,
+ "key": "1h",
+ "models": [
+ {
+ "cacheCreation": 562500,
+ "cached": 26381250,
+ "costUsd": 29.3625,
+ "input": 843750,
+ "output": 337500,
+ "tokens": 28125000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 787500,
+ "cached": 36933750,
+ "costUsd": 10.81828125,
+ "input": 1181250,
+ "output": 472500,
+ "tokens": 39375000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 206250,
+ "cached": 9673125,
+ "costUsd": 6.45975,
+ "input": 309375,
+ "output": 123750,
+ "tokens": 10312500,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 243750,
+ "cached": 11431875,
+ "costUsd": 3.348515625,
+ "input": 365625,
+ "output": 146250,
+ "tokens": 12187500,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 75000,
+ "cached": 3517500,
+ "costUsd": 0.7829999999999999,
+ "input": 112500,
+ "output": 45000,
+ "tokens": 3750000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 472759080,
+ "totalCacheCreation": 1875000,
+ "totalCached": 87937500,
+ "totalInput": 2812500,
+ "totalOutput": 1125000,
+ "totalTokens": 93750000
+ },
+ {
+ "bucketMs": 150000,
+ "buckets": [
+ 12692664,
+ 10296502,
+ 21495959,
+ 15053162,
+ 9195431,
+ 12863168,
+ 1220281,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4861617,
+ 10429490,
+ 10819712,
+ 13475983,
+ 21513944,
+ 18158869,
+ 4278136,
+ 7852928,
+ 8180580,
+ 5977487,
+ 3170661,
+ 4810945,
+ 0,
+ 0,
+ 0,
+ 0,
+ 12401967,
+ 494170,
+ 4028633,
+ 10814637,
+ 17493089,
+ 6782289,
+ 8009161,
+ 6689617,
+ 5993566,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4886891,
+ 0,
+ 0,
+ 2720091,
+ 0,
+ 0,
+ 167512,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1194401,
+ 0,
+ 10240070,
+ 15103383,
+ 8365173,
+ 15461143,
+ 22771111,
+ 22880377,
+ 23273307,
+ 7443819,
+ 14839408,
+ 12683285,
+ 10147247,
+ 737461,
+ 0,
+ 715117,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5277805,
+ 8467739,
+ 2951979,
+ 0,
+ 397983,
+ 8812233,
+ 157817,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 4218750,
+ "cached": 197859375,
+ "costUsd": 183.02624999999998,
+ "input": 6328125,
+ "output": 2531250,
+ "tokens": 210937500,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 5156250,
+ "cached": 241828125,
+ "costUsd": 70.833984375,
+ "input": 7734375,
+ "output": 3093750,
+ "tokens": 257812500,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 21.9140625,
+ "costCached": 112.450078125,
+ "costInput": 35.96484375,
+ "costOutput": 83.53125,
+ "costUsd": 253.86023437499998,
+ "key": "5h",
+ "models": [
+ {
+ "cacheCreation": 2812500,
+ "cached": 131906250,
+ "costUsd": 146.8125,
+ "input": 4218750,
+ "output": 1687500,
+ "tokens": 140625000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 3937500,
+ "cached": 184668750,
+ "costUsd": 54.09140625,
+ "input": 5906250,
+ "output": 2362500,
+ "tokens": 196875000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 1031250,
+ "cached": 48365625,
+ "costUsd": 32.29875,
+ "input": 1546875,
+ "output": 618750,
+ "tokens": 51562500,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 1218750,
+ "cached": 57159375,
+ "costUsd": 16.742578125,
+ "input": 1828125,
+ "output": 731250,
+ "tokens": 60937500,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 375000,
+ "cached": 17587500,
+ "costUsd": 3.915,
+ "input": 562500,
+ "output": 225000,
+ "tokens": 18750000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 558559368,
+ "totalCacheCreation": 9375000,
+ "totalCached": 439687500,
+ "totalInput": 14062500,
+ "totalOutput": 5625000,
+ "totalTokens": 468750000
+ },
+ {
+ "bucketMs": 720000,
+ "buckets": [
+ 0,
+ 19657832,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 11160187,
+ 28327746,
+ 80545778,
+ 33539138,
+ 85861572,
+ 6712031,
+ 41041339,
+ 47298892,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 44121034,
+ 0,
+ 34967027,
+ 91231202,
+ 104234495,
+ 43513649,
+ 100676318,
+ 121028139,
+ 45588472,
+ 90594457,
+ 68243135,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8041137,
+ 0,
+ 0,
+ 5577615,
+ 0,
+ 4470391,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6074699,
+ 36388180,
+ 39137835,
+ 76483895,
+ 28842912,
+ 102736586,
+ 115360313,
+ 101569636,
+ 59205399,
+ 55172505,
+ 0,
+ 0,
+ 39571743,
+ 0,
+ 29547720,
+ 0,
+ 17417636,
+ 43087023,
+ 0,
+ 1832552,
+ 92290060,
+ 81358193,
+ 55998054,
+ 18167447,
+ 48748681,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1392825,
+ 0,
+ 0,
+ 33173297,
+ 39026765,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 10984457,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 20250000,
+ "cached": 949725000,
+ "costUsd": 878.5260000000001,
+ "input": 30375000,
+ "output": 12150000,
+ "tokens": 1012500000,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 24750000,
+ "cached": 1160775000,
+ "costUsd": 340.003125,
+ "input": 37125000,
+ "output": 14850000,
+ "tokens": 1237500000,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 105.1875,
+ "costCached": 539.7603750000001,
+ "costInput": 172.63125,
+ "costOutput": 400.95,
+ "costUsd": 1218.529125,
+ "key": "24h",
+ "models": [
+ {
+ "cacheCreation": 13500000,
+ "cached": 633150000,
+ "costUsd": 704.7,
+ "input": 20250000,
+ "output": 8100000,
+ "tokens": 675000000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 18900000,
+ "cached": 886410000,
+ "costUsd": 259.63875,
+ "input": 28350000,
+ "output": 11340000,
+ "tokens": 945000000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 4950000,
+ "cached": 232155000,
+ "costUsd": 155.034,
+ "input": 7425000,
+ "output": 2970000,
+ "tokens": 247500000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 5850000,
+ "cached": 274365000,
+ "costUsd": 80.364375,
+ "input": 8775000,
+ "output": 3510000,
+ "tokens": 292500000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 1800000,
+ "cached": 84420000,
+ "costUsd": 18.792,
+ "input": 2700000,
+ "output": 1080000,
+ "tokens": 90000000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 605140695,
+ "totalCacheCreation": 45000000,
+ "totalCached": 2110500000,
+ "totalInput": 67500000,
+ "totalOutput": 27000000,
+ "totalTokens": 2250000000
+ },
+ {
+ "bucketMs": 5040000,
+ "buckets": [
+ 92480736,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 10019505,
+ 0,
+ 0,
+ 45361491,
+ 505729366,
+ 440296842,
+ 285269503,
+ 590128972,
+ 424829351,
+ 548074907,
+ 625616506,
+ 529459031,
+ 264920673,
+ 215370993,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 183095542,
+ 0,
+ 295171412,
+ 32296933,
+ 139767502,
+ 150285787,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 120904791,
+ 0,
+ 162969914,
+ 281412445,
+ 71972469,
+ 239024630,
+ 102212963,
+ 300441947,
+ 95337812,
+ 0,
+ 105094635,
+ 128434753,
+ 0,
+ 0,
+ 0,
+ 288284698,
+ 393754350,
+ 394296798,
+ 292027258,
+ 777429509,
+ 325299788,
+ 718634053,
+ 381117000,
+ 421277710,
+ 209434894,
+ 0,
+ 28857279,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 215173984,
+ 121539976,
+ 425210605,
+ 177538530,
+ 735873321,
+ 720299122,
+ 620486090,
+ 267535903,
+ 78449599,
+ 51341740,
+ 110807309,
+ 0,
+ 0,
+ 167879465,
+ 160658493,
+ 0,
+ 0,
+ 12928159,
+ 295851379,
+ 372031575
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 141750000,
+ "cached": 6648074999,
+ "costUsd": 6149.681999499999,
+ "input": 212625000,
+ "output": 85050000,
+ "tokens": 7087499999,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 173250000,
+ "cached": 8125424999,
+ "costUsd": 2380.021874875,
+ "input": 259875000,
+ "output": 103950000,
+ "tokens": 8662499999,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 736.3125,
+ "costCached": 3778.3226243749996,
+ "costInput": 1208.41875,
+ "costOutput": 2806.65,
+ "costUsd": 8529.703874374998,
+ "key": "7d",
+ "models": [
+ {
+ "cacheCreation": 94500000,
+ "cached": 4432049999,
+ "costUsd": 4932.8999994999995,
+ "input": 141750000,
+ "output": 56700000,
+ "tokens": 4724999999,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 132300000,
+ "cached": 6204869999,
+ "costUsd": 1817.471249875,
+ "input": 198450000,
+ "output": 79380000,
+ "tokens": 6614999999,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 34650000,
+ "cached": 1625085000,
+ "costUsd": 1085.2379999999998,
+ "input": 51975000,
+ "output": 20790000,
+ "tokens": 1732500000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 40950000,
+ "cached": 1920555000,
+ "costUsd": 562.550625,
+ "input": 61425000,
+ "output": 24570000,
+ "tokens": 2047500000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 12600000,
+ "cached": 590940000,
+ "costUsd": 131.544,
+ "input": 18900000,
+ "output": 7560000,
+ "tokens": 630000000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 555306792,
+ "totalCacheCreation": 315000000,
+ "totalCached": 14773499998,
+ "totalInput": 472500000,
+ "totalOutput": 189000000,
+ "totalTokens": 15749999998
+ },
+ {
+ "bucketMs": 22320000,
+ "buckets": [
+ 222246732,
+ 0,
+ 0,
+ 0,
+ 644822809,
+ 310932073,
+ 0,
+ 1842570663,
+ 2458693616,
+ 1160029277,
+ 812205993,
+ 524855179,
+ 1903300786,
+ 1316251807,
+ 38736130,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 779191712,
+ 0,
+ 1127354015,
+ 178082366,
+ 394627231,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 529902594,
+ 668445301,
+ 342969372,
+ 1712074619,
+ 2228494101,
+ 3711018886,
+ 4381272999,
+ 3114554524,
+ 2864547802,
+ 2823849715,
+ 878400923,
+ 1079288821,
+ 0,
+ 684862896,
+ 141753537,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 203400614,
+ 1506269158,
+ 1441531156,
+ 115122385,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 513752660,
+ 597972805,
+ 925712800,
+ 2267419330,
+ 1025891696,
+ 88047489,
+ 0,
+ 0,
+ 2011839,
+ 0,
+ 521363766,
+ 285349084,
+ 224906124,
+ 32420951,
+ 2557242505,
+ 426934099,
+ 1675895756,
+ 3699235623,
+ 1796150228,
+ 2125481644,
+ 3489960185,
+ 1718461511,
+ 1328692514,
+ 920408093,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 624328136,
+ 760701371
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 627750000,
+ "cached": 29441475000,
+ "costUsd": 27234.306,
+ "input": 941625000,
+ "output": 376650000,
+ "tokens": 31387500000,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 767250000,
+ "cached": 35984025000,
+ "costUsd": 10540.096875,
+ "input": 1150875000,
+ "output": 460350000,
+ "tokens": 38362500000,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 3260.8125,
+ "costCached": 16732.571625,
+ "costInput": 5351.568749999999,
+ "costOutput": 12429.449999999999,
+ "costUsd": 37774.40287500001,
+ "key": "31d",
+ "models": [
+ {
+ "cacheCreation": 418500000,
+ "cached": 19627650000,
+ "costUsd": 21845.7,
+ "input": 627750000,
+ "output": 251100000,
+ "tokens": 20925000000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 585900000,
+ "cached": 27478710000,
+ "costUsd": 8048.8012499999995,
+ "input": 878850000,
+ "output": 351540000,
+ "tokens": 29295000000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 153450000,
+ "cached": 7196805000,
+ "costUsd": 4806.054,
+ "input": 230175000,
+ "output": 92070000,
+ "tokens": 7672500000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 181350000,
+ "cached": 8505315000,
+ "costUsd": 2491.2956249999997,
+ "input": 272025000,
+ "output": 108810000,
+ "tokens": 9067500000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 55800000,
+ "cached": 2617020000,
+ "costUsd": 582.5519999999999,
+ "input": 83700000,
+ "output": 33480000,
+ "tokens": 2790000000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 706656935,
+ "totalCacheCreation": 1395000000,
+ "totalCached": 65425500000,
+ "totalInput": 2092500000,
+ "totalOutput": 837000000,
+ "totalTokens": 69750000000
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/gui/tests/fixtures/cruising.json b/gui/tests/fixtures/cruising.json
new file mode 100644
index 0000000..1e326a8
--- /dev/null
+++ b/gui/tests/fixtures/cruising.json
@@ -0,0 +1,1321 @@
+{
+ "snapshot": {
+ "accounts": [
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "b31c07d2",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000001",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_1",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:b31c07d2"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "9f4ae815",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000002",
+ "identity": "ship@rubriclabs.com",
+ "label": "ship@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_2",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:9f4ae815"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "c8d2f6a1",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000003",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/3",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "4e7b93c5",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000004",
+ "identity": "research@rubriclabs.com",
+ "label": "research@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_5x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/4",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "apiKey",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "a25d18f4",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000005",
+ "identity": "anthropic api · prod",
+ "label": "anthropic api · prod",
+ "onThreshold": "switch",
+ "plan": null,
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/5",
+ "provider": "anthropic",
+ "secretReference": null
+ }
+ ],
+ "providers": [
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000001",
+ "generation": 4,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "openai",
+ "thresholdPercent": 90
+ },
+ "provider": "openai",
+ "switchedAt": "2026-07-15T15:06:00.000Z"
+ },
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000003",
+ "generation": 2,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "anthropic",
+ "thresholdPercent": 90
+ },
+ "provider": "anthropic",
+ "switchedAt": "2026-07-15T13:12:00.000Z"
+ }
+ ],
+ "sampledAt": "2026-07-15T16:41:48.000Z",
+ "usage": [
+ {
+ "accountId": "00000000-0000-4000-8000-000000000001",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T18:36:00.000Z",
+ "usedPercent": 41
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T06:51:36.000Z",
+ "usedPercent": 29
+ }
+ ],
+ "extraUsage": {
+ "balanceUsd": 18.5,
+ "enabled": true,
+ "exhausted": false,
+ "limitUsd": null,
+ "spentUsd": null,
+ "usedPercent": null
+ },
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": {
+ "applicable": 0,
+ "available": 3
+ },
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000002",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T20:12:00.000Z",
+ "usedPercent": 8
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T10:13:12.000Z",
+ "usedPercent": 19
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000003",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T18:57:00.000Z",
+ "usedPercent": 25
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-19T04:42:00.000Z",
+ "usedPercent": 14
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-19T14:46:48.000Z",
+ "usedPercent": 15
+ }
+ ],
+ "extraUsage": {
+ "balanceUsd": null,
+ "enabled": true,
+ "exhausted": false,
+ "limitUsd": 50,
+ "spentUsd": 12.4,
+ "usedPercent": 25
+ },
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000004",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T20:30:00.000Z",
+ "usedPercent": 5
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-19T21:30:00.000Z",
+ "usedPercent": 9
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-21T07:06:00.000Z",
+ "usedPercent": 3
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000005",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [],
+ "extraUsage": null,
+ "measuredSpendUsd": 23.71,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ }
+ ]
+ },
+ "tokens": {
+ "nowPerHour": 226338,
+ "timeframes": [
+ {
+ "bucketMs": 30000,
+ "buckets": [
+ 0,
+ 1499,
+ 0,
+ 1819,
+ 1719,
+ 2106,
+ 2525,
+ 1078,
+ 1130,
+ 1216,
+ 1863,
+ 1014,
+ 0,
+ 923,
+ 417,
+ 0,
+ 1132,
+ 215,
+ 1200,
+ 755,
+ 2229,
+ 1860,
+ 2121,
+ 1260,
+ 88,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 225,
+ 36,
+ 1020,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 187,
+ 201,
+ 545,
+ 2493,
+ 2051,
+ 1841,
+ 2311,
+ 1977,
+ 1763,
+ 1135,
+ 2517,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 812,
+ 0,
+ 803,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 971,
+ 1431,
+ 1508,
+ 1943,
+ 0,
+ 0,
+ 0,
+ 0,
+ 454,
+ 0,
+ 0,
+ 0,
+ 760,
+ 0,
+ 997,
+ 1988,
+ 3152,
+ 1649,
+ 3068,
+ 1561,
+ 1359,
+ 2219,
+ 1545,
+ 882,
+ 1313,
+ 0,
+ 106
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 675,
+ "cached": 31657,
+ "costUsd": 0.02928555,
+ "input": 1013,
+ "output": 405,
+ "tokens": 33750,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.011334,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.00350625,
+ "costCached": 0.017991800000000002,
+ "costInput": 0.0057565,
+ "costOutput": 0.013365,
+ "costUsd": 0.04061955,
+ "key": "1h",
+ "models": [
+ {
+ "cacheCreation": 450,
+ "cached": 21105,
+ "costUsd": 0.02349,
+ "input": 675,
+ "output": 270,
+ "tokens": 22500,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 630,
+ "cached": 29547,
+ "costUsd": 0.008654625,
+ "input": 945,
+ "output": 378,
+ "tokens": 31500,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 165,
+ "cached": 7738,
+ "costUsd": 0.005169149999999999,
+ "input": 248,
+ "output": 99,
+ "tokens": 8250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 195,
+ "cached": 9145,
+ "costUsd": 0.0026793750000000003,
+ "input": 293,
+ "output": 117,
+ "tokens": 9750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 60,
+ "cached": 2814,
+ "costUsd": 0.0006264,
+ "input": 90,
+ "output": 36,
+ "tokens": 3000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 378240,
+ "totalCacheCreation": 1500,
+ "totalCached": 70349,
+ "totalInput": 2251,
+ "totalOutput": 900,
+ "totalTokens": 75000
+ },
+ {
+ "bucketMs": 150000,
+ "buckets": [
+ 10154,
+ 8237,
+ 17197,
+ 12043,
+ 7356,
+ 10291,
+ 976,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3889,
+ 8344,
+ 8656,
+ 10781,
+ 17211,
+ 14527,
+ 3423,
+ 6282,
+ 6544,
+ 4782,
+ 2537,
+ 3849,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9922,
+ 395,
+ 3223,
+ 8652,
+ 13994,
+ 5426,
+ 6407,
+ 5352,
+ 4795,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3910,
+ 0,
+ 0,
+ 2176,
+ 0,
+ 0,
+ 134,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 956,
+ 0,
+ 8192,
+ 12083,
+ 6692,
+ 12369,
+ 18217,
+ 18304,
+ 18619,
+ 5955,
+ 11872,
+ 10147,
+ 8118,
+ 590,
+ 0,
+ 572,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4222,
+ 6774,
+ 2362,
+ 0,
+ 318,
+ 7050,
+ 126,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 3375,
+ "cached": 158288,
+ "costUsd": 0.14642285000000002,
+ "input": 5063,
+ "output": 2025,
+ "tokens": 168751,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4125,
+ "cached": 193463,
+ "costUsd": 0.056667875,
+ "input": 6188,
+ "output": 2475,
+ "tokens": 206251,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.017531249999999998,
+ "costCached": 0.089960475,
+ "costInput": 0.028773999999999997,
+ "costOutput": 0.066825,
+ "costUsd": 0.203090725,
+ "key": "5h",
+ "models": [
+ {
+ "cacheCreation": 2250,
+ "cached": 105526,
+ "costUsd": 0.11745050000000001,
+ "input": 3375,
+ "output": 1350,
+ "tokens": 112501,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 3150,
+ "cached": 147736,
+ "costUsd": 0.04327325,
+ "input": 4725,
+ "output": 1890,
+ "tokens": 157501,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.025840349999999998,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 975,
+ "cached": 45727,
+ "costUsd": 0.013394625,
+ "input": 1463,
+ "output": 585,
+ "tokens": 48750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 300,
+ "cached": 14070,
+ "costUsd": 0.003132,
+ "input": 450,
+ "output": 180,
+ "tokens": 15000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 446856,
+ "totalCacheCreation": 7500,
+ "totalCached": 351751,
+ "totalInput": 11251,
+ "totalOutput": 4500,
+ "totalTokens": 375002
+ },
+ {
+ "bucketMs": 720000,
+ "buckets": [
+ 0,
+ 15726,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8928,
+ 22662,
+ 64437,
+ 26831,
+ 68689,
+ 5370,
+ 32833,
+ 37839,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 35297,
+ 0,
+ 27974,
+ 72985,
+ 83388,
+ 34811,
+ 80541,
+ 96823,
+ 36471,
+ 72476,
+ 54595,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6433,
+ 0,
+ 0,
+ 4462,
+ 0,
+ 3576,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4860,
+ 29111,
+ 31310,
+ 61187,
+ 23074,
+ 82189,
+ 92288,
+ 81256,
+ 47364,
+ 44138,
+ 0,
+ 0,
+ 31657,
+ 0,
+ 23638,
+ 0,
+ 13934,
+ 34470,
+ 0,
+ 1466,
+ 73832,
+ 65087,
+ 44798,
+ 14534,
+ 38999,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1114,
+ 0,
+ 0,
+ 26539,
+ 31221,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8788,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 16200,
+ "cached": 759780,
+ "costUsd": 0.7028207999999999,
+ "input": 24300,
+ "output": 9720,
+ "tokens": 810000,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 19800,
+ "cached": 928620,
+ "costUsd": 0.2720025,
+ "input": 29700,
+ "output": 11880,
+ "tokens": 990000,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.08415,
+ "costCached": 0.43180830000000003,
+ "costInput": 0.13810499999999998,
+ "costOutput": 0.32075999999999993,
+ "costUsd": 0.9748233,
+ "key": "24h",
+ "models": [
+ {
+ "cacheCreation": 10800,
+ "cached": 506520,
+ "costUsd": 0.5637599999999999,
+ "input": 16200,
+ "output": 6480,
+ "tokens": 540000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 15120,
+ "cached": 709128,
+ "costUsd": 0.20771099999999998,
+ "input": 22680,
+ "output": 9072,
+ "tokens": 756000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 3960,
+ "cached": 185724,
+ "costUsd": 0.1240272,
+ "input": 5940,
+ "output": 2376,
+ "tokens": 198000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4680,
+ "cached": 219492,
+ "costUsd": 0.0642915,
+ "input": 7020,
+ "output": 2808,
+ "tokens": 234000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 1440,
+ "cached": 67536,
+ "costUsd": 0.0150336,
+ "input": 2160,
+ "output": 864,
+ "tokens": 72000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 484115,
+ "totalCacheCreation": 36000,
+ "totalCached": 1688400,
+ "totalInput": 54000,
+ "totalOutput": 21600,
+ "totalTokens": 1800000
+ },
+ {
+ "bucketMs": 5040000,
+ "buckets": [
+ 73985,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8016,
+ 0,
+ 0,
+ 36289,
+ 404583,
+ 352237,
+ 228216,
+ 472103,
+ 339863,
+ 438460,
+ 500493,
+ 423567,
+ 211937,
+ 172297,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 146476,
+ 0,
+ 236137,
+ 25838,
+ 111814,
+ 120229,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 96724,
+ 0,
+ 130376,
+ 225130,
+ 57578,
+ 191220,
+ 81770,
+ 240354,
+ 76270,
+ 0,
+ 84076,
+ 102748,
+ 0,
+ 0,
+ 0,
+ 230628,
+ 315003,
+ 315437,
+ 233622,
+ 621944,
+ 260240,
+ 574907,
+ 304894,
+ 337022,
+ 167548,
+ 0,
+ 23086,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 172139,
+ 97232,
+ 340168,
+ 142031,
+ 588699,
+ 576239,
+ 496389,
+ 214029,
+ 62760,
+ 41073,
+ 88646,
+ 0,
+ 0,
+ 134304,
+ 128527,
+ 0,
+ 0,
+ 10343,
+ 236681,
+ 297625
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 113400,
+ "cached": 5318461,
+ "costUsd": 4.9197461,
+ "input": 170100,
+ "output": 68040,
+ "tokens": 5670001,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 138600,
+ "cached": 6500341,
+ "costUsd": 1.9040176250000003,
+ "input": 207900,
+ "output": 83160,
+ "tokens": 6930001,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.5890500000000001,
+ "costCached": 3.022658725,
+ "costInput": 0.966735,
+ "costOutput": 2.24532,
+ "costUsd": 6.823763725,
+ "key": "7d",
+ "models": [
+ {
+ "cacheCreation": 75600,
+ "cached": 3545641,
+ "costUsd": 3.9463204999999997,
+ "input": 113400,
+ "output": 45360,
+ "tokens": 3780001,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 105840,
+ "cached": 4963897,
+ "costUsd": 1.4539771250000002,
+ "input": 158760,
+ "output": 63504,
+ "tokens": 5292001,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 27720,
+ "cached": 1300068,
+ "costUsd": 0.8681904,
+ "input": 41580,
+ "output": 16632,
+ "tokens": 1386000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 32760,
+ "cached": 1536444,
+ "costUsd": 0.4500405,
+ "input": 49140,
+ "output": 19656,
+ "tokens": 1638000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 10080,
+ "cached": 472752,
+ "costUsd": 0.1052352,
+ "input": 15120,
+ "output": 6048,
+ "tokens": 504000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 444246,
+ "totalCacheCreation": 252000,
+ "totalCached": 11818802,
+ "totalInput": 378000,
+ "totalOutput": 151200,
+ "totalTokens": 12600002
+ },
+ {
+ "bucketMs": 22320000,
+ "buckets": [
+ 177797,
+ 0,
+ 0,
+ 0,
+ 515858,
+ 248746,
+ 0,
+ 1474057,
+ 1966955,
+ 928023,
+ 649765,
+ 419884,
+ 1522641,
+ 1053001,
+ 30989,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 623353,
+ 0,
+ 901883,
+ 142466,
+ 315702,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 423922,
+ 534756,
+ 274375,
+ 1369660,
+ 1782795,
+ 2968815,
+ 3505018,
+ 2491644,
+ 2291638,
+ 2259080,
+ 702721,
+ 863431,
+ 0,
+ 547890,
+ 113403,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 162720,
+ 1205015,
+ 1153225,
+ 92098,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 411002,
+ 478378,
+ 740570,
+ 1813935,
+ 820713,
+ 70438,
+ 0,
+ 0,
+ 1609,
+ 0,
+ 417091,
+ 228279,
+ 179925,
+ 25937,
+ 2045794,
+ 341547,
+ 1340717,
+ 2959388,
+ 1436920,
+ 1700385,
+ 2791968,
+ 1374769,
+ 1062954,
+ 736326,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 499463,
+ 608561
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 502200,
+ "cached": 23553178,
+ "costUsd": 21.787444,
+ "input": 753300,
+ "output": 301320,
+ "tokens": 25109998,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 613800,
+ "cached": 28787217,
+ "costUsd": 8.432077125,
+ "input": 920700,
+ "output": 368280,
+ "tokens": 30689997,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 2.60865,
+ "costCached": 13.386056125,
+ "costInput": 4.281255,
+ "costOutput": 9.94356,
+ "costUsd": 30.219521125,
+ "key": "31d",
+ "models": [
+ {
+ "cacheCreation": 334800,
+ "cached": 15702119,
+ "costUsd": 17.4765595,
+ "input": 502200,
+ "output": 200880,
+ "tokens": 16739999,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 468720,
+ "cached": 21982966,
+ "costUsd": 6.43904075,
+ "input": 703080,
+ "output": 281232,
+ "tokens": 23435998,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 122760,
+ "cached": 5757443,
+ "costUsd": 3.8448428999999997,
+ "input": 184140,
+ "output": 73656,
+ "tokens": 6137999,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 145080,
+ "cached": 6804251,
+ "costUsd": 1.993036375,
+ "input": 217620,
+ "output": 87048,
+ "tokens": 7253999,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 44640,
+ "cached": 2093616,
+ "costUsd": 0.4660416,
+ "input": 66960,
+ "output": 26784,
+ "tokens": 2232000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 565325,
+ "totalCacheCreation": 1116000,
+ "totalCached": 52340395,
+ "totalInput": 1674000,
+ "totalOutput": 669600,
+ "totalTokens": 55799995
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/gui/tests/fixtures/onboarding.json b/gui/tests/fixtures/onboarding.json
new file mode 100644
index 0000000..713b984
--- /dev/null
+++ b/gui/tests/fixtures/onboarding.json
@@ -0,0 +1,741 @@
+{
+ "snapshot": {
+ "accounts": [],
+ "providers": [
+ {
+ "activeAccountId": null,
+ "generation": 0,
+ "policy": {
+ "authorization": "notConfirmed",
+ "enabled": false,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "openai",
+ "thresholdPercent": 90
+ },
+ "provider": "openai",
+ "switchedAt": null
+ },
+ {
+ "activeAccountId": null,
+ "generation": 0,
+ "policy": {
+ "authorization": "notConfirmed",
+ "enabled": false,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "anthropic",
+ "thresholdPercent": 90
+ },
+ "provider": "anthropic",
+ "switchedAt": null
+ }
+ ],
+ "sampledAt": "2026-07-15T16:41:48.000Z",
+ "usage": []
+ },
+ "tokens": {
+ "nowPerHour": 0,
+ "timeframes": [
+ {
+ "bucketMs": 30000,
+ "buckets": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [],
+ "costCacheCreation": 0,
+ "costCached": 0,
+ "costInput": 0,
+ "costOutput": 0,
+ "costUsd": 0,
+ "key": "1h",
+ "models": [],
+ "peakPerHour": 0,
+ "totalCacheCreation": 0,
+ "totalCached": 0,
+ "totalInput": 0,
+ "totalOutput": 0,
+ "totalTokens": 0
+ },
+ {
+ "bucketMs": 150000,
+ "buckets": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [],
+ "costCacheCreation": 0,
+ "costCached": 0,
+ "costInput": 0,
+ "costOutput": 0,
+ "costUsd": 0,
+ "key": "5h",
+ "models": [],
+ "peakPerHour": 0,
+ "totalCacheCreation": 0,
+ "totalCached": 0,
+ "totalInput": 0,
+ "totalOutput": 0,
+ "totalTokens": 0
+ },
+ {
+ "bucketMs": 720000,
+ "buckets": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [],
+ "costCacheCreation": 0,
+ "costCached": 0,
+ "costInput": 0,
+ "costOutput": 0,
+ "costUsd": 0,
+ "key": "24h",
+ "models": [],
+ "peakPerHour": 0,
+ "totalCacheCreation": 0,
+ "totalCached": 0,
+ "totalInput": 0,
+ "totalOutput": 0,
+ "totalTokens": 0
+ },
+ {
+ "bucketMs": 5040000,
+ "buckets": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [],
+ "costCacheCreation": 0,
+ "costCached": 0,
+ "costInput": 0,
+ "costOutput": 0,
+ "costUsd": 0,
+ "key": "7d",
+ "models": [],
+ "peakPerHour": 0,
+ "totalCacheCreation": 0,
+ "totalCached": 0,
+ "totalInput": 0,
+ "totalOutput": 0,
+ "totalTokens": 0
+ },
+ {
+ "bucketMs": 22320000,
+ "buckets": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [],
+ "costCacheCreation": 0,
+ "costCached": 0,
+ "costInput": 0,
+ "costOutput": 0,
+ "costUsd": 0,
+ "key": "31d",
+ "models": [],
+ "peakPerHour": 0,
+ "totalCacheCreation": 0,
+ "totalCached": 0,
+ "totalInput": 0,
+ "totalOutput": 0,
+ "totalTokens": 0
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/gui/tests/fixtures/oneHot.json b/gui/tests/fixtures/oneHot.json
new file mode 100644
index 0000000..7c6a506
--- /dev/null
+++ b/gui/tests/fixtures/oneHot.json
@@ -0,0 +1,1280 @@
+{
+ "snapshot": {
+ "accounts": [
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "b31c07d2",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000001",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_1",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:b31c07d2"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "9f4ae815",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000002",
+ "identity": "ship@rubriclabs.com",
+ "label": "ship@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_2",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:9f4ae815"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "c8d2f6a1",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000003",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/3",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "4e7b93c5",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000004",
+ "identity": "research@rubriclabs.com",
+ "label": "research@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_5x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/4",
+ "provider": "anthropic",
+ "secretReference": null
+ }
+ ],
+ "providers": [
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000001",
+ "generation": 7,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "openai",
+ "thresholdPercent": 90
+ },
+ "provider": "openai",
+ "switchedAt": "2026-07-15T11:54:00.000Z"
+ },
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000003",
+ "generation": 3,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "anthropic",
+ "thresholdPercent": 90
+ },
+ "provider": "anthropic",
+ "switchedAt": "2026-07-15T09:42:00.000Z"
+ }
+ ],
+ "sampledAt": "2026-07-15T16:41:48.000Z",
+ "usage": [
+ {
+ "accountId": "00000000-0000-4000-8000-000000000001",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T17:21:00.000Z",
+ "usedPercent": 96
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-17T19:06:00.000Z",
+ "usedPercent": 52
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": {
+ "applicable": 1,
+ "available": 2
+ },
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000002",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T20:18:00.000Z",
+ "usedPercent": 8
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T11:54:00.000Z",
+ "usedPercent": 23
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000003",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T18:42:00.000Z",
+ "usedPercent": 38
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T08:32:24.000Z",
+ "usedPercent": 29
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-16T09:30:00.000Z",
+ "usedPercent": 85
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000004",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T19:57:00.000Z",
+ "usedPercent": 12
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-19T13:06:00.000Z",
+ "usedPercent": 12
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-20T14:18:00.000Z",
+ "usedPercent": 6
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ }
+ ]
+ },
+ "tokens": {
+ "nowPerHour": 226338,
+ "timeframes": [
+ {
+ "bucketMs": 30000,
+ "buckets": [
+ 0,
+ 1499,
+ 0,
+ 1819,
+ 1719,
+ 2106,
+ 2525,
+ 1078,
+ 1130,
+ 1216,
+ 1863,
+ 1014,
+ 0,
+ 923,
+ 417,
+ 0,
+ 1132,
+ 215,
+ 1200,
+ 755,
+ 2229,
+ 1860,
+ 2121,
+ 1260,
+ 88,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 225,
+ 36,
+ 1020,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 187,
+ 201,
+ 545,
+ 2493,
+ 2051,
+ 1841,
+ 2311,
+ 1977,
+ 1763,
+ 1135,
+ 2517,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 812,
+ 0,
+ 803,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 971,
+ 1431,
+ 1508,
+ 1943,
+ 0,
+ 0,
+ 0,
+ 0,
+ 454,
+ 0,
+ 0,
+ 0,
+ 760,
+ 0,
+ 997,
+ 1988,
+ 3152,
+ 1649,
+ 3068,
+ 1561,
+ 1359,
+ 2219,
+ 1545,
+ 882,
+ 1313,
+ 0,
+ 106
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 675,
+ "cached": 31657,
+ "costUsd": 0.02928555,
+ "input": 1013,
+ "output": 405,
+ "tokens": 33750,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.011334,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.00350625,
+ "costCached": 0.017991800000000002,
+ "costInput": 0.0057565,
+ "costOutput": 0.013365,
+ "costUsd": 0.04061955,
+ "key": "1h",
+ "models": [
+ {
+ "cacheCreation": 450,
+ "cached": 21105,
+ "costUsd": 0.02349,
+ "input": 675,
+ "output": 270,
+ "tokens": 22500,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 630,
+ "cached": 29547,
+ "costUsd": 0.008654625,
+ "input": 945,
+ "output": 378,
+ "tokens": 31500,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 165,
+ "cached": 7738,
+ "costUsd": 0.005169149999999999,
+ "input": 248,
+ "output": 99,
+ "tokens": 8250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 195,
+ "cached": 9145,
+ "costUsd": 0.0026793750000000003,
+ "input": 293,
+ "output": 117,
+ "tokens": 9750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 60,
+ "cached": 2814,
+ "costUsd": 0.0006264,
+ "input": 90,
+ "output": 36,
+ "tokens": 3000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 378240,
+ "totalCacheCreation": 1500,
+ "totalCached": 70349,
+ "totalInput": 2251,
+ "totalOutput": 900,
+ "totalTokens": 75000
+ },
+ {
+ "bucketMs": 150000,
+ "buckets": [
+ 10154,
+ 8237,
+ 17197,
+ 12043,
+ 7356,
+ 10291,
+ 976,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3889,
+ 8344,
+ 8656,
+ 10781,
+ 17211,
+ 14527,
+ 3423,
+ 6282,
+ 6544,
+ 4782,
+ 2537,
+ 3849,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9922,
+ 395,
+ 3223,
+ 8652,
+ 13994,
+ 5426,
+ 6407,
+ 5352,
+ 4795,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3910,
+ 0,
+ 0,
+ 2176,
+ 0,
+ 0,
+ 134,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 956,
+ 0,
+ 8192,
+ 12083,
+ 6692,
+ 12369,
+ 18217,
+ 18304,
+ 18619,
+ 5955,
+ 11872,
+ 10147,
+ 8118,
+ 590,
+ 0,
+ 572,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4222,
+ 6774,
+ 2362,
+ 0,
+ 318,
+ 7050,
+ 126,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 3375,
+ "cached": 158288,
+ "costUsd": 0.14642285000000002,
+ "input": 5063,
+ "output": 2025,
+ "tokens": 168751,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4125,
+ "cached": 193463,
+ "costUsd": 0.056667875,
+ "input": 6188,
+ "output": 2475,
+ "tokens": 206251,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.017531249999999998,
+ "costCached": 0.089960475,
+ "costInput": 0.028773999999999997,
+ "costOutput": 0.066825,
+ "costUsd": 0.203090725,
+ "key": "5h",
+ "models": [
+ {
+ "cacheCreation": 2250,
+ "cached": 105526,
+ "costUsd": 0.11745050000000001,
+ "input": 3375,
+ "output": 1350,
+ "tokens": 112501,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 3150,
+ "cached": 147736,
+ "costUsd": 0.04327325,
+ "input": 4725,
+ "output": 1890,
+ "tokens": 157501,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.025840349999999998,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 975,
+ "cached": 45727,
+ "costUsd": 0.013394625,
+ "input": 1463,
+ "output": 585,
+ "tokens": 48750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 300,
+ "cached": 14070,
+ "costUsd": 0.003132,
+ "input": 450,
+ "output": 180,
+ "tokens": 15000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 446856,
+ "totalCacheCreation": 7500,
+ "totalCached": 351751,
+ "totalInput": 11251,
+ "totalOutput": 4500,
+ "totalTokens": 375002
+ },
+ {
+ "bucketMs": 720000,
+ "buckets": [
+ 0,
+ 15726,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8928,
+ 22662,
+ 64437,
+ 26831,
+ 68689,
+ 5370,
+ 32833,
+ 37839,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 35297,
+ 0,
+ 27974,
+ 72985,
+ 83388,
+ 34811,
+ 80541,
+ 96823,
+ 36471,
+ 72476,
+ 54595,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6433,
+ 0,
+ 0,
+ 4462,
+ 0,
+ 3576,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4860,
+ 29111,
+ 31310,
+ 61187,
+ 23074,
+ 82189,
+ 92288,
+ 81256,
+ 47364,
+ 44138,
+ 0,
+ 0,
+ 31657,
+ 0,
+ 23638,
+ 0,
+ 13934,
+ 34470,
+ 0,
+ 1466,
+ 73832,
+ 65087,
+ 44798,
+ 14534,
+ 38999,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1114,
+ 0,
+ 0,
+ 26539,
+ 31221,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8788,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 16200,
+ "cached": 759780,
+ "costUsd": 0.7028207999999999,
+ "input": 24300,
+ "output": 9720,
+ "tokens": 810000,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 19800,
+ "cached": 928620,
+ "costUsd": 0.2720025,
+ "input": 29700,
+ "output": 11880,
+ "tokens": 990000,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.08415,
+ "costCached": 0.43180830000000003,
+ "costInput": 0.13810499999999998,
+ "costOutput": 0.32075999999999993,
+ "costUsd": 0.9748233,
+ "key": "24h",
+ "models": [
+ {
+ "cacheCreation": 10800,
+ "cached": 506520,
+ "costUsd": 0.5637599999999999,
+ "input": 16200,
+ "output": 6480,
+ "tokens": 540000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 15120,
+ "cached": 709128,
+ "costUsd": 0.20771099999999998,
+ "input": 22680,
+ "output": 9072,
+ "tokens": 756000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 3960,
+ "cached": 185724,
+ "costUsd": 0.1240272,
+ "input": 5940,
+ "output": 2376,
+ "tokens": 198000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4680,
+ "cached": 219492,
+ "costUsd": 0.0642915,
+ "input": 7020,
+ "output": 2808,
+ "tokens": 234000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 1440,
+ "cached": 67536,
+ "costUsd": 0.0150336,
+ "input": 2160,
+ "output": 864,
+ "tokens": 72000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 484115,
+ "totalCacheCreation": 36000,
+ "totalCached": 1688400,
+ "totalInput": 54000,
+ "totalOutput": 21600,
+ "totalTokens": 1800000
+ },
+ {
+ "bucketMs": 5040000,
+ "buckets": [
+ 73985,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8016,
+ 0,
+ 0,
+ 36289,
+ 404583,
+ 352237,
+ 228216,
+ 472103,
+ 339863,
+ 438460,
+ 500493,
+ 423567,
+ 211937,
+ 172297,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 146476,
+ 0,
+ 236137,
+ 25838,
+ 111814,
+ 120229,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 96724,
+ 0,
+ 130376,
+ 225130,
+ 57578,
+ 191220,
+ 81770,
+ 240354,
+ 76270,
+ 0,
+ 84076,
+ 102748,
+ 0,
+ 0,
+ 0,
+ 230628,
+ 315003,
+ 315437,
+ 233622,
+ 621944,
+ 260240,
+ 574907,
+ 304894,
+ 337022,
+ 167548,
+ 0,
+ 23086,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 172139,
+ 97232,
+ 340168,
+ 142031,
+ 588699,
+ 576239,
+ 496389,
+ 214029,
+ 62760,
+ 41073,
+ 88646,
+ 0,
+ 0,
+ 134304,
+ 128527,
+ 0,
+ 0,
+ 10343,
+ 236681,
+ 297625
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 113400,
+ "cached": 5318461,
+ "costUsd": 4.9197461,
+ "input": 170100,
+ "output": 68040,
+ "tokens": 5670001,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 138600,
+ "cached": 6500341,
+ "costUsd": 1.9040176250000003,
+ "input": 207900,
+ "output": 83160,
+ "tokens": 6930001,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.5890500000000001,
+ "costCached": 3.022658725,
+ "costInput": 0.966735,
+ "costOutput": 2.24532,
+ "costUsd": 6.823763725,
+ "key": "7d",
+ "models": [
+ {
+ "cacheCreation": 75600,
+ "cached": 3545641,
+ "costUsd": 3.9463204999999997,
+ "input": 113400,
+ "output": 45360,
+ "tokens": 3780001,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 105840,
+ "cached": 4963897,
+ "costUsd": 1.4539771250000002,
+ "input": 158760,
+ "output": 63504,
+ "tokens": 5292001,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 27720,
+ "cached": 1300068,
+ "costUsd": 0.8681904,
+ "input": 41580,
+ "output": 16632,
+ "tokens": 1386000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 32760,
+ "cached": 1536444,
+ "costUsd": 0.4500405,
+ "input": 49140,
+ "output": 19656,
+ "tokens": 1638000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 10080,
+ "cached": 472752,
+ "costUsd": 0.1052352,
+ "input": 15120,
+ "output": 6048,
+ "tokens": 504000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 444246,
+ "totalCacheCreation": 252000,
+ "totalCached": 11818802,
+ "totalInput": 378000,
+ "totalOutput": 151200,
+ "totalTokens": 12600002
+ },
+ {
+ "bucketMs": 22320000,
+ "buckets": [
+ 177797,
+ 0,
+ 0,
+ 0,
+ 515858,
+ 248746,
+ 0,
+ 1474057,
+ 1966955,
+ 928023,
+ 649765,
+ 419884,
+ 1522641,
+ 1053001,
+ 30989,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 623353,
+ 0,
+ 901883,
+ 142466,
+ 315702,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 423922,
+ 534756,
+ 274375,
+ 1369660,
+ 1782795,
+ 2968815,
+ 3505018,
+ 2491644,
+ 2291638,
+ 2259080,
+ 702721,
+ 863431,
+ 0,
+ 547890,
+ 113403,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 162720,
+ 1205015,
+ 1153225,
+ 92098,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 411002,
+ 478378,
+ 740570,
+ 1813935,
+ 820713,
+ 70438,
+ 0,
+ 0,
+ 1609,
+ 0,
+ 417091,
+ 228279,
+ 179925,
+ 25937,
+ 2045794,
+ 341547,
+ 1340717,
+ 2959388,
+ 1436920,
+ 1700385,
+ 2791968,
+ 1374769,
+ 1062954,
+ 736326,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 499463,
+ 608561
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 502200,
+ "cached": 23553178,
+ "costUsd": 21.787444,
+ "input": 753300,
+ "output": 301320,
+ "tokens": 25109998,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 613800,
+ "cached": 28787217,
+ "costUsd": 8.432077125,
+ "input": 920700,
+ "output": 368280,
+ "tokens": 30689997,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 2.60865,
+ "costCached": 13.386056125,
+ "costInput": 4.281255,
+ "costOutput": 9.94356,
+ "costUsd": 30.219521125,
+ "key": "31d",
+ "models": [
+ {
+ "cacheCreation": 334800,
+ "cached": 15702119,
+ "costUsd": 17.4765595,
+ "input": 502200,
+ "output": 200880,
+ "tokens": 16739999,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 468720,
+ "cached": 21982966,
+ "costUsd": 6.43904075,
+ "input": 703080,
+ "output": 281232,
+ "tokens": 23435998,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 122760,
+ "cached": 5757443,
+ "costUsd": 3.8448428999999997,
+ "input": 184140,
+ "output": 73656,
+ "tokens": 6137999,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 145080,
+ "cached": 6804251,
+ "costUsd": 1.993036375,
+ "input": 217620,
+ "output": 87048,
+ "tokens": 7253999,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 44640,
+ "cached": 2093616,
+ "costUsd": 0.4660416,
+ "input": 66960,
+ "output": 26784,
+ "tokens": 2232000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 565325,
+ "totalCacheCreation": 1116000,
+ "totalCached": 52340395,
+ "totalInput": 1674000,
+ "totalOutput": 669600,
+ "totalTokens": 55799995
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/gui/tests/fixtures/relay.json b/gui/tests/fixtures/relay.json
new file mode 100644
index 0000000..e670f2e
--- /dev/null
+++ b/gui/tests/fixtures/relay.json
@@ -0,0 +1,1348 @@
+{
+ "snapshot": {
+ "accounts": [
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "b31c07d2",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000001",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_1",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:b31c07d2"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "9f4ae815",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000002",
+ "identity": "ship@rubriclabs.com",
+ "label": "ship@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_2",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:9f4ae815"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "7c91e0b6",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000006",
+ "identity": "ops@rubriclabs.com",
+ "label": "ops@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_6",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:7c91e0b6"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "c8d2f6a1",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000003",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/3",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "4e7b93c5",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000004",
+ "identity": "research@rubriclabs.com",
+ "label": "research@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/4",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "a25d18f4",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000005",
+ "identity": "zero@rubriclabs.com",
+ "label": "zero@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/5",
+ "provider": "anthropic",
+ "secretReference": null
+ }
+ ],
+ "providers": [
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000006",
+ "generation": 7,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "openai",
+ "thresholdPercent": 90
+ },
+ "provider": "openai",
+ "switchedAt": "2026-07-15T16:30:57.142Z"
+ },
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000005",
+ "generation": 4,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "anthropic",
+ "thresholdPercent": 90
+ },
+ "provider": "anthropic",
+ "switchedAt": "2026-07-15T15:30:00.000Z"
+ }
+ ],
+ "sampledAt": "2026-07-15T16:41:48.000Z",
+ "usage": [
+ {
+ "accountId": "00000000-0000-4000-8000-000000000001",
+ "hardLimitReached": true,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T19:12:00.000Z",
+ "usedPercent": 100
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T11:54:00.000Z",
+ "usedPercent": 24
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000002",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T19:12:00.000Z",
+ "usedPercent": 95
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T11:54:00.000Z",
+ "usedPercent": 27
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000006",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T19:12:00.000Z",
+ "usedPercent": 51
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T11:54:00.000Z",
+ "usedPercent": 35
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000003",
+ "hardLimitReached": true,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "session",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T19:12:00.000Z",
+ "usedPercent": 100
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T20:18:00.000Z",
+ "usedPercent": 18
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000004",
+ "hardLimitReached": true,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "session",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T19:12:00.000Z",
+ "usedPercent": 100
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T20:18:00.000Z",
+ "usedPercent": 24
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000005",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "session",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T19:12:00.000Z",
+ "usedPercent": 64
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T20:18:00.000Z",
+ "usedPercent": 27
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ }
+ ]
+ },
+ "tokens": {
+ "nowPerHour": 226338,
+ "timeframes": [
+ {
+ "bucketMs": 30000,
+ "buckets": [
+ 0,
+ 1499,
+ 0,
+ 1819,
+ 1719,
+ 2106,
+ 2525,
+ 1078,
+ 1130,
+ 1216,
+ 1863,
+ 1014,
+ 0,
+ 923,
+ 417,
+ 0,
+ 1132,
+ 215,
+ 1200,
+ 755,
+ 2229,
+ 1860,
+ 2121,
+ 1260,
+ 88,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 225,
+ 36,
+ 1020,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 187,
+ 201,
+ 545,
+ 2493,
+ 2051,
+ 1841,
+ 2311,
+ 1977,
+ 1763,
+ 1135,
+ 2517,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 812,
+ 0,
+ 803,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 971,
+ 1431,
+ 1508,
+ 1943,
+ 0,
+ 0,
+ 0,
+ 0,
+ 454,
+ 0,
+ 0,
+ 0,
+ 760,
+ 0,
+ 997,
+ 1988,
+ 3152,
+ 1649,
+ 3068,
+ 1561,
+ 1359,
+ 2219,
+ 1545,
+ 882,
+ 1313,
+ 0,
+ 106
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 675,
+ "cached": 31657,
+ "costUsd": 0.02928555,
+ "input": 1013,
+ "output": 405,
+ "tokens": 33750,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.011334,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.00350625,
+ "costCached": 0.017991800000000002,
+ "costInput": 0.0057565,
+ "costOutput": 0.013365,
+ "costUsd": 0.04061955,
+ "key": "1h",
+ "models": [
+ {
+ "cacheCreation": 450,
+ "cached": 21105,
+ "costUsd": 0.02349,
+ "input": 675,
+ "output": 270,
+ "tokens": 22500,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 630,
+ "cached": 29547,
+ "costUsd": 0.008654625,
+ "input": 945,
+ "output": 378,
+ "tokens": 31500,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 165,
+ "cached": 7738,
+ "costUsd": 0.005169149999999999,
+ "input": 248,
+ "output": 99,
+ "tokens": 8250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 195,
+ "cached": 9145,
+ "costUsd": 0.0026793750000000003,
+ "input": 293,
+ "output": 117,
+ "tokens": 9750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 60,
+ "cached": 2814,
+ "costUsd": 0.0006264,
+ "input": 90,
+ "output": 36,
+ "tokens": 3000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 378240,
+ "totalCacheCreation": 1500,
+ "totalCached": 70349,
+ "totalInput": 2251,
+ "totalOutput": 900,
+ "totalTokens": 75000
+ },
+ {
+ "bucketMs": 150000,
+ "buckets": [
+ 10154,
+ 8237,
+ 17197,
+ 12043,
+ 7356,
+ 10291,
+ 976,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3889,
+ 8344,
+ 8656,
+ 10781,
+ 17211,
+ 14527,
+ 3423,
+ 6282,
+ 6544,
+ 4782,
+ 2537,
+ 3849,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9922,
+ 395,
+ 3223,
+ 8652,
+ 13994,
+ 5426,
+ 6407,
+ 5352,
+ 4795,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3910,
+ 0,
+ 0,
+ 2176,
+ 0,
+ 0,
+ 134,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 956,
+ 0,
+ 8192,
+ 12083,
+ 6692,
+ 12369,
+ 18217,
+ 18304,
+ 18619,
+ 5955,
+ 11872,
+ 10147,
+ 8118,
+ 590,
+ 0,
+ 572,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4222,
+ 6774,
+ 2362,
+ 0,
+ 318,
+ 7050,
+ 126,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 3375,
+ "cached": 158288,
+ "costUsd": 0.14642285000000002,
+ "input": 5063,
+ "output": 2025,
+ "tokens": 168751,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4125,
+ "cached": 193463,
+ "costUsd": 0.056667875,
+ "input": 6188,
+ "output": 2475,
+ "tokens": 206251,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.017531249999999998,
+ "costCached": 0.089960475,
+ "costInput": 0.028773999999999997,
+ "costOutput": 0.066825,
+ "costUsd": 0.203090725,
+ "key": "5h",
+ "models": [
+ {
+ "cacheCreation": 2250,
+ "cached": 105526,
+ "costUsd": 0.11745050000000001,
+ "input": 3375,
+ "output": 1350,
+ "tokens": 112501,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 3150,
+ "cached": 147736,
+ "costUsd": 0.04327325,
+ "input": 4725,
+ "output": 1890,
+ "tokens": 157501,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.025840349999999998,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 975,
+ "cached": 45727,
+ "costUsd": 0.013394625,
+ "input": 1463,
+ "output": 585,
+ "tokens": 48750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 300,
+ "cached": 14070,
+ "costUsd": 0.003132,
+ "input": 450,
+ "output": 180,
+ "tokens": 15000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 446856,
+ "totalCacheCreation": 7500,
+ "totalCached": 351751,
+ "totalInput": 11251,
+ "totalOutput": 4500,
+ "totalTokens": 375002
+ },
+ {
+ "bucketMs": 720000,
+ "buckets": [
+ 0,
+ 15726,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8928,
+ 22662,
+ 64437,
+ 26831,
+ 68689,
+ 5370,
+ 32833,
+ 37839,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 35297,
+ 0,
+ 27974,
+ 72985,
+ 83388,
+ 34811,
+ 80541,
+ 96823,
+ 36471,
+ 72476,
+ 54595,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6433,
+ 0,
+ 0,
+ 4462,
+ 0,
+ 3576,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4860,
+ 29111,
+ 31310,
+ 61187,
+ 23074,
+ 82189,
+ 92288,
+ 81256,
+ 47364,
+ 44138,
+ 0,
+ 0,
+ 31657,
+ 0,
+ 23638,
+ 0,
+ 13934,
+ 34470,
+ 0,
+ 1466,
+ 73832,
+ 65087,
+ 44798,
+ 14534,
+ 38999,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1114,
+ 0,
+ 0,
+ 26539,
+ 31221,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8788,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 16200,
+ "cached": 759780,
+ "costUsd": 0.7028207999999999,
+ "input": 24300,
+ "output": 9720,
+ "tokens": 810000,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 19800,
+ "cached": 928620,
+ "costUsd": 0.2720025,
+ "input": 29700,
+ "output": 11880,
+ "tokens": 990000,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.08415,
+ "costCached": 0.43180830000000003,
+ "costInput": 0.13810499999999998,
+ "costOutput": 0.32075999999999993,
+ "costUsd": 0.9748233,
+ "key": "24h",
+ "models": [
+ {
+ "cacheCreation": 10800,
+ "cached": 506520,
+ "costUsd": 0.5637599999999999,
+ "input": 16200,
+ "output": 6480,
+ "tokens": 540000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 15120,
+ "cached": 709128,
+ "costUsd": 0.20771099999999998,
+ "input": 22680,
+ "output": 9072,
+ "tokens": 756000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 3960,
+ "cached": 185724,
+ "costUsd": 0.1240272,
+ "input": 5940,
+ "output": 2376,
+ "tokens": 198000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4680,
+ "cached": 219492,
+ "costUsd": 0.0642915,
+ "input": 7020,
+ "output": 2808,
+ "tokens": 234000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 1440,
+ "cached": 67536,
+ "costUsd": 0.0150336,
+ "input": 2160,
+ "output": 864,
+ "tokens": 72000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 484115,
+ "totalCacheCreation": 36000,
+ "totalCached": 1688400,
+ "totalInput": 54000,
+ "totalOutput": 21600,
+ "totalTokens": 1800000
+ },
+ {
+ "bucketMs": 5040000,
+ "buckets": [
+ 73985,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8016,
+ 0,
+ 0,
+ 36289,
+ 404583,
+ 352237,
+ 228216,
+ 472103,
+ 339863,
+ 438460,
+ 500493,
+ 423567,
+ 211937,
+ 172297,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 146476,
+ 0,
+ 236137,
+ 25838,
+ 111814,
+ 120229,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 96724,
+ 0,
+ 130376,
+ 225130,
+ 57578,
+ 191220,
+ 81770,
+ 240354,
+ 76270,
+ 0,
+ 84076,
+ 102748,
+ 0,
+ 0,
+ 0,
+ 230628,
+ 315003,
+ 315437,
+ 233622,
+ 621944,
+ 260240,
+ 574907,
+ 304894,
+ 337022,
+ 167548,
+ 0,
+ 23086,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 172139,
+ 97232,
+ 340168,
+ 142031,
+ 588699,
+ 576239,
+ 496389,
+ 214029,
+ 62760,
+ 41073,
+ 88646,
+ 0,
+ 0,
+ 134304,
+ 128527,
+ 0,
+ 0,
+ 10343,
+ 236681,
+ 297625
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 113400,
+ "cached": 5318461,
+ "costUsd": 4.9197461,
+ "input": 170100,
+ "output": 68040,
+ "tokens": 5670001,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 138600,
+ "cached": 6500341,
+ "costUsd": 1.9040176250000003,
+ "input": 207900,
+ "output": 83160,
+ "tokens": 6930001,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.5890500000000001,
+ "costCached": 3.022658725,
+ "costInput": 0.966735,
+ "costOutput": 2.24532,
+ "costUsd": 6.823763725,
+ "key": "7d",
+ "models": [
+ {
+ "cacheCreation": 75600,
+ "cached": 3545641,
+ "costUsd": 3.9463204999999997,
+ "input": 113400,
+ "output": 45360,
+ "tokens": 3780001,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 105840,
+ "cached": 4963897,
+ "costUsd": 1.4539771250000002,
+ "input": 158760,
+ "output": 63504,
+ "tokens": 5292001,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 27720,
+ "cached": 1300068,
+ "costUsd": 0.8681904,
+ "input": 41580,
+ "output": 16632,
+ "tokens": 1386000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 32760,
+ "cached": 1536444,
+ "costUsd": 0.4500405,
+ "input": 49140,
+ "output": 19656,
+ "tokens": 1638000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 10080,
+ "cached": 472752,
+ "costUsd": 0.1052352,
+ "input": 15120,
+ "output": 6048,
+ "tokens": 504000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 444246,
+ "totalCacheCreation": 252000,
+ "totalCached": 11818802,
+ "totalInput": 378000,
+ "totalOutput": 151200,
+ "totalTokens": 12600002
+ },
+ {
+ "bucketMs": 22320000,
+ "buckets": [
+ 177797,
+ 0,
+ 0,
+ 0,
+ 515858,
+ 248746,
+ 0,
+ 1474057,
+ 1966955,
+ 928023,
+ 649765,
+ 419884,
+ 1522641,
+ 1053001,
+ 30989,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 623353,
+ 0,
+ 901883,
+ 142466,
+ 315702,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 423922,
+ 534756,
+ 274375,
+ 1369660,
+ 1782795,
+ 2968815,
+ 3505018,
+ 2491644,
+ 2291638,
+ 2259080,
+ 702721,
+ 863431,
+ 0,
+ 547890,
+ 113403,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 162720,
+ 1205015,
+ 1153225,
+ 92098,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 411002,
+ 478378,
+ 740570,
+ 1813935,
+ 820713,
+ 70438,
+ 0,
+ 0,
+ 1609,
+ 0,
+ 417091,
+ 228279,
+ 179925,
+ 25937,
+ 2045794,
+ 341547,
+ 1340717,
+ 2959388,
+ 1436920,
+ 1700385,
+ 2791968,
+ 1374769,
+ 1062954,
+ 736326,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 499463,
+ 608561
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 502200,
+ "cached": 23553178,
+ "costUsd": 21.787444,
+ "input": 753300,
+ "output": 301320,
+ "tokens": 25109998,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 613800,
+ "cached": 28787217,
+ "costUsd": 8.432077125,
+ "input": 920700,
+ "output": 368280,
+ "tokens": 30689997,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 2.60865,
+ "costCached": 13.386056125,
+ "costInput": 4.281255,
+ "costOutput": 9.94356,
+ "costUsd": 30.219521125,
+ "key": "31d",
+ "models": [
+ {
+ "cacheCreation": 334800,
+ "cached": 15702119,
+ "costUsd": 17.4765595,
+ "input": 502200,
+ "output": 200880,
+ "tokens": 16739999,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 468720,
+ "cached": 21982966,
+ "costUsd": 6.43904075,
+ "input": 703080,
+ "output": 281232,
+ "tokens": 23435998,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 122760,
+ "cached": 5757443,
+ "costUsd": 3.8448428999999997,
+ "input": 184140,
+ "output": 73656,
+ "tokens": 6137999,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 145080,
+ "cached": 6804251,
+ "costUsd": 1.993036375,
+ "input": 217620,
+ "output": 87048,
+ "tokens": 7253999,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 44640,
+ "cached": 2093616,
+ "costUsd": 0.4660416,
+ "input": 66960,
+ "output": 26784,
+ "tokens": 2232000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 565325,
+ "totalCacheCreation": 1116000,
+ "totalCached": 52340395,
+ "totalInput": 1674000,
+ "totalOutput": 669600,
+ "totalTokens": 55799995
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/gui/tests/fixtures/rotated.json b/gui/tests/fixtures/rotated.json
new file mode 100644
index 0000000..34bead6
--- /dev/null
+++ b/gui/tests/fixtures/rotated.json
@@ -0,0 +1,1280 @@
+{
+ "snapshot": {
+ "accounts": [
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "9f4ae815",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000002",
+ "identity": "ship@rubriclabs.com",
+ "label": "ship@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_2",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:9f4ae815"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "b31c07d2",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000001",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_1",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:b31c07d2"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "c8d2f6a1",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000003",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/3",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "4e7b93c5",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000004",
+ "identity": "research@rubriclabs.com",
+ "label": "research@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_5x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/4",
+ "provider": "anthropic",
+ "secretReference": null
+ }
+ ],
+ "providers": [
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000002",
+ "generation": 8,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "openai",
+ "thresholdPercent": 90
+ },
+ "provider": "openai",
+ "switchedAt": "2026-07-15T16:40:00.000Z"
+ },
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000003",
+ "generation": 3,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "anthropic",
+ "thresholdPercent": 90
+ },
+ "provider": "anthropic",
+ "switchedAt": "2026-07-15T09:42:00.000Z"
+ }
+ ],
+ "sampledAt": "2026-07-15T16:41:48.000Z",
+ "usage": [
+ {
+ "accountId": "00000000-0000-4000-8000-000000000002",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T20:36:00.000Z",
+ "usedPercent": 6
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T15:15:36.000Z",
+ "usedPercent": 21
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000001",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T16:57:00.000Z",
+ "usedPercent": 98
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-17T15:44:24.000Z",
+ "usedPercent": 55
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": {
+ "applicable": 1,
+ "available": 1
+ },
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000003",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T19:12:00.000Z",
+ "usedPercent": 21
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T11:54:00.000Z",
+ "usedPercent": 27
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-18T20:18:00.000Z",
+ "usedPercent": 27
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000004",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T20:42:00.000Z",
+ "usedPercent": 4
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-19T18:08:24.000Z",
+ "usedPercent": 10
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-21T00:22:48.000Z",
+ "usedPercent": 4
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ }
+ ]
+ },
+ "tokens": {
+ "nowPerHour": 226338,
+ "timeframes": [
+ {
+ "bucketMs": 30000,
+ "buckets": [
+ 0,
+ 1499,
+ 0,
+ 1819,
+ 1719,
+ 2106,
+ 2525,
+ 1078,
+ 1130,
+ 1216,
+ 1863,
+ 1014,
+ 0,
+ 923,
+ 417,
+ 0,
+ 1132,
+ 215,
+ 1200,
+ 755,
+ 2229,
+ 1860,
+ 2121,
+ 1260,
+ 88,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 225,
+ 36,
+ 1020,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 187,
+ 201,
+ 545,
+ 2493,
+ 2051,
+ 1841,
+ 2311,
+ 1977,
+ 1763,
+ 1135,
+ 2517,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 812,
+ 0,
+ 803,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 971,
+ 1431,
+ 1508,
+ 1943,
+ 0,
+ 0,
+ 0,
+ 0,
+ 454,
+ 0,
+ 0,
+ 0,
+ 760,
+ 0,
+ 997,
+ 1988,
+ 3152,
+ 1649,
+ 3068,
+ 1561,
+ 1359,
+ 2219,
+ 1545,
+ 882,
+ 1313,
+ 0,
+ 106
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 675,
+ "cached": 31657,
+ "costUsd": 0.02928555,
+ "input": 1013,
+ "output": 405,
+ "tokens": 33750,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.011334,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.00350625,
+ "costCached": 0.017991800000000002,
+ "costInput": 0.0057565,
+ "costOutput": 0.013365,
+ "costUsd": 0.04061955,
+ "key": "1h",
+ "models": [
+ {
+ "cacheCreation": 450,
+ "cached": 21105,
+ "costUsd": 0.02349,
+ "input": 675,
+ "output": 270,
+ "tokens": 22500,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 630,
+ "cached": 29547,
+ "costUsd": 0.008654625,
+ "input": 945,
+ "output": 378,
+ "tokens": 31500,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 165,
+ "cached": 7738,
+ "costUsd": 0.005169149999999999,
+ "input": 248,
+ "output": 99,
+ "tokens": 8250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 195,
+ "cached": 9145,
+ "costUsd": 0.0026793750000000003,
+ "input": 293,
+ "output": 117,
+ "tokens": 9750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 60,
+ "cached": 2814,
+ "costUsd": 0.0006264,
+ "input": 90,
+ "output": 36,
+ "tokens": 3000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 378240,
+ "totalCacheCreation": 1500,
+ "totalCached": 70349,
+ "totalInput": 2251,
+ "totalOutput": 900,
+ "totalTokens": 75000
+ },
+ {
+ "bucketMs": 150000,
+ "buckets": [
+ 10154,
+ 8237,
+ 17197,
+ 12043,
+ 7356,
+ 10291,
+ 976,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3889,
+ 8344,
+ 8656,
+ 10781,
+ 17211,
+ 14527,
+ 3423,
+ 6282,
+ 6544,
+ 4782,
+ 2537,
+ 3849,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9922,
+ 395,
+ 3223,
+ 8652,
+ 13994,
+ 5426,
+ 6407,
+ 5352,
+ 4795,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3910,
+ 0,
+ 0,
+ 2176,
+ 0,
+ 0,
+ 134,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 956,
+ 0,
+ 8192,
+ 12083,
+ 6692,
+ 12369,
+ 18217,
+ 18304,
+ 18619,
+ 5955,
+ 11872,
+ 10147,
+ 8118,
+ 590,
+ 0,
+ 572,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4222,
+ 6774,
+ 2362,
+ 0,
+ 318,
+ 7050,
+ 126,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 3375,
+ "cached": 158288,
+ "costUsd": 0.14642285000000002,
+ "input": 5063,
+ "output": 2025,
+ "tokens": 168751,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4125,
+ "cached": 193463,
+ "costUsd": 0.056667875,
+ "input": 6188,
+ "output": 2475,
+ "tokens": 206251,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.017531249999999998,
+ "costCached": 0.089960475,
+ "costInput": 0.028773999999999997,
+ "costOutput": 0.066825,
+ "costUsd": 0.203090725,
+ "key": "5h",
+ "models": [
+ {
+ "cacheCreation": 2250,
+ "cached": 105526,
+ "costUsd": 0.11745050000000001,
+ "input": 3375,
+ "output": 1350,
+ "tokens": 112501,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 3150,
+ "cached": 147736,
+ "costUsd": 0.04327325,
+ "input": 4725,
+ "output": 1890,
+ "tokens": 157501,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.025840349999999998,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 975,
+ "cached": 45727,
+ "costUsd": 0.013394625,
+ "input": 1463,
+ "output": 585,
+ "tokens": 48750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 300,
+ "cached": 14070,
+ "costUsd": 0.003132,
+ "input": 450,
+ "output": 180,
+ "tokens": 15000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 446856,
+ "totalCacheCreation": 7500,
+ "totalCached": 351751,
+ "totalInput": 11251,
+ "totalOutput": 4500,
+ "totalTokens": 375002
+ },
+ {
+ "bucketMs": 720000,
+ "buckets": [
+ 0,
+ 15726,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8928,
+ 22662,
+ 64437,
+ 26831,
+ 68689,
+ 5370,
+ 32833,
+ 37839,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 35297,
+ 0,
+ 27974,
+ 72985,
+ 83388,
+ 34811,
+ 80541,
+ 96823,
+ 36471,
+ 72476,
+ 54595,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6433,
+ 0,
+ 0,
+ 4462,
+ 0,
+ 3576,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4860,
+ 29111,
+ 31310,
+ 61187,
+ 23074,
+ 82189,
+ 92288,
+ 81256,
+ 47364,
+ 44138,
+ 0,
+ 0,
+ 31657,
+ 0,
+ 23638,
+ 0,
+ 13934,
+ 34470,
+ 0,
+ 1466,
+ 73832,
+ 65087,
+ 44798,
+ 14534,
+ 38999,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1114,
+ 0,
+ 0,
+ 26539,
+ 31221,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8788,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 16200,
+ "cached": 759780,
+ "costUsd": 0.7028207999999999,
+ "input": 24300,
+ "output": 9720,
+ "tokens": 810000,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 19800,
+ "cached": 928620,
+ "costUsd": 0.2720025,
+ "input": 29700,
+ "output": 11880,
+ "tokens": 990000,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.08415,
+ "costCached": 0.43180830000000003,
+ "costInput": 0.13810499999999998,
+ "costOutput": 0.32075999999999993,
+ "costUsd": 0.9748233,
+ "key": "24h",
+ "models": [
+ {
+ "cacheCreation": 10800,
+ "cached": 506520,
+ "costUsd": 0.5637599999999999,
+ "input": 16200,
+ "output": 6480,
+ "tokens": 540000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 15120,
+ "cached": 709128,
+ "costUsd": 0.20771099999999998,
+ "input": 22680,
+ "output": 9072,
+ "tokens": 756000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 3960,
+ "cached": 185724,
+ "costUsd": 0.1240272,
+ "input": 5940,
+ "output": 2376,
+ "tokens": 198000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4680,
+ "cached": 219492,
+ "costUsd": 0.0642915,
+ "input": 7020,
+ "output": 2808,
+ "tokens": 234000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 1440,
+ "cached": 67536,
+ "costUsd": 0.0150336,
+ "input": 2160,
+ "output": 864,
+ "tokens": 72000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 484115,
+ "totalCacheCreation": 36000,
+ "totalCached": 1688400,
+ "totalInput": 54000,
+ "totalOutput": 21600,
+ "totalTokens": 1800000
+ },
+ {
+ "bucketMs": 5040000,
+ "buckets": [
+ 73985,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8016,
+ 0,
+ 0,
+ 36289,
+ 404583,
+ 352237,
+ 228216,
+ 472103,
+ 339863,
+ 438460,
+ 500493,
+ 423567,
+ 211937,
+ 172297,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 146476,
+ 0,
+ 236137,
+ 25838,
+ 111814,
+ 120229,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 96724,
+ 0,
+ 130376,
+ 225130,
+ 57578,
+ 191220,
+ 81770,
+ 240354,
+ 76270,
+ 0,
+ 84076,
+ 102748,
+ 0,
+ 0,
+ 0,
+ 230628,
+ 315003,
+ 315437,
+ 233622,
+ 621944,
+ 260240,
+ 574907,
+ 304894,
+ 337022,
+ 167548,
+ 0,
+ 23086,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 172139,
+ 97232,
+ 340168,
+ 142031,
+ 588699,
+ 576239,
+ 496389,
+ 214029,
+ 62760,
+ 41073,
+ 88646,
+ 0,
+ 0,
+ 134304,
+ 128527,
+ 0,
+ 0,
+ 10343,
+ 236681,
+ 297625
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 113400,
+ "cached": 5318461,
+ "costUsd": 4.9197461,
+ "input": 170100,
+ "output": 68040,
+ "tokens": 5670001,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 138600,
+ "cached": 6500341,
+ "costUsd": 1.9040176250000003,
+ "input": 207900,
+ "output": 83160,
+ "tokens": 6930001,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.5890500000000001,
+ "costCached": 3.022658725,
+ "costInput": 0.966735,
+ "costOutput": 2.24532,
+ "costUsd": 6.823763725,
+ "key": "7d",
+ "models": [
+ {
+ "cacheCreation": 75600,
+ "cached": 3545641,
+ "costUsd": 3.9463204999999997,
+ "input": 113400,
+ "output": 45360,
+ "tokens": 3780001,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 105840,
+ "cached": 4963897,
+ "costUsd": 1.4539771250000002,
+ "input": 158760,
+ "output": 63504,
+ "tokens": 5292001,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 27720,
+ "cached": 1300068,
+ "costUsd": 0.8681904,
+ "input": 41580,
+ "output": 16632,
+ "tokens": 1386000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 32760,
+ "cached": 1536444,
+ "costUsd": 0.4500405,
+ "input": 49140,
+ "output": 19656,
+ "tokens": 1638000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 10080,
+ "cached": 472752,
+ "costUsd": 0.1052352,
+ "input": 15120,
+ "output": 6048,
+ "tokens": 504000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 444246,
+ "totalCacheCreation": 252000,
+ "totalCached": 11818802,
+ "totalInput": 378000,
+ "totalOutput": 151200,
+ "totalTokens": 12600002
+ },
+ {
+ "bucketMs": 22320000,
+ "buckets": [
+ 177797,
+ 0,
+ 0,
+ 0,
+ 515858,
+ 248746,
+ 0,
+ 1474057,
+ 1966955,
+ 928023,
+ 649765,
+ 419884,
+ 1522641,
+ 1053001,
+ 30989,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 623353,
+ 0,
+ 901883,
+ 142466,
+ 315702,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 423922,
+ 534756,
+ 274375,
+ 1369660,
+ 1782795,
+ 2968815,
+ 3505018,
+ 2491644,
+ 2291638,
+ 2259080,
+ 702721,
+ 863431,
+ 0,
+ 547890,
+ 113403,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 162720,
+ 1205015,
+ 1153225,
+ 92098,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 411002,
+ 478378,
+ 740570,
+ 1813935,
+ 820713,
+ 70438,
+ 0,
+ 0,
+ 1609,
+ 0,
+ 417091,
+ 228279,
+ 179925,
+ 25937,
+ 2045794,
+ 341547,
+ 1340717,
+ 2959388,
+ 1436920,
+ 1700385,
+ 2791968,
+ 1374769,
+ 1062954,
+ 736326,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 499463,
+ 608561
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 502200,
+ "cached": 23553178,
+ "costUsd": 21.787444,
+ "input": 753300,
+ "output": 301320,
+ "tokens": 25109998,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 613800,
+ "cached": 28787217,
+ "costUsd": 8.432077125,
+ "input": 920700,
+ "output": 368280,
+ "tokens": 30689997,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 2.60865,
+ "costCached": 13.386056125,
+ "costInput": 4.281255,
+ "costOutput": 9.94356,
+ "costUsd": 30.219521125,
+ "key": "31d",
+ "models": [
+ {
+ "cacheCreation": 334800,
+ "cached": 15702119,
+ "costUsd": 17.4765595,
+ "input": 502200,
+ "output": 200880,
+ "tokens": 16739999,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 468720,
+ "cached": 21982966,
+ "costUsd": 6.43904075,
+ "input": 703080,
+ "output": 281232,
+ "tokens": 23435998,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 122760,
+ "cached": 5757443,
+ "costUsd": 3.8448428999999997,
+ "input": 184140,
+ "output": 73656,
+ "tokens": 6137999,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 145080,
+ "cached": 6804251,
+ "costUsd": 1.993036375,
+ "input": 217620,
+ "output": 87048,
+ "tokens": 7253999,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 44640,
+ "cached": 2093616,
+ "costUsd": 0.4660416,
+ "input": 66960,
+ "output": 26784,
+ "tokens": 2232000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 565325,
+ "totalCacheCreation": 1116000,
+ "totalCached": 52340395,
+ "totalInput": 1674000,
+ "totalOutput": 669600,
+ "totalTokens": 55799995
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/gui/tests/fixtures/tuned.json b/gui/tests/fixtures/tuned.json
new file mode 100644
index 0000000..55bad06
--- /dev/null
+++ b/gui/tests/fixtures/tuned.json
@@ -0,0 +1,1321 @@
+{
+ "snapshot": {
+ "accounts": [
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "b31c07d2",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000001",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_1",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:b31c07d2"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "9f4ae815",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000002",
+ "identity": "ship@rubriclabs.com",
+ "label": "ship@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "pro",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": "user_2",
+ "profilePath": null,
+ "provider": "openai",
+ "secretReference": "codex:9f4ae815"
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "c8d2f6a1",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000003",
+ "identity": "dexter@rubriclabs.com",
+ "label": "dexter@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_20x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/3",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "oauth",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "4e7b93c5",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000004",
+ "identity": "research@rubriclabs.com",
+ "label": "research@rubriclabs.com",
+ "onThreshold": "switch",
+ "plan": "claude_max_5x",
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/4",
+ "provider": "anthropic",
+ "secretReference": null
+ },
+ {
+ "auth": "apiKey",
+ "createdAt": "2026-06-11T16:42:00.000Z",
+ "enabled": true,
+ "externalAccountId": "a25d18f4",
+ "health": "ready",
+ "id": "00000000-0000-4000-8000-000000000005",
+ "identity": "anthropic api · prod",
+ "label": "anthropic api · prod",
+ "onThreshold": "switch",
+ "plan": null,
+ "updatedAt": "2026-07-15T16:40:00.000Z",
+ "externalUserId": null,
+ "profilePath": "/tmp/tokenmaxx/claude/5",
+ "provider": "anthropic",
+ "secretReference": null
+ }
+ ],
+ "providers": [
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000001",
+ "generation": 4,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 480000,
+ "provider": "openai",
+ "thresholdPercent": 85
+ },
+ "provider": "openai",
+ "switchedAt": "2026-07-15T15:06:00.000Z"
+ },
+ {
+ "activeAccountId": "00000000-0000-4000-8000-000000000003",
+ "generation": 2,
+ "policy": {
+ "authorization": "confirmed",
+ "enabled": true,
+ "hiddenWindowIds": [],
+ "hysteresisPercent": 5,
+ "maximumSnapshotAgeMilliseconds": 420000,
+ "minimumDwellMilliseconds": 300000,
+ "provider": "anthropic",
+ "thresholdPercent": 90
+ },
+ "provider": "anthropic",
+ "switchedAt": "2026-07-15T13:12:00.000Z"
+ }
+ ],
+ "sampledAt": "2026-07-15T16:41:48.000Z",
+ "usage": [
+ {
+ "accountId": "00000000-0000-4000-8000-000000000001",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T18:36:00.000Z",
+ "usedPercent": 41
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T06:51:36.000Z",
+ "usedPercent": 29
+ }
+ ],
+ "extraUsage": {
+ "balanceUsd": 18.5,
+ "enabled": true,
+ "exhausted": false,
+ "limitUsd": null,
+ "spentUsd": null,
+ "usedPercent": null
+ },
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": {
+ "applicable": 0,
+ "available": 3
+ },
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000002",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5 hour",
+ "resetAt": "2026-07-15T20:12:00.000Z",
+ "usedPercent": 8
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-18T10:13:12.000Z",
+ "usedPercent": 19
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "openai",
+ "resetCredits": null,
+ "source": "codexUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000003",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T18:57:00.000Z",
+ "usedPercent": 25
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-19T04:42:00.000Z",
+ "usedPercent": 14
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-19T14:46:48.000Z",
+ "usedPercent": 15
+ }
+ ],
+ "extraUsage": {
+ "balanceUsd": null,
+ "enabled": true,
+ "exhausted": false,
+ "limitUsd": 50,
+ "spentUsd": 12.4,
+ "usedPercent": 25
+ },
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000004",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [
+ {
+ "id": "five-hour",
+ "kind": "hard",
+ "label": "5h session",
+ "resetAt": "2026-07-15T20:30:00.000Z",
+ "usedPercent": 5
+ },
+ {
+ "id": "weekly",
+ "kind": "hard",
+ "label": "7 day · all models",
+ "resetAt": "2026-07-19T21:30:00.000Z",
+ "usedPercent": 9
+ },
+ {
+ "id": "weekly_scoped:fable",
+ "kind": "hard",
+ "label": "7 day · Fable",
+ "resetAt": "2026-07-21T07:06:00.000Z",
+ "usedPercent": 3
+ }
+ ],
+ "extraUsage": null,
+ "measuredSpendUsd": null,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ },
+ {
+ "accountId": "00000000-0000-4000-8000-000000000005",
+ "hardLimitReached": false,
+ "observedAt": "2026-07-15T16:41:49.402Z",
+ "windows": [],
+ "extraUsage": null,
+ "measuredSpendUsd": 23.71,
+ "provider": "anthropic",
+ "source": "claudeUsageEndpoint"
+ }
+ ]
+ },
+ "tokens": {
+ "nowPerHour": 226338,
+ "timeframes": [
+ {
+ "bucketMs": 30000,
+ "buckets": [
+ 0,
+ 1499,
+ 0,
+ 1819,
+ 1719,
+ 2106,
+ 2525,
+ 1078,
+ 1130,
+ 1216,
+ 1863,
+ 1014,
+ 0,
+ 923,
+ 417,
+ 0,
+ 1132,
+ 215,
+ 1200,
+ 755,
+ 2229,
+ 1860,
+ 2121,
+ 1260,
+ 88,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 225,
+ 36,
+ 1020,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 187,
+ 201,
+ 545,
+ 2493,
+ 2051,
+ 1841,
+ 2311,
+ 1977,
+ 1763,
+ 1135,
+ 2517,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 812,
+ 0,
+ 803,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 971,
+ 1431,
+ 1508,
+ 1943,
+ 0,
+ 0,
+ 0,
+ 0,
+ 454,
+ 0,
+ 0,
+ 0,
+ 760,
+ 0,
+ 997,
+ 1988,
+ 3152,
+ 1649,
+ 3068,
+ 1561,
+ 1359,
+ 2219,
+ 1545,
+ 882,
+ 1313,
+ 0,
+ 106
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 675,
+ "cached": 31657,
+ "costUsd": 0.02928555,
+ "input": 1013,
+ "output": 405,
+ "tokens": 33750,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.011334,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.00350625,
+ "costCached": 0.017991800000000002,
+ "costInput": 0.0057565,
+ "costOutput": 0.013365,
+ "costUsd": 0.04061955,
+ "key": "1h",
+ "models": [
+ {
+ "cacheCreation": 450,
+ "cached": 21105,
+ "costUsd": 0.02349,
+ "input": 675,
+ "output": 270,
+ "tokens": 22500,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 630,
+ "cached": 29547,
+ "costUsd": 0.008654625,
+ "input": 945,
+ "output": 378,
+ "tokens": 31500,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 165,
+ "cached": 7738,
+ "costUsd": 0.005169149999999999,
+ "input": 248,
+ "output": 99,
+ "tokens": 8250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 195,
+ "cached": 9145,
+ "costUsd": 0.0026793750000000003,
+ "input": 293,
+ "output": 117,
+ "tokens": 9750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 60,
+ "cached": 2814,
+ "costUsd": 0.0006264,
+ "input": 90,
+ "output": 36,
+ "tokens": 3000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 378240,
+ "totalCacheCreation": 1500,
+ "totalCached": 70349,
+ "totalInput": 2251,
+ "totalOutput": 900,
+ "totalTokens": 75000
+ },
+ {
+ "bucketMs": 150000,
+ "buckets": [
+ 10154,
+ 8237,
+ 17197,
+ 12043,
+ 7356,
+ 10291,
+ 976,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3889,
+ 8344,
+ 8656,
+ 10781,
+ 17211,
+ 14527,
+ 3423,
+ 6282,
+ 6544,
+ 4782,
+ 2537,
+ 3849,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9922,
+ 395,
+ 3223,
+ 8652,
+ 13994,
+ 5426,
+ 6407,
+ 5352,
+ 4795,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3910,
+ 0,
+ 0,
+ 2176,
+ 0,
+ 0,
+ 134,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 956,
+ 0,
+ 8192,
+ 12083,
+ 6692,
+ 12369,
+ 18217,
+ 18304,
+ 18619,
+ 5955,
+ 11872,
+ 10147,
+ 8118,
+ 590,
+ 0,
+ 572,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4222,
+ 6774,
+ 2362,
+ 0,
+ 318,
+ 7050,
+ 126,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 3375,
+ "cached": 158288,
+ "costUsd": 0.14642285000000002,
+ "input": 5063,
+ "output": 2025,
+ "tokens": 168751,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4125,
+ "cached": 193463,
+ "costUsd": 0.056667875,
+ "input": 6188,
+ "output": 2475,
+ "tokens": 206251,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.017531249999999998,
+ "costCached": 0.089960475,
+ "costInput": 0.028773999999999997,
+ "costOutput": 0.066825,
+ "costUsd": 0.203090725,
+ "key": "5h",
+ "models": [
+ {
+ "cacheCreation": 2250,
+ "cached": 105526,
+ "costUsd": 0.11745050000000001,
+ "input": 3375,
+ "output": 1350,
+ "tokens": 112501,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 3150,
+ "cached": 147736,
+ "costUsd": 0.04327325,
+ "input": 4725,
+ "output": 1890,
+ "tokens": 157501,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 825,
+ "cached": 38692,
+ "costUsd": 0.025840349999999998,
+ "input": 1238,
+ "output": 495,
+ "tokens": 41250,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 975,
+ "cached": 45727,
+ "costUsd": 0.013394625,
+ "input": 1463,
+ "output": 585,
+ "tokens": 48750,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 300,
+ "cached": 14070,
+ "costUsd": 0.003132,
+ "input": 450,
+ "output": 180,
+ "tokens": 15000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 446856,
+ "totalCacheCreation": 7500,
+ "totalCached": 351751,
+ "totalInput": 11251,
+ "totalOutput": 4500,
+ "totalTokens": 375002
+ },
+ {
+ "bucketMs": 720000,
+ "buckets": [
+ 0,
+ 15726,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8928,
+ 22662,
+ 64437,
+ 26831,
+ 68689,
+ 5370,
+ 32833,
+ 37839,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 35297,
+ 0,
+ 27974,
+ 72985,
+ 83388,
+ 34811,
+ 80541,
+ 96823,
+ 36471,
+ 72476,
+ 54595,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6433,
+ 0,
+ 0,
+ 4462,
+ 0,
+ 3576,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4860,
+ 29111,
+ 31310,
+ 61187,
+ 23074,
+ 82189,
+ 92288,
+ 81256,
+ 47364,
+ 44138,
+ 0,
+ 0,
+ 31657,
+ 0,
+ 23638,
+ 0,
+ 13934,
+ 34470,
+ 0,
+ 1466,
+ 73832,
+ 65087,
+ 44798,
+ 14534,
+ 38999,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1114,
+ 0,
+ 0,
+ 26539,
+ 31221,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8788,
+ 0
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 16200,
+ "cached": 759780,
+ "costUsd": 0.7028207999999999,
+ "input": 24300,
+ "output": 9720,
+ "tokens": 810000,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 19800,
+ "cached": 928620,
+ "costUsd": 0.2720025,
+ "input": 29700,
+ "output": 11880,
+ "tokens": 990000,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.08415,
+ "costCached": 0.43180830000000003,
+ "costInput": 0.13810499999999998,
+ "costOutput": 0.32075999999999993,
+ "costUsd": 0.9748233,
+ "key": "24h",
+ "models": [
+ {
+ "cacheCreation": 10800,
+ "cached": 506520,
+ "costUsd": 0.5637599999999999,
+ "input": 16200,
+ "output": 6480,
+ "tokens": 540000,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 15120,
+ "cached": 709128,
+ "costUsd": 0.20771099999999998,
+ "input": 22680,
+ "output": 9072,
+ "tokens": 756000,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 3960,
+ "cached": 185724,
+ "costUsd": 0.1240272,
+ "input": 5940,
+ "output": 2376,
+ "tokens": 198000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 4680,
+ "cached": 219492,
+ "costUsd": 0.0642915,
+ "input": 7020,
+ "output": 2808,
+ "tokens": 234000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 1440,
+ "cached": 67536,
+ "costUsd": 0.0150336,
+ "input": 2160,
+ "output": 864,
+ "tokens": 72000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 484115,
+ "totalCacheCreation": 36000,
+ "totalCached": 1688400,
+ "totalInput": 54000,
+ "totalOutput": 21600,
+ "totalTokens": 1800000
+ },
+ {
+ "bucketMs": 5040000,
+ "buckets": [
+ 73985,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8016,
+ 0,
+ 0,
+ 36289,
+ 404583,
+ 352237,
+ 228216,
+ 472103,
+ 339863,
+ 438460,
+ 500493,
+ 423567,
+ 211937,
+ 172297,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 146476,
+ 0,
+ 236137,
+ 25838,
+ 111814,
+ 120229,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 96724,
+ 0,
+ 130376,
+ 225130,
+ 57578,
+ 191220,
+ 81770,
+ 240354,
+ 76270,
+ 0,
+ 84076,
+ 102748,
+ 0,
+ 0,
+ 0,
+ 230628,
+ 315003,
+ 315437,
+ 233622,
+ 621944,
+ 260240,
+ 574907,
+ 304894,
+ 337022,
+ 167548,
+ 0,
+ 23086,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 172139,
+ 97232,
+ 340168,
+ 142031,
+ 588699,
+ 576239,
+ 496389,
+ 214029,
+ 62760,
+ 41073,
+ 88646,
+ 0,
+ 0,
+ 134304,
+ 128527,
+ 0,
+ 0,
+ 10343,
+ 236681,
+ 297625
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 113400,
+ "cached": 5318461,
+ "costUsd": 4.9197461,
+ "input": 170100,
+ "output": 68040,
+ "tokens": 5670001,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 138600,
+ "cached": 6500341,
+ "costUsd": 1.9040176250000003,
+ "input": 207900,
+ "output": 83160,
+ "tokens": 6930001,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 0.5890500000000001,
+ "costCached": 3.022658725,
+ "costInput": 0.966735,
+ "costOutput": 2.24532,
+ "costUsd": 6.823763725,
+ "key": "7d",
+ "models": [
+ {
+ "cacheCreation": 75600,
+ "cached": 3545641,
+ "costUsd": 3.9463204999999997,
+ "input": 113400,
+ "output": 45360,
+ "tokens": 3780001,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 105840,
+ "cached": 4963897,
+ "costUsd": 1.4539771250000002,
+ "input": 158760,
+ "output": 63504,
+ "tokens": 5292001,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 27720,
+ "cached": 1300068,
+ "costUsd": 0.8681904,
+ "input": 41580,
+ "output": 16632,
+ "tokens": 1386000,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 32760,
+ "cached": 1536444,
+ "costUsd": 0.4500405,
+ "input": 49140,
+ "output": 19656,
+ "tokens": 1638000,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 10080,
+ "cached": 472752,
+ "costUsd": 0.1052352,
+ "input": 15120,
+ "output": 6048,
+ "tokens": 504000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 444246,
+ "totalCacheCreation": 252000,
+ "totalCached": 11818802,
+ "totalInput": 378000,
+ "totalOutput": 151200,
+ "totalTokens": 12600002
+ },
+ {
+ "bucketMs": 22320000,
+ "buckets": [
+ 177797,
+ 0,
+ 0,
+ 0,
+ 515858,
+ 248746,
+ 0,
+ 1474057,
+ 1966955,
+ 928023,
+ 649765,
+ 419884,
+ 1522641,
+ 1053001,
+ 30989,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 623353,
+ 0,
+ 901883,
+ 142466,
+ 315702,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 423922,
+ 534756,
+ 274375,
+ 1369660,
+ 1782795,
+ 2968815,
+ 3505018,
+ 2491644,
+ 2291638,
+ 2259080,
+ 702721,
+ 863431,
+ 0,
+ 547890,
+ 113403,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 162720,
+ 1205015,
+ 1153225,
+ 92098,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 411002,
+ 478378,
+ 740570,
+ 1813935,
+ 820713,
+ 70438,
+ 0,
+ 0,
+ 1609,
+ 0,
+ 417091,
+ 228279,
+ 179925,
+ 25937,
+ 2045794,
+ 341547,
+ 1340717,
+ 2959388,
+ 1436920,
+ 1700385,
+ 2791968,
+ 1374769,
+ 1062954,
+ 736326,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 499463,
+ 608561
+ ],
+ "byProvider": [
+ {
+ "cacheCreation": 502200,
+ "cached": 23553178,
+ "costUsd": 21.787444,
+ "input": 753300,
+ "output": 301320,
+ "tokens": 25109998,
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 613800,
+ "cached": 28787217,
+ "costUsd": 8.432077125,
+ "input": 920700,
+ "output": 368280,
+ "tokens": 30689997,
+ "provider": "openai"
+ }
+ ],
+ "costCacheCreation": 2.60865,
+ "costCached": 13.386056125,
+ "costInput": 4.281255,
+ "costOutput": 9.94356,
+ "costUsd": 30.219521125,
+ "key": "31d",
+ "models": [
+ {
+ "cacheCreation": 334800,
+ "cached": 15702119,
+ "costUsd": 17.4765595,
+ "input": 502200,
+ "output": 200880,
+ "tokens": 16739999,
+ "model": "claude-opus-4-8",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 468720,
+ "cached": 21982966,
+ "costUsd": 6.43904075,
+ "input": 703080,
+ "output": 281232,
+ "tokens": 23435998,
+ "model": "gpt-5.6-sol",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 122760,
+ "cached": 5757443,
+ "costUsd": 3.8448428999999997,
+ "input": 184140,
+ "output": 73656,
+ "tokens": 6137999,
+ "model": "claude-sonnet-4-6",
+ "provider": "anthropic"
+ },
+ {
+ "cacheCreation": 145080,
+ "cached": 6804251,
+ "costUsd": 1.993036375,
+ "input": 217620,
+ "output": 87048,
+ "tokens": 7253999,
+ "model": "gpt-5.6-codex",
+ "provider": "openai"
+ },
+ {
+ "cacheCreation": 44640,
+ "cached": 2093616,
+ "costUsd": 0.4660416,
+ "input": 66960,
+ "output": 26784,
+ "tokens": 2232000,
+ "model": "claude-haiku-4-5",
+ "provider": "anthropic"
+ }
+ ],
+ "peakPerHour": 565325,
+ "totalCacheCreation": 1116000,
+ "totalCached": 52340395,
+ "totalInput": 1674000,
+ "totalOutput": 669600,
+ "totalTokens": 55799995
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 7ec8ed3..a07aabf 100644
--- a/package.json
+++ b/package.json
@@ -48,10 +48,13 @@
"scripts": {
"bleed": "bun x npm-check-updates -u",
"build": "bun run clean && bun build ./src/index.ts --target bun --outdir dist --external '@opentui/*' && cp bin/launcher.cjs dist/launcher.cjs && chmod 755 dist/index.js dist/launcher.cjs",
+ "build:bin": "bun build --compile ./src/index.ts --outfile gui/target/bin/tokenmaxx",
"check": "bun run typecheck && bun x biome check . && bun test",
"clean": "rm -rf dist",
"dev": "bun run src/index.ts",
"format": "bun x biome check --write .",
+ "gui:bundle": "gui/scripts/bundle.sh",
+ "gui:dev": "bun run build:bin && TOKENMAXX_BIN=gui/target/bin/tokenmaxx cargo run --manifest-path gui/Cargo.toml",
"prepare": "bun x @rubriclab/package prepare",
"typecheck": "tsc --noEmit"
},
@@ -59,5 +62,5 @@
"post-commit": "bun x @rubriclab/package post-commit"
},
"type": "module",
- "version": "0.0.66"
+ "version": "0.0.67"
}
diff --git a/src/cli.ts b/src/cli.ts
index 356b520..f025f96 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -5,8 +5,8 @@ import { homedir } from 'node:os'
import { join } from 'node:path'
import { createInterface } from 'node:readline/promises'
import { z } from 'zod'
-import { registerClaudeAccount, registerClaudeApiKeyAccount } from './claude.ts'
-import { registerCodexAccount, registerOpenAiApiKeyAccount } from './codex.ts'
+import { registerClaudeAccount } from './claude.ts'
+import { registerCodexAccount } from './codex.ts'
import {
healInstalledConfigs,
installClaudeConfig,
@@ -26,8 +26,11 @@ import {
managerVersion,
readDashboard,
readProxyPort,
+ readRouting,
requestAccountRemove,
requestAccountSave,
+ requestAddApiKey,
+ requestRouting,
requestSwitch,
startManagerServer
} from './ipc.ts'
@@ -37,7 +40,7 @@ import { proxyIdentity } from './proxy.ts'
import { createStateStore, type StateStore } from './storage.ts'
import { renderDashboard } from './ui.ts'
import { createMacOsKeychainVault } from './vault.ts'
-import { availableUpdate, installedVersion, VERSION } from './version.ts'
+import { availableUpdate, compiledBinary, installedVersion, VERSION } from './version.ts'
const DaemonLockSchema = z
.object({
@@ -351,20 +354,28 @@ async function runDaemon(context: ApplicationContext): Promise {
}
}
+function daemonCommandArguments(): string[] {
+ if (compiledBinary) {
+ return ['daemon', 'run']
+ }
+ const entrypoint = process.argv[1]
+ if (entrypoint === undefined) {
+ throw new ApplicationError('ENTRYPOINT_MISSING', 'Cannot locate the CLI entrypoint')
+ }
+ return [entrypoint, 'daemon', 'run']
+}
+
async function startDaemon(context: ApplicationContext): Promise {
if (await managerAvailable(context.paths.managerSocket)) {
return
}
await replacePortOccupant(context.paths.proxyPort)
await mkdir(context.paths.runtime, { mode: 0o700, recursive: true })
- const entrypoint = process.argv[1]
- if (entrypoint === undefined) {
- throw new ApplicationError('ENTRYPOINT_MISSING', 'Cannot locate the CLI entrypoint')
- }
+ const daemonArguments = daemonCommandArguments()
const logDescriptor = openSync(join(context.paths.runtime, 'daemon.log'), 'a', 0o600)
try {
for (let attempt = 0; attempt < 3; attempt += 1) {
- const child = spawn(process.execPath, [entrypoint, 'daemon', 'run'], {
+ const child = spawn(process.execPath, daemonArguments, {
detached: true,
env: process.env,
stdio: ['ignore', logDescriptor, logDescriptor]
@@ -543,10 +554,9 @@ export function stripTerminalNoise(line: string): string {
return clean.trim()
}
-async function registerApiKeyAccount(
- provider: 'openai' | 'anthropic',
+async function promptApiKey(
keyArgument: string | undefined
-): Promise {
+): Promise<{ key: string; label: string }> {
if (process.stdin.isTTY !== true && keyArgument === undefined) {
throw new ApplicationError(
'USAGE',
@@ -555,41 +565,19 @@ async function registerApiKeyAccount(
}
await handTerminalBack()
const readline = createInterface({ input: process.stdin, output: process.stdout })
- let key: string
- let label: string
try {
- key = keyArgument ?? stripTerminalNoise(await readline.question('Paste the API key: '))
- label = stripTerminalNoise(
+ const key = keyArgument ?? stripTerminalNoise(await readline.question('Paste the API key: '))
+ const label = stripTerminalNoise(
await readline.question('Name this account (shown in the dashboard): ')
)
+ return { key, label }
} finally {
readline.close()
}
- if (label.trim().length === 0) {
- throw new ApplicationError('USAGE', 'The account needs a name')
- }
- const vault = createMacOsKeychainVault()
- return provider === 'openai'
- ? registerOpenAiApiKeyAccount({ key, label: label.trim(), vault })
- : registerClaudeApiKeyAccount({ key, label: label.trim(), vault })
}
-async function login(
- context: ApplicationContext,
- providerArgument: string | undefined,
- options: { apiKey: boolean; apiKeyValue?: string } = { apiKey: false }
-): Promise {
- if (providerArgument === undefined) {
- throw new ApplicationError('USAGE', 'Usage: tokenmaxx login [--api-key [key]]')
- }
- const provider = providerFromCli(providerArgument)
- if (!options.apiKey) {
- assertCliInstalled(provider)
- }
- await ensureDaemon(context)
- const authenticated = options.apiKey
- ? await registerApiKeyAccount(provider, options.apiKeyValue)
- : await registerIsolatedAccount(provider)
+async function signInOauth(context: ApplicationContext, provider: ProviderId): Promise {
+ const authenticated = await registerIsolatedAccount(provider)
const existing = context.store
.listAccounts(provider)
.find(
@@ -612,7 +600,9 @@ async function login(
secretReference: existing?.secretReference ?? null
})
} catch (error) {
- await removeUnstoredAccount(authenticated)
+ if (authenticated.secretReference !== null) {
+ await createMacOsKeychainVault().remove(authenticated.secretReference)
+ }
throw error
}
process.stdout.write(
@@ -620,21 +610,38 @@ async function login(
? `Signed in ${account.label}.\n`
: `Re-authenticated ${account.label}; live sessions pick it up on their next request.\n`
)
- if (existing === undefined) {
- const status = await installStatus()
- const alreadyRouted = provider === 'openai' ? status.codexRouted : status.claudeRouted
- if (!alreadyRouted) {
- await setRouting(context, provider, true).catch(() => undefined)
- process.stdout.write(
- `tokenmaxx is on for ${providerArgument} — run ${providerArgument} as usual.\n`
- )
- }
- }
+ return existing === undefined
}
-async function removeUnstoredAccount(account: Account): Promise {
- if (account.secretReference !== null) {
- await createMacOsKeychainVault().remove(account.secretReference)
+async function login(
+ context: ApplicationContext,
+ providerArgument: string | undefined,
+ options: { apiKey: boolean; apiKeyValue?: string } = { apiKey: false }
+): Promise {
+ if (providerArgument === undefined) {
+ throw new ApplicationError('USAGE', 'Usage: tokenmaxx login [--api-key [key]]')
+ }
+ const provider = providerFromCli(providerArgument)
+ if (!options.apiKey) {
+ assertCliInstalled(provider)
+ }
+ await ensureDaemon(context)
+ const socket = context.paths.managerSocket
+ if (options.apiKey) {
+ const account = await requestAddApiKey(socket, {
+ provider,
+ ...(await promptApiKey(options.apiKeyValue))
+ })
+ process.stdout.write(`Signed in ${account.label}.\n`)
+ } else if (!(await signInOauth(context, provider))) {
+ return
+ }
+ const routing = await readRouting(socket)
+ if (!routing.routed[provider]) {
+ await requestRouting(socket, provider, true).catch(() => undefined)
+ process.stdout.write(
+ `tokenmaxx is on for ${providerArgument} — run ${providerArgument} as usual.\n`
+ )
}
}
@@ -840,18 +847,6 @@ async function uninstallConfig(targetArgument?: string): Promise {
)
}
-async function setRouting(
- context: ApplicationContext,
- provider: ProviderId,
- enable: boolean
-): Promise {
- if (provider === 'openai') {
- await (enable ? installCodexConfig(context.paths) : uninstallCodexConfig())
- } else {
- await (enable ? installClaudeConfig(context.paths) : uninstallClaudeConfig())
- }
-}
-
async function doctor(context: ApplicationContext): Promise {
const tools = [
['bun', '1.2+'],
@@ -884,7 +879,7 @@ async function doctor(context: ApplicationContext): Promise {
process.stdout.write(
update === null
? `ok version ${VERSION} (latest)\n`
- : `note version ${VERSION} — v${update} is out: bun add -g tokenmaxx\n`
+ : `note version ${VERSION} — v${update} is out: ${compiledBinary ? 'update the tokenmaxx app' : 'bun add -g tokenmaxx'}\n`
)
if (running) {
const port = await readProxyPort(context.paths.managerSocket).catch(() => null)
@@ -954,9 +949,9 @@ export async function runCli(rawArguments: readonly string[]): Promise {
fixture: {
name: fixtureName,
now,
+ routed,
timewarp: Number.isFinite(timewarp) && timewarp > 0 ? timewarp : 0
- },
- routing: { anthropic: routed, openai: routed }
+ }
})
context.store.close()
process.exit(0)
@@ -964,16 +959,9 @@ export async function runCli(rawArguments: readonly string[]): Promise {
await ensureDaemon(context)
if (process.stdout.isTTY) {
const { runTuiDashboard } = await import('./tui/dashboard.ts')
- const readRouting = async (): Promise> => {
- const status = await installStatus()
- return { anthropic: status.claudeRouted, openai: status.codexRouted }
- }
let alert = ''
for (;;) {
- const action = await runTuiDashboard(context.paths.managerSocket, {
- alert,
- routing: await readRouting()
- })
+ const action = await runTuiDashboard(context.paths.managerSocket, { alert })
alert = ''
await handTerminalBack()
if (action === undefined) {
@@ -995,13 +983,13 @@ export async function runCli(rawArguments: readonly string[]): Promise {
})
continue
}
- if (action.kind === 'routing') {
- await setRouting(context, action.provider, action.enable).catch(error => {
- alert = errorMessage(error)
- })
- continue
- }
if (action.kind === 'update') {
+ if (compiledBinary) {
+ process.stdout.write(
+ `v${action.version} is out — update the tokenmaxx app from https://tokenmaxx.sh\n`
+ )
+ break
+ }
process.stdout.write(`Updating tokenmaxx to v${action.version}…\n`)
const bun = Bun.which('bun') ?? 'bun'
const result = Bun.spawnSync([bun, 'add', '-g', `tokenmaxx@${action.version}`], {
@@ -1022,6 +1010,11 @@ export async function runCli(rawArguments: readonly string[]): Promise {
process.stdout.write(`${renderDashboard(await readDashboard(context.paths.managerSocket))}\n`)
return 0
}
+ case 'version':
+ case '--version':
+ case '-v':
+ process.stdout.write(`${VERSION}\n`)
+ return 0
case 'help':
case '--help':
case '-h':
@@ -1075,7 +1068,7 @@ export async function runCli(rawArguments: readonly string[]): Promise {
await runDaemon(context)
return 0
case 'start':
- await startDaemon(context)
+ await ensureDaemon(context)
process.stdout.write('Manager daemon is running.\n')
return 0
case 'stop':
diff --git a/src/config-install.test.ts b/src/config-install.test.ts
index a7da7c3..317dc28 100644
--- a/src/config-install.test.ts
+++ b/src/config-install.test.ts
@@ -222,6 +222,21 @@ describe('healInstalledConfigs', () => {
expect((await installStatus()).codexRouted).toBe(false)
})
+ test('leaves configs routed to another instance alone', async () => {
+ await installCodexConfig(paths())
+ await installClaudeConfig(paths())
+ const elsewhere = applicationPaths({
+ ...process.env,
+ TOKENMAXX_HOME: join(home, 'elsewhere'),
+ TOKENMAXX_PROXY_PORT: '18459'
+ })
+ expect(await healInstalledConfigs(elsewhere)).toEqual([])
+ expect((await readClaudeSettings()).env?.ANTHROPIC_BASE_URL).toBe(
+ 'http://127.0.0.1:8459/anthropic'
+ )
+ expect(await readCodexConfig()).toContain('http://127.0.0.1:8459/openai')
+ })
+
test('runs once per version, not on every start', async () => {
await healInstalledConfigs(paths())
await writeClaudeSettings({
diff --git a/src/config-install.ts b/src/config-install.ts
index fb10149..1ee9e87 100644
--- a/src/config-install.ts
+++ b/src/config-install.ts
@@ -182,11 +182,14 @@ interface InstallStatus {
codexRouted: boolean
claudeRouted: boolean
codexStale: boolean
+ codexBaseUrl: string | null
+ claudeBaseUrl: string | null
}
export async function installStatus(): Promise {
const codexRaw = await readFileOrEmpty(codexConfigPath())
let codexRouted = false
+ let codexBaseUrl: string | null = null
try {
const parsed = Bun.TOML.parse(codexRaw) as {
model_provider?: unknown
@@ -194,7 +197,8 @@ export async function installStatus(): Promise {
}
const selected = typeof parsed.model_provider === 'string' ? parsed.model_provider : null
const baseUrl = selected === null ? undefined : parsed.model_providers?.[selected]?.base_url
- codexRouted = typeof baseUrl === 'string' && baseUrl.includes('127.0.0.1')
+ codexBaseUrl = typeof baseUrl === 'string' ? baseUrl : null
+ codexRouted = codexBaseUrl?.includes('127.0.0.1') ?? false
} catch {
codexRouted = false
}
@@ -203,31 +207,33 @@ export async function installStatus(): Promise {
([...legacyBeginMarkers, tableBeginMarker].some(marker => codexRaw.includes(marker)) ||
codexRaw.match(bareProviderTable) !== null)
- let claudeRouted = false
+ let claudeBaseUrl: string | null = null
try {
const settings = JSON.parse(await readFileOrEmpty(claudeSettingsPath())) as ClaudeSettings
- claudeRouted = settings.env?.ANTHROPIC_BASE_URL?.includes('127.0.0.1') ?? false
+ claudeBaseUrl = settings.env?.ANTHROPIC_BASE_URL ?? null
} catch {
- claudeRouted = false
+ claudeBaseUrl = null
}
- return { claudeRouted, codexRouted, codexStale }
+ const claudeRouted = claudeBaseUrl?.includes('127.0.0.1') ?? false
+ return { claudeBaseUrl, claudeRouted, codexBaseUrl, codexRouted, codexStale }
}
// Configs written by an older version stay stale after an update (#17): re-apply
// install for whatever is currently routed, once per version change. Never adds
-// routing — a harness the user uninstalled or never installed stays untouched.
+// routing — a harness the user uninstalled or never installed stays untouched, and a
+// config routed to another tokenmaxx instance's port belongs to that instance.
export async function healInstalledConfigs(paths: ApplicationPaths): Promise {
const stampPath = join(paths.root, 'healed-version')
if ((await readFileOrEmpty(stampPath)).trim() === VERSION) {
return []
}
- const { claudeRouted, codexRouted } = await installStatus()
+ const { claudeBaseUrl, codexBaseUrl } = await installStatus()
const healed: string[] = []
- if (codexRouted) {
+ if (codexBaseUrl === proxyBaseUrl(paths, 'openai')) {
await installCodexConfig(paths)
healed.push('codex')
}
- if (claudeRouted) {
+ if (claudeBaseUrl === proxyBaseUrl(paths, 'anthropic')) {
await installClaudeConfig(paths)
healed.push('claude')
}
diff --git a/src/ipc.test.ts b/src/ipc.test.ts
new file mode 100644
index 0000000..03cf1e7
--- /dev/null
+++ b/src/ipc.test.ts
@@ -0,0 +1,122 @@
+import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
+import { mkdtempSync, rmSync } from 'node:fs'
+import { mkdir, readFile, writeFile } from 'node:fs/promises'
+import { tmpdir } from 'node:os'
+import { join } from 'node:path'
+import { ApplicationError } from './errors.ts'
+import {
+ readDashboard,
+ readRouting,
+ requestAddApiKey,
+ requestRouting,
+ startManagerServer
+} from './ipc.ts'
+import { AccountManager } from './manager.ts'
+import { applicationPaths, ensureApplicationPaths } from './paths.ts'
+import { createStateStore } from './storage.ts'
+import type { CredentialVault } from './vault.ts'
+
+const secrets = new Map()
+const vault: CredentialVault = {
+ async read(reference) {
+ return secrets.get(reference) ?? null
+ },
+ async remove(reference) {
+ secrets.delete(reference)
+ },
+ async write(reference, value) {
+ secrets.set(reference, value)
+ }
+}
+
+const acceptingFetch = async () => new Response('{}', { status: 200 })
+
+let home = ''
+let socketPath = ''
+let close: () => Promise = async () => undefined
+
+beforeEach(async () => {
+ home = mkdtempSync(join(tmpdir(), 'tokenmaxx-ipc-'))
+ process.env.CODEX_HOME = join(home, 'codex')
+ process.env.CLAUDE_CONFIG_DIR = join(home, 'claude')
+ process.env.PI_CODING_AGENT_DIR = join(home, 'pi')
+ await mkdir(process.env.CODEX_HOME, { recursive: true })
+ await mkdir(process.env.CLAUDE_CONFIG_DIR, { recursive: true })
+ const paths = applicationPaths({ ...process.env, TOKENMAXX_HOME: join(home, 'state') })
+ await ensureApplicationPaths(paths)
+ const manager = new AccountManager({
+ dependencies: { fetchImplementation: acceptingFetch },
+ paths,
+ store: createStateStore(paths.database),
+ vault
+ })
+ socketPath = paths.managerSocket
+ const server = await startManagerServer({ manager, onStop: () => undefined, socketPath })
+ close = server.close
+})
+
+afterEach(async () => {
+ await close()
+ delete process.env.CODEX_HOME
+ delete process.env.CLAUDE_CONFIG_DIR
+ delete process.env.PI_CODING_AGENT_DIR
+ secrets.clear()
+ rmSync(home, { force: true, recursive: true })
+})
+
+describe('routing over ipc', () => {
+ test('reads and toggles codex and claude routing', async () => {
+ expect((await readRouting(socketPath)).routed).toEqual({ anthropic: false, openai: false })
+
+ const on = await requestRouting(socketPath, 'anthropic', true)
+ expect(on.routed.anthropic).toBe(true)
+ const settings = await readFile(join(home, 'claude', 'settings.json'), 'utf8')
+ expect(settings).toContain('127.0.0.1')
+
+ const off = await requestRouting(socketPath, 'anthropic', false)
+ expect(off.routed.anthropic).toBe(false)
+ })
+
+ test('routes pi and refuses to touch a models.json it cannot parse', async () => {
+ await mkdir(join(home, 'pi'), { recursive: true })
+ expect((await requestRouting(socketPath, 'pi', true)).pi).toEqual({
+ present: true,
+ routed: true
+ })
+
+ await writeFile(join(home, 'pi', 'models.json'), '{ not json')
+ const failure = await requestRouting(socketPath, 'pi', true).catch(error => error)
+ expect(failure).toBeInstanceOf(ApplicationError)
+ expect((failure as ApplicationError).code).toBe('MANUAL_EDIT_REQUIRED')
+ })
+})
+
+describe('api key accounts over ipc', () => {
+ test('stores the key in the vault and activates the first account', async () => {
+ const account = await requestAddApiKey(socketPath, {
+ key: 'sk-ant-test',
+ label: 'team key',
+ provider: 'anthropic'
+ })
+ expect(account.auth).toBe('apiKey')
+ expect(account.secretReference === null ? null : secrets.get(account.secretReference)).toBe(
+ 'sk-ant-test'
+ )
+
+ const dashboard = await readDashboard(socketPath)
+ expect(dashboard.accounts.map(candidate => candidate.label)).toEqual(['team key'])
+ expect(dashboard.providers.find(state => state.provider === 'anthropic')?.activeAccountId).toBe(
+ account.id
+ )
+ })
+
+ test('rejects an empty name', async () => {
+ const failure = await requestAddApiKey(socketPath, {
+ key: 'sk-test',
+ label: ' ',
+ provider: 'openai'
+ }).catch(error => error)
+ expect((failure as ApplicationError).code).toBe('USAGE')
+ expect(secrets.size).toBe(0)
+ })
+})
diff --git a/src/ipc.ts b/src/ipc.ts
index 1d84d1b..5dbf4bd 100644
--- a/src/ipc.ts
+++ b/src/ipc.ts
@@ -19,7 +19,15 @@ import {
} from './domain.ts'
import { ApplicationError, errorMessage } from './errors.ts'
import type { AccountManager } from './manager.ts'
-import { VERSION } from './version.ts'
+import {
+ type RoutingStatus,
+ RoutingStatusSchema,
+ type RoutingTarget,
+ RoutingTargetSchema,
+ routingStatus,
+ setRouting
+} from './routing.ts'
+import { availableUpdate, VERSION } from './version.ts'
const RpcRequestSchema = z
.object({
@@ -62,6 +70,14 @@ const PolicyParamsSchema = z
const ResetParamsSchema = z.object({ accountId: z.uuid() }).strict()
+const RoutingParamsSchema = z.object({ enable: z.boolean(), target: RoutingTargetSchema }).strict()
+
+const AddApiKeyParamsSchema = z
+ .object({ key: z.string().min(1), label: z.string().min(1), provider: ProviderIdSchema })
+ .strict()
+
+const LatestVersionSchema = z.object({ latest: z.string().nullable() }).strict()
+
const ReplaceCredentialParamsSchema = z
.object({
account: AccountSchema,
@@ -119,6 +135,19 @@ async function dispatch(
return manager.codexResetCredits(ResetParamsSchema.parse(params).accountId)
case 'codex/consumeReset':
return manager.consumeCodexReset(ResetParamsSchema.parse(params).accountId)
+ case 'account/addApiKey': {
+ const account = await manager.addApiKeyAccount(AddApiKeyParamsSchema.parse(params))
+ return { account }
+ }
+ case 'routing/read':
+ return routingStatus()
+ case 'routing/set': {
+ const parsed = RoutingParamsSchema.parse(params)
+ await setRouting(manager.paths, parsed.target, parsed.enable)
+ return routingStatus()
+ }
+ case 'version/latest':
+ return { latest: await availableUpdate() }
default:
throw new ApplicationError('METHOD_NOT_FOUND', `Unknown manager method ${method}`)
}
@@ -395,3 +424,48 @@ export function requestAccountSave(
timeoutMilliseconds: 15_000
}).then(() => undefined)
}
+
+export function requestAddApiKey(
+ socketPath: string,
+ input: { provider: ProviderId; key: string; label: string }
+): Promise {
+ return managerRequest({
+ method: 'account/addApiKey',
+ params: input,
+ schema: z.object({ account: AccountSchema }).transform(result => result.account),
+ socketPath,
+ timeoutMilliseconds: 30_000
+ })
+}
+
+export function readRouting(socketPath: string): Promise {
+ return managerRequest({
+ method: 'routing/read',
+ schema: RoutingStatusSchema,
+ socketPath,
+ timeoutMilliseconds: 15_000
+ })
+}
+
+export function requestRouting(
+ socketPath: string,
+ target: RoutingTarget,
+ enable: boolean
+): Promise {
+ return managerRequest({
+ method: 'routing/set',
+ params: { enable, target },
+ schema: RoutingStatusSchema,
+ socketPath,
+ timeoutMilliseconds: 15_000
+ })
+}
+
+export function readLatestVersion(socketPath: string): Promise {
+ return managerRequest({
+ method: 'version/latest',
+ schema: LatestVersionSchema,
+ socketPath,
+ timeoutMilliseconds: 5_000
+ }).then(result => result.latest)
+}
diff --git a/src/manager.ts b/src/manager.ts
index 3079ce5..1dddd08 100644
--- a/src/manager.ts
+++ b/src/manager.ts
@@ -1,9 +1,16 @@
-import { claudeUpstream, migrateClaudeAccount, probeClaude, removeClaudeProfile } from './claude.ts'
+import {
+ claudeUpstream,
+ migrateClaudeAccount,
+ probeClaude,
+ registerClaudeApiKeyAccount,
+ removeClaudeProfile
+} from './claude.ts'
import {
codexUpstream,
probeCodex,
probeCodexResetCredits,
- redeemCodexResetCredit
+ redeemCodexResetCredit,
+ registerOpenAiApiKeyAccount
} from './codex.ts'
import {
type Account,
@@ -165,6 +172,10 @@ export class AccountManager {
return this.#proxy?.port ?? null
}
+ public get paths(): ApplicationPaths {
+ return this.#paths
+ }
+
private async upstreamInjection(
provider: ProviderId,
forceRefresh: boolean
@@ -318,6 +329,27 @@ export class AccountManager {
})
}
+ public async addApiKeyAccount(input: {
+ provider: ProviderId
+ key: string
+ label: string
+ }): Promise {
+ const label = input.label.trim()
+ if (label.length === 0) {
+ throw new ApplicationError('USAGE', 'The account needs a name')
+ }
+ const register =
+ input.provider === 'openai' ? registerOpenAiApiKeyAccount : registerClaudeApiKeyAccount
+ const account = await register({
+ fetchImplementation: this.#dependencies.fetchImplementation,
+ key: input.key,
+ label,
+ vault: this.#vault
+ })
+ await this.saveAccount({ account, removePrevious: { profilePath: null, secretReference: null } })
+ return account
+ }
+
public setAutomationPolicy(input: {
provider: ProviderId
enabled?: boolean
diff --git a/src/routing.ts b/src/routing.ts
new file mode 100644
index 0000000..650aa9f
--- /dev/null
+++ b/src/routing.ts
@@ -0,0 +1,65 @@
+import { z } from 'zod'
+import {
+ installClaudeConfig,
+ installCodexConfig,
+ installPiConfig,
+ installStatus,
+ piStatus,
+ uninstallClaudeConfig,
+ uninstallCodexConfig,
+ uninstallPiConfig
+} from './config-install.ts'
+import { ProviderIdSchema } from './domain.ts'
+import { ApplicationError } from './errors.ts'
+import type { ApplicationPaths } from './paths.ts'
+
+const ProviderFlagsSchema = z.record(ProviderIdSchema, z.boolean())
+
+export const RoutingTargetSchema = z.enum(['openai', 'anthropic', 'pi'])
+export type RoutingTarget = z.infer
+
+export const RoutingStatusSchema = z
+ .object({
+ clis: ProviderFlagsSchema,
+ codexStale: z.boolean(),
+ pi: z.object({ present: z.boolean(), routed: z.boolean() }).strict(),
+ routed: ProviderFlagsSchema
+ })
+ .strict()
+export type RoutingStatus = z.infer
+
+export async function routingStatus(
+ which: (binary: string) => string | null = Bun.which
+): Promise {
+ const [install, pi] = await Promise.all([installStatus(), piStatus(which)])
+ return {
+ clis: { anthropic: which('claude') !== null, openai: which('codex') !== null },
+ codexStale: install.codexStale,
+ pi,
+ routed: { anthropic: install.claudeRouted, openai: install.codexRouted }
+ }
+}
+
+export async function setRouting(
+ paths: ApplicationPaths,
+ target: RoutingTarget,
+ enable: boolean
+): Promise {
+ switch (target) {
+ case 'openai':
+ await (enable ? installCodexConfig(paths) : uninstallCodexConfig())
+ return
+ case 'anthropic':
+ await (enable ? installClaudeConfig(paths) : uninstallClaudeConfig())
+ return
+ case 'pi': {
+ const result = await (enable ? installPiConfig(paths) : uninstallPiConfig())
+ if (result.manual !== null) {
+ throw new ApplicationError(
+ 'MANUAL_EDIT_REQUIRED',
+ `${result.path} needs a manual edit — run: tokenmaxx ${enable ? 'install' : 'uninstall'} pi`
+ )
+ }
+ }
+ }
+}
diff --git a/src/tui/dashboard.ts b/src/tui/dashboard.ts
index 61209ad..ba61d53 100644
--- a/src/tui/dashboard.ts
+++ b/src/tui/dashboard.ts
@@ -1,5 +1,4 @@
import { Box, createCliRenderer, parseColor, type RGBA, Text } from '@opentui/core'
-import { installPiConfig, type PiStatus, piStatus, uninstallPiConfig } from '../config-install.ts'
import type {
Account,
AnalyticsSnapshot,
@@ -14,15 +13,17 @@ import type {
} from '../domain.ts'
import {
readAnalytics,
+ readRouting,
refreshUsage,
requestAccountSave,
requestConsumeReset,
requestPolicy,
requestResetCredits,
+ requestRouting,
requestSwitch
} from '../ipc.ts'
-import { applicationPaths } from '../paths.ts'
import { readPreferences, writePreferences } from '../preferences.ts'
+import type { RoutingStatus } from '../routing.ts'
import { availableUpdate, installedVersion, VERSION } from '../version.ts'
import { buildScenario } from './fixtures.ts'
import {
@@ -95,7 +96,7 @@ interface Ctx {
themePreference: ThemePreference
themePinnedByEnvironment: boolean
themeFromTerminalActive: boolean
- pi: PiStatus
+ pi: RoutingStatus['pi']
}
function labelWidth(ctx: Ctx): number {
@@ -1172,7 +1173,6 @@ type DashboardAction =
| { kind: 'relogin'; provider: ProviderId }
| { kind: 'login'; provider: ProviderId }
| { kind: 'loginApiKey'; provider: ProviderId }
- | { kind: 'routing'; provider: ProviderId; enable: boolean }
| { kind: 'update'; version: string }
function view(ctx: Ctx, analytics: AnalyticsSnapshot, rows: Row[], state: ViewState) {
@@ -1308,21 +1308,28 @@ function view(ctx: Ctx, analytics: AnalyticsSnapshot, rows: Row[], state: ViewSt
interface FixtureOptions {
name: string
now: number
+ routed: boolean
timewarp: number
}
export async function runTuiDashboard(
socketPath: string,
- options: { routing: Record; fixture?: FixtureOptions; alert?: string }
+ options: { fixture?: FixtureOptions; alert?: string }
): Promise {
const fixture = options.fixture
const live = fixture === undefined
try {
process.stdin.setRawMode?.(true)
} catch {}
- const cliPresent: Record = live
- ? { anthropic: Bun.which('claude') !== null, openai: Bun.which('codex') !== null }
- : { anthropic: true, openai: true }
+ let routing: RoutingStatus =
+ fixture === undefined
+ ? await readRouting(socketPath)
+ : {
+ clis: { anthropic: true, openai: true },
+ codexStale: false,
+ pi: { present: true, routed: true },
+ routed: { anthropic: fixture.routed, openai: fixture.routed }
+ }
const renderer = await createCliRenderer({ exitOnCtrlC: false, targetFps: 30 })
await renderer.waitForThemeMode(400).catch(() => null)
const themeEnvironmentOverride = themeOverride(process.env)
@@ -1346,7 +1353,6 @@ export async function runTuiDashboard(
? await readAnalytics(socketPath)
: buildScenario(fixture.name, simulatedNow)
let rows = orderedRows(analytics.snapshot)
- let pi: PiStatus = live ? await piStatus() : { present: true, routed: true }
const state: ViewState = {
addConfirm: null,
alert: options.alert ?? '',
@@ -1383,11 +1389,11 @@ export async function runTuiDashboard(
try {
next = view(
{
- cliPresent,
+ cliPresent: routing.clis,
columns,
now: live ? Date.now() : simulatedNow,
- pi,
- routing: options.routing,
+ pi: routing.pi,
+ routing: routing.routed,
rows: process.stdout.rows ?? 24,
switchFlagMs: fixture !== undefined && fixture.timewarp > 0 ? 24 * 60_000 : 120_000,
theme: currentTheme(),
@@ -1435,7 +1441,7 @@ export async function runTuiDashboard(
}
analytics = await readAnalytics(socketPath)
rows = orderedRows(analytics.snapshot)
- pi = await piStatus()
+ routing = await readRouting(socketPath)
clampSelection()
})
@@ -1455,7 +1461,7 @@ export async function runTuiDashboard(
}
if (row.accountId === ADD_ROW) {
state.addConfirm = {
- choice: cliPresent[row.provider] ? 'oauth' : 'apiKey',
+ choice: routing.clis[row.provider] ? 'oauth' : 'apiKey',
provider: row.provider
}
paint()
@@ -1572,8 +1578,19 @@ export async function runTuiDashboard(
applyPolicy(provider, { hiddenWindowIds: next }, 'rate-limit view…')
}
- const toggleRouting = (provider: ProviderId) => {
- finish({ enable: !options.routing[provider], kind: 'routing', provider })
+ const toggleTarget = (target: ProviderId | 'pi', routed: boolean) => {
+ if (!live) {
+ routing =
+ target === 'pi'
+ ? { ...routing, pi: { ...routing.pi, routed: !routed } }
+ : { ...routing, routed: { ...routing.routed, [target]: !routed } }
+ paint()
+ return
+ }
+ const name = target === 'pi' ? 'pi' : providerCli[target]
+ void withBusy(`${routed ? 'unrouting' : 'routing'} ${name}…`, async () => {
+ routing = await requestRouting(socketPath, target, !routed)
+ })
}
const adjustSetting = (delta: number) => {
@@ -1582,27 +1599,12 @@ export async function runTuiDashboard(
return
}
if (row.scope === 'harness') {
- if (!pi.present) {
+ if (!routing.pi.present) {
state.note = 'pi is not installed'
paint()
return
}
- if (!live) {
- pi = { ...pi, routed: !pi.routed }
- paint()
- return
- }
- void withBusy(pi.routed ? 'unrouting pi…' : 'routing pi…', async () => {
- if (pi.routed) {
- await uninstallPiConfig()
- } else {
- const result = await installPiConfig(applicationPaths())
- if (result.manual !== null) {
- throw new Error('models.json needs a manual edit — run: tokenmaxx install pi')
- }
- }
- pi = await piStatus()
- })
+ toggleTarget('pi', routing.pi.routed)
return
}
if (row.scope === 'display') {
@@ -1623,7 +1625,7 @@ export async function runTuiDashboard(
}
const policy = currentPolicy(row.provider)
if (row.key === 'routing') {
- toggleRouting(row.provider)
+ toggleTarget(row.provider, routing.routed[row.provider])
return
}
if (row.key === 'auto') {
@@ -1810,7 +1812,7 @@ export async function runTuiDashboard(
const row = rows[state.selected]
if (row !== undefined && row.accountId === ADD_ROW) {
state.addConfirm = {
- choice: cliPresent[row.provider] ? 'oauth' : 'apiKey',
+ choice: routing.clis[row.provider] ? 'oauth' : 'apiKey',
provider: row.provider
}
paint()
diff --git a/src/version.ts b/src/version.ts
index b069241..142f901 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -4,6 +4,9 @@ import packageJson from '../package.json'
export const VERSION: string = packageJson.version
+// `bun build --compile` mounts the bundle under /$bunfs/, which is how the app-bundled binary runs.
+export const compiledBinary = Bun.main.startsWith('/$bunfs/')
+
// The version on disk, which an update may have moved past this running process.
export async function installedVersion(): Promise {
try {