Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
26ff5fe
Port 0.56.5 completed empty Codex fragments
Finesssee Sep 6, 2026
4271c99
Port 0.56.5 Kilo auth recovery
Finesssee Sep 6, 2026
60ddc97
Port 0.56.5 z.ai compact token totals
Finesssee Sep 6, 2026
8f624a2
Port 0.56.5 Antigravity turn timestamp correlation
Finesssee Sep 7, 2026
f3fd1e0
Port 0.56.5 Codex extra-credit reconciliation
Finesssee Sep 7, 2026
9950c25
Port 0.56.5 retained Codex scan range
Finesssee Sep 7, 2026
76fb48b
Port 0.56.5 abandoned spend refresh cleanup
Finesssee Sep 7, 2026
606cb26
Port 0.56.5 z.ai reset plausibility
Finesssee Sep 7, 2026
a05cfed
Refactor z.ai reset plausibility
Finesssee Sep 7, 2026
cde5217
Extract z.ai provider tests
Finesssee Sep 7, 2026
814eaab
Port 0.56.5 Claude identity-less account actions
Finesssee Sep 7, 2026
974f07f
Fix Claude account action freshness proof
Finesssee Sep 7, 2026
f84a7af
Refactor 0.56.5 Codex empty-fragment helper
Finesssee Sep 7, 2026
cc10785
Fix Claude account action test fixtures
Finesssee Sep 7, 2026
9e7fee9
Fix 0.56.5 native Rust compile regressions
Finesssee Sep 7, 2026
e2ed904
Finish 0.56.5 native Rust compile fixes
Finesssee Sep 7, 2026
b156898
Finish 0.56.5 native Tauri compile fixes
Finesssee Sep 7, 2026
c5f682d
Fix 0.56.5 native Rust test regressions
Finesssee Sep 7, 2026
145c3c6
Preserve terminal Codex catch-up pause across range changes
Finesssee Sep 7, 2026
5471ed9
Make 0.56.5 Rust port Clippy-clean
Finesssee Sep 7, 2026
98c694e
ci: rerun hosted checks for 0.56.5
Finesssee Sep 7, 2026
65987ed
refactor: unify usage spend refresh state
Finesssee Sep 8, 2026
8698980
style: apply workspace rustfmt
Finesssee Sep 8, 2026
6f5085d
Merge repaired 0.56.4 base
Finesssee Sep 8, 2026
9ed7182
fix: repair merged provider fetch contract formatting
Finesssee Sep 8, 2026
8188496
Merge formatted repaired base for #439
Finesssee Sep 8, 2026
b8b0917
Merge repaired 0.56.4 base
Finesssee Sep 8, 2026
06dcec3
test: complete Claude fetch fixtures
Finesssee Sep 8, 2026
36953d0
Merge final repaired base for #439
Finesssee Sep 8, 2026
a213eab
Merge final format fix for #439
Finesssee Sep 8, 2026
4a781d3
Merge stabilized 0.56.4 base
Finesssee Sep 8, 2026
9bc7ece
Merge latest stacked base for #439
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
10 changes: 10 additions & 0 deletions apps/desktop-tauri/src-tauri/src/commands/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ pub struct CostSnapshotBridge {
#[serde(default)]
pub balance: Option<f64>,
#[serde(default)]
pub balance_updated_at: Option<String>,
#[serde(default)]
pub account_id: Option<String>,
#[serde(default)]
pub formatted_balance: Option<String>,
#[serde(default)]
pub daily: Vec<CostDailyPointBridge>,
Expand Down Expand Up @@ -195,6 +199,8 @@ pub struct ProviderUsageSnapshot {
pub account_email: Option<String>,
#[serde(default = "default_source_label")]
pub source_label: String,
#[serde(default)]
pub has_successful_claude_cli_quota: bool,
/// Defaults to launch time when absent so the card renders as fresh.
#[serde(default)]
pub updated_at: String,
Expand Down Expand Up @@ -378,6 +384,8 @@ impl ProviderUsageSnapshot {
formatted_used: c.format_used(),
formatted_limit: c.format_limit(),
balance: c.balance,
balance_updated_at: c.balance_updated_at.map(|dt| dt.to_rfc3339()),
account_id: c.account_id.clone(),
formatted_balance: c.format_balance(),
daily: c
.daily
Expand All @@ -392,6 +400,7 @@ impl ProviderUsageSnapshot {
plan_name: usage.login_method.clone(),
account_email: usage.account_email.clone(),
source_label: result.source_label.clone(),
has_successful_claude_cli_quota: result.has_successful_claude_cli_quota,
updated_at: usage.updated_at.to_rfc3339(),
error: None,
error_state: codexbar::core::ProviderStateKind::Ready,
Expand Down Expand Up @@ -438,6 +447,7 @@ impl ProviderUsageSnapshot {
plan_name: None,
account_email: None,
source_label: String::new(),
has_successful_claude_cli_quota: false,
updated_at: chrono::Utc::now().to_rfc3339(),
error: Some(error),
error_state: state_kind,
Expand Down
66 changes: 52 additions & 14 deletions apps/desktop-tauri/src-tauri/src/commands/providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,13 @@ async fn refresh_provider(

/// F6 (upstream 0.48.0 UsageStore+CodexResetBackfill): backfill missing
/// `resets_at` / `reset_description` on fresh Codex windows from the cached
/// lane data when the cached reset is still future. Fresh `used_percent` is
/// untouched; only the reset timestamp/description are backfilled.
/// lane data when the cached reset is still future. z.ai five-hour cached
/// resets use the same plausibility bound as the provider parser, so an
/// impossible rejected reset cannot be restored from the cache. Fresh
/// `used_percent` is untouched; only reset metadata is backfilled.
///
/// This is Codex-scoped by design (upstream: "Provider-specific by design"):
/// other providers do not carry bounded resume state.
/// This remains provider-scoped by design (upstream: "Provider-specific by
/// design"): only Codex and z.ai carry the relevant bounded reset semantics.
///
/// Applies to the bridge snapshot before publishing so every surface (tray,
/// CLI, frontend) sees the backfilled reset instead of a missing one.
Expand All @@ -460,26 +462,31 @@ pub(super) fn codex_reset_backfill(
cached: Option<&ProviderUsageSnapshot>,
) {
let Some(cached) = cached else { return };
if snapshot.provider_id != "codex" {
if !matches!(snapshot.provider_id.as_str(), "codex" | "zai") {
return;
}

// Backfill each slot from the corresponding cached slot.
backfill_slot_window(&mut snapshot.primary, &cached.primary);
backfill_slot_window(
&snapshot.provider_id,
&mut snapshot.primary,
&cached.primary,
);
if let (Some(fresh), Some(cached_sec)) = (&mut snapshot.secondary, &cached.secondary) {
backfill_slot_window(fresh, cached_sec);
backfill_slot_window(&snapshot.provider_id, fresh, cached_sec);
}
// Tertiary (monthly/other): the Codex bridge doesn't normally populate this,
// but the slot exists for forward-compat. Backfill when available.
if let (Some(fresh), Some(cached_ter)) = (&mut snapshot.tertiary, &cached.tertiary) {
backfill_slot_window(fresh, cached_ter);
backfill_slot_window(&snapshot.provider_id, fresh, cached_ter);
}
}

/// Backfill `resets_at` and `reset_description` on a fresh window from the
/// cached window whose reset is still in the future. `used_percent` is never
/// overwritten (upstream: "fresh used_percent untouched").
fn backfill_slot_window(
provider_id: &str,
fresh: &mut bridge::RateWindowSnapshot,
cached: &bridge::RateWindowSnapshot,
) {
Expand All @@ -491,11 +498,20 @@ fn backfill_slot_window(
};
// Only backfill when the cached reset is still future — a stale reset is
// worse than a missing one.
if let Ok(cached_dt) = chrono::DateTime::parse_from_rfc3339(cached_reset) {
if cached_dt <= chrono::Utc::now() {
return;
}
} else {
let Ok(cached_dt) = chrono::DateTime::parse_from_rfc3339(cached_reset) else {
return;
};
let now = chrono::Utc::now();
if cached_dt <= now {
return;
}
// A missing z.ai five-hour reset can mean the provider rejected an
// impossible future timestamp. Do not let equally impossible cached
// evidence undo that rejection, but preserve a plausible cached reset.
if provider_id == "zai"
&& fresh.window_minutes == Some(300)
&& cached_dt > now + chrono::Duration::minutes(5 * 60 + 1)
{
return;
}
fresh.resets_at = Some(cached_reset.clone());
Expand All @@ -521,14 +537,17 @@ pub(super) fn preserve_last_good_transient_failure(
return snapshot;
}

let Some(previous) = guard
let Some(mut previous) = guard
.provider_cache
.iter()
.find(|cached| cached.provider_id == id.cli_name() && cached.error.is_none())
.cloned()
else {
return snapshot;
};
// Preserved quota remains useful for display, but the failed current
// attempt cannot prove that Claude CLI is available for account actions.
previous.has_successful_claude_cli_quota = false;

let count = guard
.transient_provider_failure_counts
Expand Down Expand Up @@ -1133,6 +1152,7 @@ mod reset_backfill_tests {
plan_name: None,
account_email: None,
source_label: String::new(),
has_successful_claude_cli_quota: false,
updated_at: "2026-01-01T00:00:00Z".into(),
error: None,
error_state: codexbar::core::ProviderStateKind::Ready,
Expand Down Expand Up @@ -1192,6 +1212,24 @@ mod reset_backfill_tests {
assert!(fresh.primary.resets_at.is_none(), "non-codex skip");
}

#[test]
fn zai_five_hour_backfill_rejects_impossible_cached_reset() {
for (offset, should_backfill) in [
(chrono::Duration::hours(1), true),
(chrono::Duration::hours(10), false),
] {
let future = (chrono::Utc::now() + offset).to_rfc3339();
let mut cached = codex_snapshot(win(50.0, Some(&future)));
cached.provider_id = "zai".into();
let mut fresh = codex_snapshot(win(30.0, None));
fresh.provider_id = "zai".into();
fresh.primary.reset_description = Some("5-hour".into());
codex_reset_backfill(&mut fresh, Some(&cached));
assert_eq!(fresh.primary.resets_at.is_some(), should_backfill);
assert!((fresh.primary.used_percent - 30.0).abs() < f64::EPSILON);
}
}

#[test]
fn f6_skips_when_no_cached_snapshot() {
let mut fresh = codex_snapshot(win(30.0, None));
Expand Down
12 changes: 12 additions & 0 deletions apps/desktop-tauri/src-tauri/src/commands/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,7 @@ fn provider_cache_upsert_replaces_existing_provider() {
cost: None,
wayfinder_usage: None,
source_label: "CLI".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};
let mut first =
Expand All @@ -963,6 +964,7 @@ fn provider_cache_prunes_disabled_providers() {
cost: None,
wayfinder_usage: None,
source_label: "CLI".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};
let codex =
Expand Down Expand Up @@ -994,6 +996,7 @@ fn hiding_codex_spark_rows_preserves_other_extra_usage() {
cost: None,
wayfinder_usage: None,
source_label: "CLI".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};
let mut snapshot =
Expand Down Expand Up @@ -1025,6 +1028,7 @@ fn claude_transient_auth_failure_preserves_first_last_good_snapshot() {
cost: None,
wayfinder_usage: None,
source_label: "OAuth".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};
let good =
Expand Down Expand Up @@ -1056,6 +1060,7 @@ fn claude_repeated_auth_failure_surfaces_error() {
cost: None,
wayfinder_usage: None,
source_label: "OAuth".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};
let good =
Expand Down Expand Up @@ -1092,6 +1097,7 @@ fn claude_cloudflare_challenge_retains_prior_usage_while_surfaceing_guidance() {
cost: None,
wayfinder_usage: None,
source_label: "OAuth".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};
let good =
Expand Down Expand Up @@ -1139,6 +1145,7 @@ fn claude_cloudflare_challenge_keeps_prior_usage_when_guidance_surfaces() {
cost: None,
wayfinder_usage: None,
source_label: "Web".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};
let mut good =
Expand Down Expand Up @@ -1182,6 +1189,7 @@ fn claude_cli_parse_failure_keeps_last_good_every_time() {
cost: None,
wayfinder_usage: None,
source_label: "CLI".to_string(),
has_successful_claude_cli_quota: true,
pace_authoritative: true,
};
let good =
Expand All @@ -1205,6 +1213,7 @@ fn claude_cli_parse_failure_keeps_last_good_every_time() {

assert_eq!(first.error, None);
assert_eq!(first.primary.used_percent, 17.0);
assert!(!first.has_successful_claude_cli_quota);
// Parse failures keep last-good on every refresh (upstream #2247), unlike one-shot auth.
assert_eq!(second.error, None);
assert_eq!(second.primary.used_percent, 17.0);
Expand All @@ -1218,6 +1227,7 @@ fn claude_hard_credentials_missing_does_not_preserve_stale() {
cost: None,
wayfinder_usage: None,
source_label: "OAuth".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};
let good =
Expand Down Expand Up @@ -1379,6 +1389,7 @@ fn japanese_provider_snapshot_localizes_weekly_label() {
cost: None,
wayfinder_usage: None,
source_label: "OAuth".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};

Expand Down Expand Up @@ -1409,6 +1420,7 @@ fn japanese_provider_snapshot_localizes_pace_reserve_description() {
cost: None,
wayfinder_usage: None,
source_label: "OAuth".to_string(),
has_successful_claude_cli_quota: false,
pace_authoritative: true,
};

Expand Down
Loading