mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
Extend rate limit reads with usage capabilities (#42358)
## What changed - Accept optional `account/rateLimits/read` capabilities for Luna Reserve support and lightweight background polling while preserving omitted and `null` params. - Forward the Luna Reserve capability only for eligible ChatGPT sessions, and let lightweight polls skip the separate reset-credit detail request. - Return the backend's `ordinaryUsageAllowed` decision only when its account and user identity match the active session. ## Testing - Cover capability defaults, eligible and restricted authentication modes, lightweight polling, identity filtering, and backend permission handling. GitOrigin-RevId: f407a3ae1e70e411fdf245f072a16e453f59cd87
This commit is contained in:
committed by
copyberry
parent
0227158fd5
commit
577a4fcd06
@@ -2154,6 +2154,11 @@ mod tests {
|
||||
"params?: GetAccountTokenUsageParams | undefined, }"
|
||||
);
|
||||
assert!(client_request_ts.contains(LEGACY_ACCOUNT_USAGE_REQUEST));
|
||||
const LEGACY_ACCOUNT_RATE_LIMITS_REQUEST: &str = concat!(
|
||||
"{ \"method\": \"account/rateLimits/read\", id: RequestId, ",
|
||||
"params?: GetAccountRateLimitsParams | undefined, }"
|
||||
);
|
||||
assert!(client_request_ts.contains(LEGACY_ACCOUNT_RATE_LIMITS_REQUEST));
|
||||
let account_usage_response_ts = std::str::from_utf8(
|
||||
fixture_tree
|
||||
.get(Path::new("v2/GetAccountTokenUsageResponse.ts"))
|
||||
@@ -2232,12 +2237,16 @@ mod tests {
|
||||
});
|
||||
|
||||
let contents = std::str::from_utf8(contents)?;
|
||||
// The stable usage RPC originally required `params: undefined`. Keep that exact
|
||||
// legacy value accepted while extending the same method with optional thread params.
|
||||
let legacy_account_usage_undefined = path == Path::new("ClientRequest.ts")
|
||||
&& contents.matches("| undefined").count() == 1
|
||||
&& contents.contains(LEGACY_ACCOUNT_USAGE_REQUEST);
|
||||
if contents.contains("| undefined") && !legacy_account_usage_undefined {
|
||||
// Both stable usage RPCs originally required `params: undefined`. Preserve that
|
||||
// source compatibility only for these exact envelopes, not arbitrary new fields.
|
||||
let checked_contents = if path == Path::new("ClientRequest.ts") {
|
||||
contents
|
||||
.replace(LEGACY_ACCOUNT_USAGE_REQUEST, "")
|
||||
.replace(LEGACY_ACCOUNT_RATE_LIMITS_REQUEST, "")
|
||||
} else {
|
||||
contents.to_owned()
|
||||
};
|
||||
if checked_contents.contains("| undefined") {
|
||||
undefined_offenders.push(path.clone());
|
||||
}
|
||||
|
||||
|
||||
@@ -493,6 +493,16 @@ enum GetAccountTokenUsageParamsTypeScript {
|
||||
Undefined,
|
||||
}
|
||||
|
||||
/// Preserve omitted/undefined params while exporting the new usage capability type.
|
||||
#[allow(dead_code)]
|
||||
#[derive(TS)]
|
||||
#[ts(untagged)]
|
||||
enum GetAccountRateLimitsParamsTypeScript {
|
||||
Params(v2::GetAccountRateLimitsParams),
|
||||
#[ts(type = "undefined")]
|
||||
Undefined,
|
||||
}
|
||||
|
||||
client_request_definitions! {
|
||||
Initialize => "initialize" {
|
||||
params: v1::InitializeParams,
|
||||
@@ -1232,7 +1242,7 @@ client_request_definitions! {
|
||||
},
|
||||
|
||||
GetAccountRateLimits => "account/rateLimits/read" {
|
||||
params: #[ts(type = "undefined")] #[serde(skip_serializing_if = "Option::is_none")] Option<()>,
|
||||
params: #[ts(optional, as = "Option<GetAccountRateLimitsParamsTypeScript>", inline)] #[serde(default, skip_serializing_if = "Option::is_none")] v2::NullableGetAccountRateLimitsParams,
|
||||
serialization: None,
|
||||
response: v2::GetAccountRateLimitsResponse,
|
||||
},
|
||||
|
||||
@@ -308,10 +308,30 @@ impl fmt::Debug for ChatgptAuthTokensRefreshResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/// Usage-read capabilities of the requesting client, never inferred from its experiment arm.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct GetAccountRateLimitsParams {
|
||||
/// The client supports automatic Luna Reserve fallback. For eligible ChatGPT CLI users,
|
||||
/// allow the backend to record experiment exposure after ordinary usage is blocked.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub supports_luna_reserve: bool,
|
||||
/// Skip the separate reset-credit detail lookup for background usage polls. The usage
|
||||
/// response still includes the available count; omitted/false preserves detailed reads.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub exclude_reset_credit_details: bool,
|
||||
}
|
||||
|
||||
pub type NullableGetAccountRateLimitsParams = Option<GetAccountRateLimitsParams>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct GetAccountRateLimitsResponse {
|
||||
/// Backend permission for ordinary included usage, validated against the active account.
|
||||
/// Null means unavailable; clients must not infer recovery from percentages or reset times.
|
||||
pub ordinary_usage_allowed: Option<bool>,
|
||||
/// Backward-compatible single-bucket view; mirrors the historical payload.
|
||||
pub rate_limits: RateLimitSnapshot,
|
||||
/// Multi-bucket view keyed by metered `limit_id` (for example, `codex`).
|
||||
|
||||
Reference in New Issue
Block a user