mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Propagate rate limit reached type (#18227)
## Summary First PR in the split from #17956. - adds the core/app-server `RateLimitReachedType` shape - maps backend `rate_limit_reached_type` into Codex rate-limit snapshots - carries the field through app-server notifications/responses and generated schemas - updates existing constructors/tests for the new optional field ## Validation - `cargo test -p codex-backend-client` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server rate_limits` - `cargo test -p codex-tui workspace_` - `cargo test -p codex-tui status_` - `just fmt` - `just fix -p codex-backend-client` - `just fix -p codex-app-server-protocol` - `just fix -p codex-app-server` - `just fix -p codex-tui`
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use crate::types::CodeTaskDetailsResponse;
|
||||
use crate::types::ConfigFileResponse;
|
||||
use crate::types::PaginatedListTaskListItem;
|
||||
use crate::types::RateLimitReachedKind as BackendRateLimitReachedKind;
|
||||
use crate::types::RateLimitStatusPayload;
|
||||
use crate::types::TurnAttemptsSiblingTurnsResponse;
|
||||
use anyhow::Result;
|
||||
@@ -9,6 +10,7 @@ use codex_login::CodexAuth;
|
||||
use codex_login::default_client::get_codex_user_agent;
|
||||
use codex_protocol::account::PlanType as AccountPlanType;
|
||||
use codex_protocol::protocol::CreditsSnapshot;
|
||||
use codex_protocol::protocol::RateLimitReachedType;
|
||||
use codex_protocol::protocol::RateLimitSnapshot;
|
||||
use codex_protocol::protocol::RateLimitWindow;
|
||||
use reqwest::StatusCode;
|
||||
@@ -412,12 +414,17 @@ impl Client {
|
||||
payload: RateLimitStatusPayload,
|
||||
) -> Vec<RateLimitSnapshot> {
|
||||
let plan_type = Some(Self::map_plan_type(payload.plan_type));
|
||||
let rate_limit_reached_type = payload
|
||||
.rate_limit_reached_type
|
||||
.flatten()
|
||||
.and_then(|details| Self::map_rate_limit_reached_type(details.kind));
|
||||
let mut snapshots = vec![Self::make_rate_limit_snapshot(
|
||||
Some("codex".to_string()),
|
||||
/*limit_name*/ None,
|
||||
payload.rate_limit.flatten().map(|details| *details),
|
||||
payload.credits.flatten().map(|details| *details),
|
||||
plan_type,
|
||||
rate_limit_reached_type,
|
||||
)];
|
||||
if let Some(additional) = payload.additional_rate_limits.flatten() {
|
||||
snapshots.extend(additional.into_iter().map(|details| {
|
||||
@@ -427,6 +434,7 @@ impl Client {
|
||||
details.rate_limit.flatten().map(|rate_limit| *rate_limit),
|
||||
/*credits*/ None,
|
||||
plan_type,
|
||||
/*rate_limit_reached_type*/ None,
|
||||
)
|
||||
}));
|
||||
}
|
||||
@@ -439,6 +447,7 @@ impl Client {
|
||||
rate_limit: Option<crate::types::RateLimitStatusDetails>,
|
||||
credits: Option<crate::types::CreditStatusDetails>,
|
||||
plan_type: Option<AccountPlanType>,
|
||||
rate_limit_reached_type: Option<RateLimitReachedType>,
|
||||
) -> RateLimitSnapshot {
|
||||
let (primary, secondary) = match rate_limit {
|
||||
Some(details) => (
|
||||
@@ -454,6 +463,30 @@ impl Client {
|
||||
secondary,
|
||||
credits: Self::map_credits(credits),
|
||||
plan_type,
|
||||
rate_limit_reached_type,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_rate_limit_reached_type(
|
||||
kind: BackendRateLimitReachedKind,
|
||||
) -> Option<RateLimitReachedType> {
|
||||
match kind {
|
||||
BackendRateLimitReachedKind::RateLimitReached => {
|
||||
Some(RateLimitReachedType::RateLimitReached)
|
||||
}
|
||||
BackendRateLimitReachedKind::WorkspaceOwnerCreditsDepleted => {
|
||||
Some(RateLimitReachedType::WorkspaceOwnerCreditsDepleted)
|
||||
}
|
||||
BackendRateLimitReachedKind::WorkspaceMemberCreditsDepleted => {
|
||||
Some(RateLimitReachedType::WorkspaceMemberCreditsDepleted)
|
||||
}
|
||||
BackendRateLimitReachedKind::WorkspaceOwnerUsageLimitReached => {
|
||||
Some(RateLimitReachedType::WorkspaceOwnerUsageLimitReached)
|
||||
}
|
||||
BackendRateLimitReachedKind::WorkspaceMemberUsageLimitReached => {
|
||||
Some(RateLimitReachedType::WorkspaceMemberUsageLimitReached)
|
||||
}
|
||||
BackendRateLimitReachedKind::Unknown => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,6 +554,8 @@ impl Client {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codex_backend_openapi_models::models::AdditionalRateLimitDetails;
|
||||
use codex_backend_openapi_models::models::RateLimitReachedKind;
|
||||
use codex_backend_openapi_models::models::RateLimitReachedType as BackendRateLimitReachedType;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
@@ -574,6 +609,9 @@ mod tests {
|
||||
balance: Some(Some("9.99".to_string())),
|
||||
..Default::default()
|
||||
}))),
|
||||
rate_limit_reached_type: Some(Some(BackendRateLimitReachedType {
|
||||
kind: RateLimitReachedKind::WorkspaceMemberCreditsDepleted,
|
||||
})),
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
@@ -598,6 +636,10 @@ mod tests {
|
||||
})
|
||||
);
|
||||
assert_eq!(snapshots[0].plan_type, Some(AccountPlanType::Pro));
|
||||
assert_eq!(
|
||||
snapshots[0].rate_limit_reached_type,
|
||||
Some(RateLimitReachedType::WorkspaceMemberCreditsDepleted)
|
||||
);
|
||||
|
||||
assert_eq!(snapshots[1].limit_id.as_deref(), Some("codex_other"));
|
||||
assert_eq!(snapshots[1].limit_name.as_deref(), Some("codex_other"));
|
||||
@@ -607,6 +649,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(snapshots[1].credits, None);
|
||||
assert_eq!(snapshots[1].plan_type, Some(AccountPlanType::Pro));
|
||||
assert_eq!(snapshots[1].rate_limit_reached_type, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -620,6 +663,7 @@ mod tests {
|
||||
rate_limit: None,
|
||||
}])),
|
||||
credits: None,
|
||||
rate_limit_reached_type: None,
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
@@ -645,6 +689,7 @@ mod tests {
|
||||
secondary: None,
|
||||
credits: None,
|
||||
plan_type: Some(AccountPlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
},
|
||||
RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
@@ -657,6 +702,7 @@ mod tests {
|
||||
secondary: None,
|
||||
credits: None,
|
||||
plan_type: Some(AccountPlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -667,4 +713,58 @@ mod tests {
|
||||
.unwrap_or_else(|| snapshots[0].clone());
|
||||
assert_eq!(preferred.limit_id.as_deref(), Some("codex"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_payload_maps_every_rate_limit_reached_type() {
|
||||
let cases = [
|
||||
(
|
||||
RateLimitReachedKind::RateLimitReached,
|
||||
Some(RateLimitReachedType::RateLimitReached),
|
||||
),
|
||||
(
|
||||
RateLimitReachedKind::WorkspaceOwnerCreditsDepleted,
|
||||
Some(RateLimitReachedType::WorkspaceOwnerCreditsDepleted),
|
||||
),
|
||||
(
|
||||
RateLimitReachedKind::WorkspaceMemberCreditsDepleted,
|
||||
Some(RateLimitReachedType::WorkspaceMemberCreditsDepleted),
|
||||
),
|
||||
(
|
||||
RateLimitReachedKind::WorkspaceOwnerUsageLimitReached,
|
||||
Some(RateLimitReachedType::WorkspaceOwnerUsageLimitReached),
|
||||
),
|
||||
(
|
||||
RateLimitReachedKind::WorkspaceMemberUsageLimitReached,
|
||||
Some(RateLimitReachedType::WorkspaceMemberUsageLimitReached),
|
||||
),
|
||||
(RateLimitReachedKind::Unknown, None),
|
||||
];
|
||||
|
||||
for (kind, expected) in cases {
|
||||
let payload = RateLimitStatusPayload {
|
||||
plan_type: crate::types::PlanType::Plus,
|
||||
rate_limit: None,
|
||||
credits: None,
|
||||
additional_rate_limits: None,
|
||||
rate_limit_reached_type: Some(Some(BackendRateLimitReachedType { kind })),
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
assert_eq!(snapshots[0].rate_limit_reached_type, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_payload_preserves_absent_rate_limit_reached_type() {
|
||||
let payload = RateLimitStatusPayload {
|
||||
plan_type: crate::types::PlanType::Plus,
|
||||
rate_limit: None,
|
||||
credits: None,
|
||||
additional_rate_limits: None,
|
||||
rate_limit_reached_type: None,
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
assert_eq!(snapshots[0].rate_limit_reached_type, None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ pub use codex_backend_openapi_models::models::ConfigFileResponse;
|
||||
pub use codex_backend_openapi_models::models::CreditStatusDetails;
|
||||
pub use codex_backend_openapi_models::models::PaginatedListTaskListItem;
|
||||
pub use codex_backend_openapi_models::models::PlanType;
|
||||
pub use codex_backend_openapi_models::models::RateLimitReachedKind;
|
||||
pub use codex_backend_openapi_models::models::RateLimitStatusDetails;
|
||||
pub use codex_backend_openapi_models::models::RateLimitStatusPayload;
|
||||
pub use codex_backend_openapi_models::models::RateLimitWindowSnapshot;
|
||||
|
||||
Reference in New Issue
Block a user