[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:
richardopenai
2026-04-17 13:37:25 -07:00
committed by GitHub
parent f017a23835
commit 139fa8b8f2
27 changed files with 371 additions and 6 deletions
@@ -2046,6 +2046,16 @@
],
"type": "string"
},
"RateLimitReachedType": {
"enum": [
"rate_limit_reached",
"workspace_owner_credits_depleted",
"workspace_member_credits_depleted",
"workspace_owner_usage_limit_reached",
"workspace_member_usage_limit_reached"
],
"type": "string"
},
"RateLimitSnapshot": {
"properties": {
"credits": {
@@ -2090,6 +2100,16 @@
}
]
},
"rateLimitReachedType": {
"anyOf": [
{
"$ref": "#/definitions/RateLimitReachedType"
},
{
"type": "null"
}
]
},
"secondary": {
"anyOf": [
{
@@ -10692,6 +10692,16 @@
},
"type": "object"
},
"RateLimitReachedType": {
"enum": [
"rate_limit_reached",
"workspace_owner_credits_depleted",
"workspace_member_credits_depleted",
"workspace_owner_usage_limit_reached",
"workspace_member_usage_limit_reached"
],
"type": "string"
},
"RateLimitSnapshot": {
"properties": {
"credits": {
@@ -10736,6 +10746,16 @@
}
]
},
"rateLimitReachedType": {
"anyOf": [
{
"$ref": "#/definitions/v2/RateLimitReachedType"
},
{
"type": "null"
}
]
},
"secondary": {
"anyOf": [
{
@@ -7444,6 +7444,16 @@
},
"type": "object"
},
"RateLimitReachedType": {
"enum": [
"rate_limit_reached",
"workspace_owner_credits_depleted",
"workspace_member_credits_depleted",
"workspace_owner_usage_limit_reached",
"workspace_member_usage_limit_reached"
],
"type": "string"
},
"RateLimitSnapshot": {
"properties": {
"credits": {
@@ -7488,6 +7498,16 @@
}
]
},
"rateLimitReachedType": {
"anyOf": [
{
"$ref": "#/definitions/RateLimitReachedType"
},
{
"type": "null"
}
]
},
"secondary": {
"anyOf": [
{
@@ -39,6 +39,16 @@
],
"type": "string"
},
"RateLimitReachedType": {
"enum": [
"rate_limit_reached",
"workspace_owner_credits_depleted",
"workspace_member_credits_depleted",
"workspace_owner_usage_limit_reached",
"workspace_member_usage_limit_reached"
],
"type": "string"
},
"RateLimitSnapshot": {
"properties": {
"credits": {
@@ -83,6 +93,16 @@
}
]
},
"rateLimitReachedType": {
"anyOf": [
{
"$ref": "#/definitions/RateLimitReachedType"
},
{
"type": "null"
}
]
},
"secondary": {
"anyOf": [
{
@@ -39,6 +39,16 @@
],
"type": "string"
},
"RateLimitReachedType": {
"enum": [
"rate_limit_reached",
"workspace_owner_credits_depleted",
"workspace_member_credits_depleted",
"workspace_owner_usage_limit_reached",
"workspace_member_usage_limit_reached"
],
"type": "string"
},
"RateLimitSnapshot": {
"properties": {
"credits": {
@@ -83,6 +93,16 @@
}
]
},
"rateLimitReachedType": {
"anyOf": [
{
"$ref": "#/definitions/RateLimitReachedType"
},
{
"type": "null"
}
]
},
"secondary": {
"anyOf": [
{
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type RateLimitReachedType = "rate_limit_reached" | "workspace_owner_credits_depleted" | "workspace_member_credits_depleted" | "workspace_owner_usage_limit_reached" | "workspace_member_usage_limit_reached";
@@ -3,6 +3,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { PlanType } from "../PlanType";
import type { CreditsSnapshot } from "./CreditsSnapshot";
import type { RateLimitReachedType } from "./RateLimitReachedType";
import type { RateLimitWindow } from "./RateLimitWindow";
export type RateLimitSnapshot = { limitId: string | null, limitName: string | null, primary: RateLimitWindow | null, secondary: RateLimitWindow | null, credits: CreditsSnapshot | null, planType: PlanType | null, };
export type RateLimitSnapshot = { limitId: string | null, limitName: string | null, primary: RateLimitWindow | null, secondary: RateLimitWindow | null, credits: CreditsSnapshot | null, planType: PlanType | null, rateLimitReachedType: RateLimitReachedType | null, };
@@ -241,6 +241,7 @@ export type { PluginUninstallParams } from "./PluginUninstallParams";
export type { PluginUninstallResponse } from "./PluginUninstallResponse";
export type { PluginsMigration } from "./PluginsMigration";
export type { ProfileV2 } from "./ProfileV2";
export type { RateLimitReachedType } from "./RateLimitReachedType";
export type { RateLimitSnapshot } from "./RateLimitSnapshot";
export type { RateLimitWindow } from "./RateLimitWindow";
export type { RawResponseItemCompletedNotification } from "./RawResponseItemCompletedNotification";
@@ -70,6 +70,7 @@ use codex_protocol::protocol::ModelRerouteReason as CoreModelRerouteReason;
use codex_protocol::protocol::NetworkAccess as CoreNetworkAccess;
use codex_protocol::protocol::NonSteerableTurnKind as CoreNonSteerableTurnKind;
use codex_protocol::protocol::PatchApplyStatus as CorePatchApplyStatus;
use codex_protocol::protocol::RateLimitReachedType as CoreRateLimitReachedType;
use codex_protocol::protocol::RateLimitSnapshot as CoreRateLimitSnapshot;
use codex_protocol::protocol::RateLimitWindow as CoreRateLimitWindow;
use codex_protocol::protocol::ReadOnlyAccess as CoreReadOnlyAccess;
@@ -6529,6 +6530,7 @@ pub struct RateLimitSnapshot {
pub secondary: Option<RateLimitWindow>,
pub credits: Option<CreditsSnapshot>,
pub plan_type: Option<PlanType>,
pub rate_limit_reached_type: Option<RateLimitReachedType>,
}
impl From<CoreRateLimitSnapshot> for RateLimitSnapshot {
@@ -6540,6 +6542,60 @@ impl From<CoreRateLimitSnapshot> for RateLimitSnapshot {
secondary: value.secondary.map(RateLimitWindow::from),
credits: value.credits.map(CreditsSnapshot::from),
plan_type: value.plan_type,
rate_limit_reached_type: value
.rate_limit_reached_type
.map(RateLimitReachedType::from),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "snake_case")]
#[ts(export_to = "v2/", rename_all = "snake_case")]
pub enum RateLimitReachedType {
RateLimitReached,
WorkspaceOwnerCreditsDepleted,
WorkspaceMemberCreditsDepleted,
WorkspaceOwnerUsageLimitReached,
WorkspaceMemberUsageLimitReached,
}
impl From<CoreRateLimitReachedType> for RateLimitReachedType {
fn from(value: CoreRateLimitReachedType) -> Self {
match value {
CoreRateLimitReachedType::RateLimitReached => Self::RateLimitReached,
CoreRateLimitReachedType::WorkspaceOwnerCreditsDepleted => {
Self::WorkspaceOwnerCreditsDepleted
}
CoreRateLimitReachedType::WorkspaceMemberCreditsDepleted => {
Self::WorkspaceMemberCreditsDepleted
}
CoreRateLimitReachedType::WorkspaceOwnerUsageLimitReached => {
Self::WorkspaceOwnerUsageLimitReached
}
CoreRateLimitReachedType::WorkspaceMemberUsageLimitReached => {
Self::WorkspaceMemberUsageLimitReached
}
}
}
}
impl From<RateLimitReachedType> for CoreRateLimitReachedType {
fn from(value: RateLimitReachedType) -> Self {
match value {
RateLimitReachedType::RateLimitReached => Self::RateLimitReached,
RateLimitReachedType::WorkspaceOwnerCreditsDepleted => {
Self::WorkspaceOwnerCreditsDepleted
}
RateLimitReachedType::WorkspaceMemberCreditsDepleted => {
Self::WorkspaceMemberCreditsDepleted
}
RateLimitReachedType::WorkspaceOwnerUsageLimitReached => {
Self::WorkspaceOwnerUsageLimitReached
}
RateLimitReachedType::WorkspaceMemberUsageLimitReached => {
Self::WorkspaceMemberUsageLimitReached
}
}
}
}