Skip to content

Commit c333fdf

Browse files
committed
v1.4.5
1 parent 9771e11 commit c333fdf

3 files changed

Lines changed: 85 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "claude-code-usage-monitor"
3-
version = "1.4.4"
3+
version = "1.4.5"
44
edition = "2021"
55
license = "MIT"
66
description = "Claude Code Usage Monitor"

src/poller.rs

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const CREATE_NO_WINDOW: u32 = 0x08000000;
1616

1717
const MODEL_FALLBACK_CHAIN: &[&str] = &["claude-3-haiku-20240307", "claude-haiku-4-5-20251001"];
1818

19-
#[derive(Debug)]
19+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2020
pub enum PollError {
2121
AuthRequired,
2222
NoCredentials,
@@ -73,22 +73,44 @@ struct CodexRateLimitWindow {
7373
}
7474

7575
pub fn poll(show_claude_code: bool, show_codex: bool) -> Result<AppUsageData, PollError> {
76+
poll_with(show_claude_code, show_codex, poll_claude_code, poll_codex)
77+
}
78+
79+
fn poll_with(
80+
show_claude_code: bool,
81+
show_codex: bool,
82+
mut poll_claude_code: impl FnMut() -> Result<UsageData, PollError>,
83+
mut poll_codex: impl FnMut() -> Result<UsageData, PollError>,
84+
) -> Result<AppUsageData, PollError> {
7685
let mut data = AppUsageData::default();
86+
let mut first_error = None;
7787

7888
if show_claude_code {
79-
data.claude_code = Some(poll_claude_code()?);
89+
match poll_claude_code() {
90+
Ok(claude_code) => data.claude_code = Some(claude_code),
91+
Err(error) => {
92+
if show_codex {
93+
diagnose::log(format!("Claude Code usage poll failed: {error:?}"));
94+
}
95+
first_error.get_or_insert(error);
96+
}
97+
}
8098
}
8199

82100
if show_codex {
83101
match poll_codex() {
84102
Ok(codex) => data.codex = Some(codex),
85-
Err(error) if !show_claude_code => return Err(error),
86-
Err(error) => diagnose::log(format!("Codex usage poll failed: {error:?}")),
103+
Err(error) => {
104+
if show_claude_code {
105+
diagnose::log(format!("Codex usage poll failed: {error:?}"));
106+
}
107+
first_error.get_or_insert(error);
108+
}
87109
}
88110
}
89111

90112
if data.claude_code.is_none() && data.codex.is_none() {
91-
Err(PollError::RequestFailed)
113+
Err(first_error.unwrap_or(PollError::RequestFailed))
92114
} else {
93115
Ok(data)
94116
}
@@ -1097,3 +1119,59 @@ pub fn app_is_past_reset(data: &AppUsageData) -> bool {
10971119
data.claude_code.as_ref().is_some_and(is_past_reset)
10981120
|| data.codex.as_ref().is_some_and(is_past_reset)
10991121
}
1122+
1123+
#[cfg(test)]
1124+
mod tests {
1125+
use super::*;
1126+
1127+
fn usage_with_session_percent(percentage: f64) -> UsageData {
1128+
UsageData {
1129+
session: UsageSection {
1130+
percentage,
1131+
resets_at: None,
1132+
},
1133+
weekly: UsageSection::default(),
1134+
}
1135+
}
1136+
1137+
#[test]
1138+
fn claude_failure_does_not_block_codex_when_both_are_enabled() {
1139+
let data = poll_with(
1140+
true,
1141+
true,
1142+
|| Err(PollError::AuthRequired),
1143+
|| Ok(usage_with_session_percent(42.0)),
1144+
)
1145+
.expect("codex data should keep the poll successful");
1146+
1147+
assert!(data.claude_code.is_none());
1148+
assert_eq!(data.codex.unwrap().session.percentage, 42.0);
1149+
}
1150+
1151+
#[test]
1152+
fn codex_failure_does_not_block_claude_when_both_are_enabled() {
1153+
let data = poll_with(
1154+
true,
1155+
true,
1156+
|| Ok(usage_with_session_percent(64.0)),
1157+
|| Err(PollError::RequestFailed),
1158+
)
1159+
.expect("claude data should keep the poll successful");
1160+
1161+
assert_eq!(data.claude_code.unwrap().session.percentage, 64.0);
1162+
assert!(data.codex.is_none());
1163+
}
1164+
1165+
#[test]
1166+
fn returns_first_error_when_no_enabled_provider_succeeds() {
1167+
let error = poll_with(
1168+
true,
1169+
true,
1170+
|| Err(PollError::AuthRequired),
1171+
|| Err(PollError::RequestFailed),
1172+
)
1173+
.expect_err("all-provider failure should return an error");
1174+
1175+
assert_eq!(error, PollError::AuthRequired);
1176+
}
1177+
}

0 commit comments

Comments
 (0)