Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9ef4ab7
Port 0.56.6 Kiro unavailable plan summaries
Finesssee Sep 7, 2026
9d43a61
Fix 0.56.6 Kiro unavailable summary semantics
Finesssee Sep 7, 2026
464d7e5
Cover 0.56.6 Hooks label parity
Finesssee Sep 7, 2026
1608620
Port 0.56.6 Kimi membership recovery
Finesssee Sep 7, 2026
50e1d13
Port 0.56.6 exhausted automatic quota selection
Finesssee Sep 7, 2026
4f3c496
Fix 0.56.6 exhausted switcher policy
Finesssee Sep 7, 2026
b7fa271
Port 0.56.6 lazy Codex history reads
Finesssee Sep 7, 2026
bbb4b85
Port 0.56.6 GPT-6 Astra pricing
Finesssee Sep 7, 2026
cd7586c
Port 0.56.6 Codex subscription dates
Finesssee Sep 7, 2026
1b6ee8b
Fix 0.56.6 native Rust compile regressions
Finesssee Sep 7, 2026
3939ff6
Finish 0.56.6 native Rust compile fixes
Finesssee Sep 7, 2026
15996e8
Fix 0.56.6 native Rust test regressions
Finesssee Sep 7, 2026
3f4778b
Make 0.56.6 Rust port Clippy-clean
Finesssee Sep 7, 2026
7082c47
refactor: move metric policy to providers
Finesssee Sep 8, 2026
64d34cb
style: apply workspace rustfmt
Finesssee Sep 8, 2026
973b196
Merge repaired 0.56.5 base
Finesssee Sep 8, 2026
b72e81c
Merge formatted repaired base for #440
Finesssee Sep 8, 2026
4639328
Merge repaired 0.56.5 base
Finesssee Sep 8, 2026
6d9d48a
Merge repaired child base for #440
Finesssee Sep 8, 2026
28eb93d
Merge final repaired base for #440
Finesssee Sep 8, 2026
3aef903
Merge final format fix for #440
Finesssee Sep 8, 2026
549dda1
Merge stabilized child base for #440
Finesssee Sep 8, 2026
df27cde
Merge latest stacked base for #440
Finesssee Sep 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions apps/desktop-tauri/src-tauri/src/commands/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,15 @@ pub struct SessionEquivalentForecastSnapshot {
pub weekly_used_percent: f64,
}

/// Subscription dates from an authenticated OpenAI dashboard/API response.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscriptionMetadataSnapshot {
pub starts_at: Option<String>,
pub expires_at: Option<String>,
pub renews_at: Option<String>,
}

/// A frontend-friendly snapshot of one provider's usage data.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -197,6 +206,8 @@ pub struct ProviderUsageSnapshot {
pub plan_name: Option<String>,
#[serde(default)]
pub account_email: Option<String>,
#[serde(default)]
pub subscription: Option<SubscriptionMetadataSnapshot>,
#[serde(default = "default_source_label")]
pub source_label: String,
#[serde(default)]
Expand Down Expand Up @@ -399,6 +410,13 @@ impl ProviderUsageSnapshot {
}),
plan_name: usage.login_method.clone(),
account_email: usage.account_email.clone(),
subscription: usage.subscription.as_ref().map(|subscription| {
SubscriptionMetadataSnapshot {
starts_at: subscription.starts_at.map(|date| date.to_rfc3339()),
expires_at: subscription.expires_at.map(|date| date.to_rfc3339()),
renews_at: subscription.renews_at.map(|date| date.to_rfc3339()),
}
}),
source_label: result.source_label.clone(),
has_successful_claude_cli_quota: result.has_successful_claude_cli_quota,
updated_at: usage.updated_at.to_rfc3339(),
Expand Down Expand Up @@ -446,6 +464,7 @@ impl ProviderUsageSnapshot {
cost: None,
plan_name: None,
account_email: None,
subscription: None,
source_label: String::new(),
has_successful_claude_cli_quota: false,
updated_at: chrono::Utc::now().to_rfc3339(),
Expand Down
1 change: 1 addition & 0 deletions apps/desktop-tauri/src-tauri/src/commands/providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,7 @@ mod reset_backfill_tests {
cost: None,
plan_name: None,
account_email: None,
subscription: None,
source_label: String::new(),
has_successful_claude_cli_quota: false,
updated_at: "2026-01-01T00:00:00Z".into(),
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop-tauri/src-tauri/src/powertoys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ mod tests {
cost: None,
plan_name: Some("Team".to_string()),
account_email: Some("dev@example.com".to_string()),
subscription: None,
source_label: "web".to_string(),
has_successful_claude_cli_quota: false,
updated_at: "2026-07-09T00:00:00Z".to_string(),
Expand Down Expand Up @@ -245,6 +246,7 @@ mod tests {
cost: None,
plan_name: None,
account_email: None,
subscription: None,
source_label: "web".to_string(),
has_successful_claude_cli_quota: false,
updated_at: "2026-07-09T00:00:00Z".to_string(),
Expand Down
85 changes: 82 additions & 3 deletions apps/desktop-tauri/src-tauri/src/tray_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,14 +674,22 @@ fn selected_tray_percents(
let (selected, companion) =
crate::usage_metric::selected_usage_icon_windows(snapshot, settings);
(
display_metric_percent(selected.used_percent, settings.show_as_used),
display_metric_percent(&selected, settings.show_as_used),
companion
.as_ref()
.map(|window| display_metric_percent(window.used_percent, settings.show_as_used)),
.map(|window| display_metric_percent(window, settings.show_as_used)),
)
}

fn display_metric_percent(used_percent: f64, show_as_used: bool) -> f64 {
fn display_metric_percent(window: &crate::commands::RateWindowSnapshot, show_as_used: bool) -> f64 {
if window.is_informational {
return 0.0;
}
if window.is_exhausted || window.used_percent >= 100.0 {
return if show_as_used { 100.0 } else { 0.0 };
}

let used_percent = window.used_percent;
let used = used_percent.clamp(0.0, 100.0);
if show_as_used { used } else { 100.0 - used }
}
Expand Down Expand Up @@ -1085,6 +1093,7 @@ mod tests {
}),
plan_name: None,
account_email: None,
subscription: None,
source_label: String::new(),
has_successful_claude_cli_quota: false,
updated_at: "2025-01-01T00:00:00Z".into(),
Expand Down Expand Up @@ -1380,6 +1389,76 @@ mod tests {
assert_eq!(secondary, Some(80.0));
}

#[test]
fn exhausted_automatic_window_never_renders_as_remaining_progress() {
let mut settings = Settings {
show_as_used: false,
..Settings::default()
};
let mut snapshot = fake_snapshot_with(
"opencodego",
"OpenCode Go",
20.0,
Some(60.0),
Some(40.0),
None,
);
snapshot
.tertiary
.as_mut()
.expect("monthly quota")
.is_exhausted = true;

let (remaining, _) = selected_tray_percents(&snapshot, &settings);
assert_eq!(remaining, 0.0);

settings.show_as_used = true;
let (used, _) = selected_tray_percents(&snapshot, &settings);
assert_eq!(used, 100.0);
}

#[test]
fn full_automatic_window_without_exhausted_flag_has_zero_remaining_progress() {
let mut settings = Settings {
show_as_used: false,
..Settings::default()
};
let mut snapshot = fake_snapshot_with(
"opencodego",
"OpenCode Go",
20.0,
Some(60.0),
Some(100.0),
None,
);
snapshot
.tertiary
.as_mut()
.expect("monthly quota")
.is_exhausted = false;

let (remaining, _) = selected_tray_percents(&snapshot, &settings);
assert_eq!(remaining, 0.0);

settings.show_as_used = true;
let (used, _) = selected_tray_percents(&snapshot, &settings);
assert_eq!(used, 100.0);
}

#[test]
fn missing_automatic_window_does_not_look_like_available_remaining_progress() {
let settings = Settings {
show_as_used: false,
..Settings::default()
};
let mut snapshot = fake_snapshot_with("opencodego", "OpenCode Go", 0.0, None, None, None);
snapshot.primary.is_informational = true;

let (remaining, _) = selected_tray_percents(&snapshot, &settings);

assert_eq!(remaining, 0.0);
}

#[test]
fn selected_tray_percent_falls_back_when_extra_usage_missing() {
let mut settings = Settings::default();
Expand Down
109 changes: 95 additions & 14 deletions apps/desktop-tauri/src-tauri/src/usage_metric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,29 @@ fn automatic_window(
}
}

highest_window(
std::iter::once(&snapshot.primary)
.chain(snapshot.secondary.iter())
.chain(snapshot.model_specific.iter())
.chain(snapshot.tertiary.iter())
.chain(
snapshot
.extra_rate_windows
.iter()
.map(|extra| &extra.window),
)
.filter(|window| !window.is_informational),
)
.cloned()
let windows = std::iter::once(&snapshot.primary)
.chain(snapshot.secondary.iter())
.chain(snapshot.model_specific.iter())
.chain(snapshot.tertiary.iter())
.chain(
snapshot
.extra_rate_windows
.iter()
.map(|extra| &extra.window),
)
.filter(|window| !window.is_informational);
let prioritize_exhausted = provider
.map(|id| {
codexbar::core::instantiate_provider(id).automatic_metric_prioritizes_exhausted_window()
})
.unwrap_or(true);
let selected = if prioritize_exhausted {
highest_automatic_window(windows)
} else {
highest_window(windows)
};

selected.cloned()
}

fn average_window(snapshot: &ProviderUsageSnapshot) -> Option<RateWindowSnapshot> {
Expand Down Expand Up @@ -187,6 +196,24 @@ fn highest_window<'a>(
})
}

fn highest_automatic_window<'a>(
windows: impl Iterator<Item = &'a RateWindowSnapshot>,
) -> Option<&'a RateWindowSnapshot> {
windows.max_by(|a, b| {
automatic_window_is_exhausted(a)
.cmp(&automatic_window_is_exhausted(b))
.then_with(|| {
a.used_percent
.partial_cmp(&b.used_percent)
.unwrap_or(Ordering::Equal)
})
})
}

fn automatic_window_is_exhausted(window: &RateWindowSnapshot) -> bool {
window.is_exhausted || window.used_percent >= 100.0
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -210,6 +237,7 @@ mod tests {
cost: None,
plan_name: None,
account_email: None,
subscription: None,
source_label: "test".to_string(),
has_successful_claude_cli_quota: false,
updated_at: "2026-08-16T00:00:00Z".to_string(),
Expand Down Expand Up @@ -260,6 +288,59 @@ mod tests {
);
}

#[test]
fn opencodego_automatic_prefers_explicitly_exhausted_window_over_higher_percentage() {
let mut snapshot = snapshot();
snapshot.provider_id = "opencodego".to_string();
snapshot.primary.is_exhausted = true;

let selected = selected_usage_window(&snapshot, &Settings::default());

assert_eq!(selected.used_percent, 20.0);
assert!(selected.is_exhausted);
}

#[test]
fn claude_and_codex_automatic_keep_highest_used_window() {
for provider_id in ["claude", "codex"] {
let mut snapshot = snapshot();
snapshot.provider_id = provider_id.to_string();
snapshot.primary.is_exhausted = true;

let selected = selected_usage_window(&snapshot, &Settings::default());

assert_eq!(
selected.used_percent, 60.0,
"{provider_id} should keep highest-used automatic selection"
);
assert!(!selected.is_exhausted);
}
}

#[test]
fn automatic_treats_a_full_window_as_exhausted_even_without_the_flag() {
let mut snapshot = snapshot();
let mut full = window(100.0);
full.is_exhausted = false;
snapshot.tertiary = Some(full);

let selected = selected_usage_window(&snapshot, &Settings::default());

assert_eq!(selected.used_percent, 100.0);
assert!(!selected.is_exhausted);
}

#[test]
fn non_automatic_highest_window_keeps_percentage_order() {
let healthy = window(80.0);
let mut exhausted = window(20.0);
exhausted.is_exhausted = true;

let selected = highest_window([&healthy, &exhausted].into_iter()).expect("window");

assert_eq!(selected.used_percent, 80.0);
}

#[test]
fn single_meaningful_quota_omits_the_companion_icon_lane() {
let mut snapshot = snapshot();
Expand Down
18 changes: 18 additions & 0 deletions apps/desktop-tauri/src/surfaces/settings/tabs/AdvancedTab.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,22 @@ describe("AdvancedTab", () => {
).toBeGreaterThan(0);
});
});

it("keeps the Windows Hooks settings surface to one master label and toggle", () => {
render(<AdvancedTab settings={settings} set={vi.fn()} saving={false} />);

const hooksSection = screen
.getByRole("heading", { name: "HooksTitle" })
.closest("section");

expect(hooksSection).not.toBeNull();
expect(hooksSection?.querySelectorAll(".settings-field__label")).toHaveLength(1);
expect(hooksSection?.querySelectorAll('input[type="checkbox"]')).toHaveLength(1);
expect(
hooksSection?.querySelectorAll(
'input[type="text"], input[type="number"], textarea',
),
).toHaveLength(0);
expect(screen.getAllByText("HooksEnableLabel")).toHaveLength(1);
});
});
8 changes: 8 additions & 0 deletions apps/desktop-tauri/src/types/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,12 @@ export interface SessionEquivalentForecastSnapshot {
weeklyUsedPercent: number;
}

export interface SubscriptionMetadataSnapshot {
startsAt: string | null;
expiresAt: string | null;
renewsAt: string | null;
}

/** Backend-classified provider availability state (camelCase serde on the bridge). */
export type ProviderStateKind =
| "ready"
Expand Down Expand Up @@ -606,6 +612,7 @@ export interface ProviderUsageSnapshot {
cost: CostSnapshotBridge | null;
planName: string | null;
accountEmail: string | null;
subscription?: SubscriptionMetadataSnapshot | null;
sourceLabel: string;
/** Backend proof of a live successful Claude CLI quota fetch; only true is proof. */
hasSuccessfulClaudeCliQuota?: boolean;
Expand Down Expand Up @@ -948,6 +955,7 @@ export interface CodexAccountUsageSnapshot {
credits: CodexCreditsBalance | null;
/** Persisted account-scoped extra-usage cost, when available. */
cost?: CostSnapshotBridge | null;
subscription?: SubscriptionMetadataSnapshot | null;
updatedAt: string;
}

Expand Down
Loading