mirror of
https://github.com/openai/codex.git
synced 2026-05-21 19:45:26 +00:00
Compare commits
1 Commits
xl/plugins
...
jchu/codex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b42be8d6b |
@@ -934,6 +934,62 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CurrentUsageLimitNudgeState": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unknown"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"inactive"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"nudge": {
|
||||
"$ref": "#/definitions/UsageLimitNudge"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"active"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nudge",
|
||||
"type"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"DeprecationNoticeNotification": {
|
||||
"properties": {
|
||||
"details": {
|
||||
@@ -2422,6 +2478,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"currentUsageLimitNudge": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CurrentUsageLimitNudgeState"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "unknown"
|
||||
}
|
||||
},
|
||||
"limitId": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -4343,6 +4409,34 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UsageLimitNudge": {
|
||||
"properties": {
|
||||
"action": {
|
||||
"$ref": "#/definitions/UsageLimitNudgeAction"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"threshold": {
|
||||
"format": "uint8",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action",
|
||||
"key",
|
||||
"threshold"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudgeAction": {
|
||||
"enum": [
|
||||
"add_credits",
|
||||
"upgrade"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
@@ -7636,6 +7636,62 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CurrentUsageLimitNudgeState": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unknown"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"inactive"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"nudge": {
|
||||
"$ref": "#/definitions/v2/UsageLimitNudge"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"active"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nudge",
|
||||
"type"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"DeprecationNoticeNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -12114,6 +12170,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"currentUsageLimitNudge": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/CurrentUsageLimitNudgeState"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "unknown"
|
||||
}
|
||||
},
|
||||
"limitId": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -17186,6 +17252,34 @@
|
||||
"title": "TurnSteerResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudge": {
|
||||
"properties": {
|
||||
"action": {
|
||||
"$ref": "#/definitions/v2/UsageLimitNudgeAction"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"threshold": {
|
||||
"format": "uint8",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action",
|
||||
"key",
|
||||
"threshold"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudgeAction": {
|
||||
"enum": [
|
||||
"add_credits",
|
||||
"upgrade"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
@@ -4155,6 +4155,62 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CurrentUsageLimitNudgeState": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unknown"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"inactive"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"nudge": {
|
||||
"$ref": "#/definitions/UsageLimitNudge"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"active"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nudge",
|
||||
"type"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"DeprecationNoticeNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
@@ -8788,6 +8844,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"currentUsageLimitNudge": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CurrentUsageLimitNudgeState"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "unknown"
|
||||
}
|
||||
},
|
||||
"limitId": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -15072,6 +15138,34 @@
|
||||
"title": "TurnSteerResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudge": {
|
||||
"properties": {
|
||||
"action": {
|
||||
"$ref": "#/definitions/UsageLimitNudgeAction"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"threshold": {
|
||||
"format": "uint8",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action",
|
||||
"key",
|
||||
"threshold"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudgeAction": {
|
||||
"enum": [
|
||||
"add_credits",
|
||||
"upgrade"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
@@ -22,6 +22,62 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CurrentUsageLimitNudgeState": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unknown"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"inactive"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"nudge": {
|
||||
"$ref": "#/definitions/UsageLimitNudge"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"active"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nudge",
|
||||
"type"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PlanType": {
|
||||
"enum": [
|
||||
"free",
|
||||
@@ -61,6 +117,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"currentUsageLimitNudge": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CurrentUsageLimitNudgeState"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "unknown"
|
||||
}
|
||||
},
|
||||
"limitId": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -141,6 +207,34 @@
|
||||
"usedPercent"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudge": {
|
||||
"properties": {
|
||||
"action": {
|
||||
"$ref": "#/definitions/UsageLimitNudgeAction"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"threshold": {
|
||||
"format": "uint8",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action",
|
||||
"key",
|
||||
"threshold"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudgeAction": {
|
||||
"enum": [
|
||||
"add_credits",
|
||||
"upgrade"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
@@ -22,6 +22,62 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CurrentUsageLimitNudgeState": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"unknown"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "UnknownCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"inactive"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "InactiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"nudge": {
|
||||
"$ref": "#/definitions/UsageLimitNudge"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"active"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeStateType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"nudge",
|
||||
"type"
|
||||
],
|
||||
"title": "ActiveCurrentUsageLimitNudgeState",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PlanType": {
|
||||
"enum": [
|
||||
"free",
|
||||
@@ -61,6 +117,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"currentUsageLimitNudge": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CurrentUsageLimitNudgeState"
|
||||
}
|
||||
],
|
||||
"default": {
|
||||
"type": "unknown"
|
||||
}
|
||||
},
|
||||
"limitId": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -141,6 +207,34 @@
|
||||
"usedPercent"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudge": {
|
||||
"properties": {
|
||||
"action": {
|
||||
"$ref": "#/definitions/UsageLimitNudgeAction"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"threshold": {
|
||||
"format": "uint8",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"action",
|
||||
"key",
|
||||
"threshold"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageLimitNudgeAction": {
|
||||
"enum": [
|
||||
"add_credits",
|
||||
"upgrade"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/CurrentUsageLimitNudgeState.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/CurrentUsageLimitNudgeState.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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.
|
||||
import type { UsageLimitNudge } from "./UsageLimitNudge";
|
||||
|
||||
export type CurrentUsageLimitNudgeState = { "type": "unknown" } | { "type": "inactive" } | { "type": "active", nudge: UsageLimitNudge, };
|
||||
@@ -3,7 +3,8 @@
|
||||
// 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 { CurrentUsageLimitNudgeState } from "./CurrentUsageLimitNudgeState";
|
||||
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, rateLimitReachedType: RateLimitReachedType | 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, currentUsageLimitNudge: CurrentUsageLimitNudgeState, };
|
||||
|
||||
6
codex-rs/app-server-protocol/schema/typescript/v2/UsageLimitNudge.ts
generated
Normal file
6
codex-rs/app-server-protocol/schema/typescript/v2/UsageLimitNudge.ts
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
// 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.
|
||||
import type { UsageLimitNudgeAction } from "./UsageLimitNudgeAction";
|
||||
|
||||
export type UsageLimitNudge = { key: string, threshold: number, action: UsageLimitNudgeAction, };
|
||||
5
codex-rs/app-server-protocol/schema/typescript/v2/UsageLimitNudgeAction.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/v2/UsageLimitNudgeAction.ts
generated
Normal file
@@ -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 UsageLimitNudgeAction = "add_credits" | "upgrade";
|
||||
@@ -75,6 +75,7 @@ export type { ConfiguredHookHandler } from "./ConfiguredHookHandler";
|
||||
export type { ConfiguredHookMatcherGroup } from "./ConfiguredHookMatcherGroup";
|
||||
export type { ContextCompactedNotification } from "./ContextCompactedNotification";
|
||||
export type { CreditsSnapshot } from "./CreditsSnapshot";
|
||||
export type { CurrentUsageLimitNudgeState } from "./CurrentUsageLimitNudgeState";
|
||||
export type { DeprecationNoticeNotification } from "./DeprecationNoticeNotification";
|
||||
export type { DeviceKeyAlgorithm } from "./DeviceKeyAlgorithm";
|
||||
export type { DeviceKeyCreateParams } from "./DeviceKeyCreateParams";
|
||||
@@ -403,6 +404,8 @@ export type { TurnStartedNotification } from "./TurnStartedNotification";
|
||||
export type { TurnStatus } from "./TurnStatus";
|
||||
export type { TurnSteerParams } from "./TurnSteerParams";
|
||||
export type { TurnSteerResponse } from "./TurnSteerResponse";
|
||||
export type { UsageLimitNudge } from "./UsageLimitNudge";
|
||||
export type { UsageLimitNudgeAction } from "./UsageLimitNudgeAction";
|
||||
export type { UserInput } from "./UserInput";
|
||||
export type { WarningNotification } from "./WarningNotification";
|
||||
export type { WebSearchAction } from "./WebSearchAction";
|
||||
|
||||
@@ -61,6 +61,7 @@ use codex_protocol::protocol::AgentStatus as CoreAgentStatus;
|
||||
use codex_protocol::protocol::AskForApproval as CoreAskForApproval;
|
||||
use codex_protocol::protocol::CodexErrorInfo as CoreCodexErrorInfo;
|
||||
use codex_protocol::protocol::CreditsSnapshot as CoreCreditsSnapshot;
|
||||
use codex_protocol::protocol::CurrentUsageLimitNudgeState as CoreCurrentUsageLimitNudgeState;
|
||||
use codex_protocol::protocol::ExecCommandSource as CoreExecCommandSource;
|
||||
use codex_protocol::protocol::ExecCommandStatus as CoreExecCommandStatus;
|
||||
use codex_protocol::protocol::GranularApprovalConfig as CoreGranularApprovalConfig;
|
||||
@@ -99,6 +100,8 @@ use codex_protocol::protocol::SubAgentSource as CoreSubAgentSource;
|
||||
use codex_protocol::protocol::ThreadGoalStatus as CoreThreadGoalStatus;
|
||||
use codex_protocol::protocol::TokenUsage as CoreTokenUsage;
|
||||
use codex_protocol::protocol::TokenUsageInfo as CoreTokenUsageInfo;
|
||||
use codex_protocol::protocol::UsageLimitNudge as CoreUsageLimitNudge;
|
||||
use codex_protocol::protocol::UsageLimitNudgeAction as CoreUsageLimitNudgeAction;
|
||||
use codex_protocol::request_permissions::PermissionGrantScope as CorePermissionGrantScope;
|
||||
use codex_protocol::request_permissions::RequestPermissionProfile as CoreRequestPermissionProfile;
|
||||
use codex_protocol::user_input::ByteRange as CoreByteRange;
|
||||
@@ -7514,10 +7517,14 @@ pub struct RateLimitSnapshot {
|
||||
pub credits: Option<CreditsSnapshot>,
|
||||
pub plan_type: Option<PlanType>,
|
||||
pub rate_limit_reached_type: Option<RateLimitReachedType>,
|
||||
#[serde(default)]
|
||||
pub current_usage_limit_nudge: CurrentUsageLimitNudgeState,
|
||||
}
|
||||
|
||||
impl From<CoreRateLimitSnapshot> for RateLimitSnapshot {
|
||||
fn from(value: CoreRateLimitSnapshot) -> Self {
|
||||
let current_usage_limit_nudge =
|
||||
CurrentUsageLimitNudgeState::from(value.current_usage_limit_nudge_state());
|
||||
Self {
|
||||
limit_id: value.limit_id,
|
||||
limit_name: value.limit_name,
|
||||
@@ -7528,6 +7535,79 @@ impl From<CoreRateLimitSnapshot> for RateLimitSnapshot {
|
||||
rate_limit_reached_type: value
|
||||
.rate_limit_reached_type
|
||||
.map(RateLimitReachedType::from),
|
||||
current_usage_limit_nudge,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[ts(tag = "type", export_to = "v2/")]
|
||||
pub enum CurrentUsageLimitNudgeState {
|
||||
Unknown,
|
||||
Inactive,
|
||||
Active { nudge: UsageLimitNudge },
|
||||
}
|
||||
|
||||
impl Default for CurrentUsageLimitNudgeState {
|
||||
fn default() -> Self {
|
||||
Self::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CoreCurrentUsageLimitNudgeState> for CurrentUsageLimitNudgeState {
|
||||
fn from(value: CoreCurrentUsageLimitNudgeState) -> Self {
|
||||
match value {
|
||||
CoreCurrentUsageLimitNudgeState::Unknown => Self::Unknown,
|
||||
CoreCurrentUsageLimitNudgeState::Inactive => Self::Inactive,
|
||||
CoreCurrentUsageLimitNudgeState::Active(nudge) => Self::Active {
|
||||
nudge: UsageLimitNudge::from(nudge),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct UsageLimitNudge {
|
||||
pub key: String,
|
||||
pub threshold: u8,
|
||||
pub action: UsageLimitNudgeAction,
|
||||
}
|
||||
|
||||
impl From<CoreUsageLimitNudge> for UsageLimitNudge {
|
||||
fn from(value: CoreUsageLimitNudge) -> Self {
|
||||
Self {
|
||||
key: value.key,
|
||||
threshold: value.threshold.as_percent(),
|
||||
action: value.action.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 UsageLimitNudgeAction {
|
||||
AddCredits,
|
||||
Upgrade,
|
||||
}
|
||||
|
||||
impl From<CoreUsageLimitNudgeAction> for UsageLimitNudgeAction {
|
||||
fn from(value: CoreUsageLimitNudgeAction) -> Self {
|
||||
match value {
|
||||
CoreUsageLimitNudgeAction::AddCredits => Self::AddCredits,
|
||||
CoreUsageLimitNudgeAction::Upgrade => Self::Upgrade,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UsageLimitNudgeAction> for CoreUsageLimitNudgeAction {
|
||||
fn from(value: UsageLimitNudgeAction) -> Self {
|
||||
match value {
|
||||
UsageLimitNudgeAction::AddCredits => Self::AddCredits,
|
||||
UsageLimitNudgeAction::Upgrade => Self::Upgrade,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10803,4 +10883,94 @@ mod tests {
|
||||
"unexpected error: {err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rate_limit_snapshot_preserves_current_usage_limit_nudge_states() {
|
||||
let active: RateLimitSnapshot = serde_json::from_value(json!({
|
||||
"limitId": "codex",
|
||||
"limitName": null,
|
||||
"primary": null,
|
||||
"secondary": null,
|
||||
"credits": null,
|
||||
"planType": null,
|
||||
"rateLimitReachedType": null,
|
||||
"currentUsageLimitNudge": {
|
||||
"type": "active",
|
||||
"nudge": {
|
||||
"key": "near_limit_75_upgrade",
|
||||
"threshold": 75,
|
||||
"action": "upgrade"
|
||||
}
|
||||
}
|
||||
}))
|
||||
.expect("active snapshot should deserialize");
|
||||
assert_eq!(
|
||||
active.current_usage_limit_nudge,
|
||||
CurrentUsageLimitNudgeState::Active {
|
||||
nudge: UsageLimitNudge {
|
||||
key: "near_limit_75_upgrade".to_string(),
|
||||
threshold: 75,
|
||||
action: UsageLimitNudgeAction::Upgrade,
|
||||
},
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_value(&active)
|
||||
.expect("active snapshot should serialize")
|
||||
.get("currentUsageLimitNudge"),
|
||||
Some(&json!({
|
||||
"type": "active",
|
||||
"nudge": {
|
||||
"key": "near_limit_75_upgrade",
|
||||
"threshold": 75,
|
||||
"action": "upgrade"
|
||||
}
|
||||
}))
|
||||
);
|
||||
|
||||
let inactive: RateLimitSnapshot = serde_json::from_value(json!({
|
||||
"limitId": "codex",
|
||||
"limitName": null,
|
||||
"primary": null,
|
||||
"secondary": null,
|
||||
"credits": null,
|
||||
"planType": null,
|
||||
"rateLimitReachedType": null,
|
||||
"currentUsageLimitNudge": {
|
||||
"type": "inactive"
|
||||
}
|
||||
}))
|
||||
.expect("inactive snapshot should deserialize");
|
||||
assert_eq!(
|
||||
inactive.current_usage_limit_nudge,
|
||||
CurrentUsageLimitNudgeState::Inactive
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_value(&inactive)
|
||||
.expect("inactive snapshot should serialize")
|
||||
.get("currentUsageLimitNudge"),
|
||||
Some(&json!({ "type": "inactive" }))
|
||||
);
|
||||
|
||||
let missing: RateLimitSnapshot = serde_json::from_value(json!({
|
||||
"limitId": "codex",
|
||||
"limitName": null,
|
||||
"primary": null,
|
||||
"secondary": null,
|
||||
"credits": null,
|
||||
"planType": null,
|
||||
"rateLimitReachedType": null
|
||||
}))
|
||||
.expect("missing snapshot should deserialize");
|
||||
assert_eq!(
|
||||
missing.current_usage_limit_nudge,
|
||||
CurrentUsageLimitNudgeState::Unknown
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_value(&missing)
|
||||
.expect("missing snapshot should serialize")
|
||||
.get("currentUsageLimitNudge"),
|
||||
Some(&json!({ "type": "unknown" }))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1651,7 +1651,7 @@ Field notes:
|
||||
|
||||
```json
|
||||
{ "method": "account/rateLimits/read", "id": 7 }
|
||||
{ "id": 7, "result": { "rateLimits": { "primary": { "usedPercent": 25, "windowDurationMins": 15, "resetsAt": 1730947200 }, "secondary": null, "rateLimitReachedType": null } } }
|
||||
{ "id": 7, "result": { "rateLimits": { "primary": { "usedPercent": 25, "windowDurationMins": 15, "resetsAt": 1730947200 }, "secondary": null, "rateLimitReachedType": null, "currentUsageLimitNudge": { "type": "active", "nudge": { "key": "near_limit_75_add_credits", "threshold": 75, "action": "add_credits" } } } } }
|
||||
{ "method": "account/rateLimits/updated", "params": { "rateLimits": { … } } }
|
||||
```
|
||||
|
||||
@@ -1661,6 +1661,7 @@ Field notes:
|
||||
- `windowDurationMins` is the quota window length.
|
||||
- `resetsAt` is a Unix timestamp (seconds) for the next reset.
|
||||
- `rateLimitReachedType` identifies the backend-classified limit state when one has been reached.
|
||||
- `currentUsageLimitNudge` is the current backend-selected near-limit prompt state. Its `type` is `unknown`, `inactive`, or `active`; active states include the nudge payload under `nudge`.
|
||||
|
||||
### 8) Notify a workspace owner about a limit
|
||||
|
||||
|
||||
@@ -4471,6 +4471,7 @@ mod tests {
|
||||
}),
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
|
||||
handle_token_count_event(
|
||||
|
||||
@@ -666,6 +666,7 @@ mod tests {
|
||||
use codex_app_server_protocol::ApplyPatchApprovalParams;
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_app_server_protocol::ConfigWarningNotification;
|
||||
use codex_app_server_protocol::CurrentUsageLimitNudgeState;
|
||||
use codex_app_server_protocol::DynamicToolCallParams;
|
||||
use codex_app_server_protocol::FileChangeRequestApprovalParams;
|
||||
use codex_app_server_protocol::GuardianWarningNotification;
|
||||
@@ -751,6 +752,7 @@ mod tests {
|
||||
credits: None,
|
||||
plan_type: Some(PlanType::Plus),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: CurrentUsageLimitNudgeState::Unknown,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -770,7 +772,10 @@ mod tests {
|
||||
"secondary": null,
|
||||
"credits": null,
|
||||
"planType": "plus",
|
||||
"rateLimitReachedType": null
|
||||
"rateLimitReachedType": null,
|
||||
"currentUsageLimitNudge": {
|
||||
"type": "unknown"
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -5,6 +5,7 @@ use app_test_support::to_response;
|
||||
use app_test_support::write_chatgpt_auth;
|
||||
use codex_app_server_protocol::AddCreditsNudgeCreditType;
|
||||
use codex_app_server_protocol::AddCreditsNudgeEmailStatus;
|
||||
use codex_app_server_protocol::CurrentUsageLimitNudgeState;
|
||||
use codex_app_server_protocol::GetAccountRateLimitsResponse;
|
||||
use codex_app_server_protocol::JSONRPCError;
|
||||
use codex_app_server_protocol::JSONRPCResponse;
|
||||
@@ -183,6 +184,7 @@ async fn get_account_rate_limits_returns_snapshot() -> Result<()> {
|
||||
credits: None,
|
||||
plan_type: Some(AccountPlanType::Pro),
|
||||
rate_limit_reached_type: Some(RateLimitReachedType::WorkspaceMemberUsageLimitReached),
|
||||
current_usage_limit_nudge: CurrentUsageLimitNudgeState::Unknown,
|
||||
},
|
||||
rate_limits_by_limit_id: Some(
|
||||
[
|
||||
@@ -206,6 +208,7 @@ async fn get_account_rate_limits_returns_snapshot() -> Result<()> {
|
||||
rate_limit_reached_type: Some(
|
||||
RateLimitReachedType::WorkspaceMemberUsageLimitReached,
|
||||
),
|
||||
current_usage_limit_nudge: CurrentUsageLimitNudgeState::Unknown,
|
||||
},
|
||||
),
|
||||
(
|
||||
@@ -222,6 +225,7 @@ async fn get_account_rate_limits_returns_snapshot() -> Result<()> {
|
||||
credits: None,
|
||||
plan_type: Some(AccountPlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: CurrentUsageLimitNudgeState::Unknown,
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -15,6 +15,8 @@ use codex_protocol::protocol::CreditsSnapshot;
|
||||
use codex_protocol::protocol::RateLimitReachedType;
|
||||
use codex_protocol::protocol::RateLimitSnapshot;
|
||||
use codex_protocol::protocol::RateLimitWindow;
|
||||
use codex_protocol::protocol::UsageLimitNudgeAction;
|
||||
use codex_protocol::protocol::UsageLimitNudgeStatePayload;
|
||||
use reqwest::StatusCode;
|
||||
use reqwest::header::CONTENT_TYPE;
|
||||
use reqwest::header::HeaderMap;
|
||||
@@ -452,6 +454,9 @@ impl Client {
|
||||
.rate_limit_reached_type
|
||||
.flatten()
|
||||
.and_then(|details| Self::map_rate_limit_reached_type(details.kind));
|
||||
let current_usage_limit_nudge = payload
|
||||
.current_usage_limit_nudge
|
||||
.map(|nudge| Self::map_usage_limit_nudge_state(*nudge));
|
||||
let mut snapshots = vec![Self::make_rate_limit_snapshot(
|
||||
Some("codex".to_string()),
|
||||
/*limit_name*/ None,
|
||||
@@ -459,6 +464,7 @@ impl Client {
|
||||
payload.credits.flatten().map(|details| *details),
|
||||
plan_type,
|
||||
rate_limit_reached_type,
|
||||
current_usage_limit_nudge,
|
||||
)];
|
||||
if let Some(additional) = payload.additional_rate_limits.flatten() {
|
||||
snapshots.extend(additional.into_iter().map(|details| {
|
||||
@@ -469,6 +475,7 @@ impl Client {
|
||||
/*credits*/ None,
|
||||
plan_type,
|
||||
/*rate_limit_reached_type*/ None,
|
||||
/*current_usage_limit_nudge*/ None,
|
||||
)
|
||||
}));
|
||||
}
|
||||
@@ -482,6 +489,7 @@ impl Client {
|
||||
credits: Option<crate::types::CreditStatusDetails>,
|
||||
plan_type: Option<AccountPlanType>,
|
||||
rate_limit_reached_type: Option<RateLimitReachedType>,
|
||||
current_usage_limit_nudge: Option<UsageLimitNudgeStatePayload>,
|
||||
) -> RateLimitSnapshot {
|
||||
let (primary, secondary) = match rate_limit {
|
||||
Some(details) => (
|
||||
@@ -498,6 +506,29 @@ impl Client {
|
||||
credits: Self::map_credits(credits),
|
||||
plan_type,
|
||||
rate_limit_reached_type,
|
||||
current_usage_limit_nudge,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_usage_limit_nudge_state(
|
||||
nudge: crate::types::UsageLimitNudgeState,
|
||||
) -> UsageLimitNudgeStatePayload {
|
||||
match nudge {
|
||||
crate::types::UsageLimitNudgeState::Inactive => UsageLimitNudgeStatePayload::Inactive,
|
||||
crate::types::UsageLimitNudgeState::Active {
|
||||
key,
|
||||
threshold,
|
||||
action,
|
||||
} => UsageLimitNudgeStatePayload::Active {
|
||||
key,
|
||||
threshold,
|
||||
action: match action {
|
||||
crate::types::UsageLimitNudgeAction::AddCredits => {
|
||||
UsageLimitNudgeAction::AddCredits
|
||||
}
|
||||
crate::types::UsageLimitNudgeAction::Upgrade => UsageLimitNudgeAction::Upgrade,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,6 +692,7 @@ mod tests {
|
||||
rate_limit_reached_type: Some(Some(BackendRateLimitReachedType {
|
||||
kind: RateLimitReachedKind::WorkspaceMemberCreditsDepleted,
|
||||
})),
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
@@ -713,6 +745,7 @@ mod tests {
|
||||
}])),
|
||||
credits: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
@@ -739,6 +772,7 @@ mod tests {
|
||||
credits: None,
|
||||
plan_type: Some(AccountPlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
},
|
||||
RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
@@ -752,6 +786,7 @@ mod tests {
|
||||
credits: None,
|
||||
plan_type: Some(AccountPlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -796,6 +831,7 @@ mod tests {
|
||||
credits: None,
|
||||
additional_rate_limits: None,
|
||||
rate_limit_reached_type: Some(Some(BackendRateLimitReachedType { kind })),
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
@@ -811,12 +847,72 @@ mod tests {
|
||||
credits: None,
|
||||
additional_rate_limits: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
assert_eq!(snapshots[0].rate_limit_reached_type, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_payload_preserves_active_current_usage_limit_nudge() {
|
||||
let payload = RateLimitStatusPayload {
|
||||
plan_type: crate::types::PlanType::Plus,
|
||||
rate_limit: None,
|
||||
credits: None,
|
||||
additional_rate_limits: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: Some(Box::new(crate::types::UsageLimitNudgeState::Active {
|
||||
key: "near_limit_75_add_credits".to_string(),
|
||||
threshold: 75,
|
||||
action: crate::types::UsageLimitNudgeAction::AddCredits,
|
||||
})),
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
assert_eq!(
|
||||
snapshots[0].current_usage_limit_nudge,
|
||||
Some(UsageLimitNudgeStatePayload::Active {
|
||||
key: "near_limit_75_add_credits".to_string(),
|
||||
threshold: 75,
|
||||
action: UsageLimitNudgeAction::AddCredits,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_payload_preserves_explicitly_inactive_current_usage_limit_nudge() {
|
||||
let payload = RateLimitStatusPayload {
|
||||
plan_type: crate::types::PlanType::Plus,
|
||||
rate_limit: None,
|
||||
credits: None,
|
||||
additional_rate_limits: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: Some(Box::new(crate::types::UsageLimitNudgeState::Inactive)),
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
assert_eq!(
|
||||
snapshots[0].current_usage_limit_nudge,
|
||||
Some(UsageLimitNudgeStatePayload::Inactive)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn usage_payload_preserves_missing_current_usage_limit_nudge() {
|
||||
let payload = RateLimitStatusPayload {
|
||||
plan_type: crate::types::PlanType::Plus,
|
||||
rate_limit: None,
|
||||
credits: None,
|
||||
additional_rate_limits: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
|
||||
let snapshots = Client::rate_limit_snapshots_from_payload(payload);
|
||||
assert_eq!(snapshots[0].current_usage_limit_nudge, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_credits_nudge_email_uses_expected_paths_and_bodies() {
|
||||
let codex_client = Client {
|
||||
|
||||
@@ -7,6 +7,8 @@ pub use codex_backend_openapi_models::models::RateLimitStatusDetails;
|
||||
pub use codex_backend_openapi_models::models::RateLimitStatusPayload;
|
||||
pub use codex_backend_openapi_models::models::RateLimitWindowSnapshot;
|
||||
pub use codex_backend_openapi_models::models::TaskListItem;
|
||||
pub use codex_backend_openapi_models::models::UsageLimitNudgeAction;
|
||||
pub use codex_backend_openapi_models::models::UsageLimitNudgeState;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::de::Deserializer;
|
||||
|
||||
@@ -2,6 +2,7 @@ use codex_protocol::account::PlanType;
|
||||
use codex_protocol::protocol::CreditsSnapshot;
|
||||
use codex_protocol::protocol::RateLimitSnapshot;
|
||||
use codex_protocol::protocol::RateLimitWindow;
|
||||
use codex_protocol::protocol::UsageLimitNudgeStatePayload;
|
||||
use http::HeaderMap;
|
||||
use serde::Deserialize;
|
||||
use std::collections::BTreeSet;
|
||||
@@ -94,6 +95,7 @@ pub fn parse_rate_limit_for_limit(
|
||||
credits,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -126,6 +128,7 @@ struct RateLimitEvent {
|
||||
credits: Option<RateLimitEventCredits>,
|
||||
metered_limit_name: Option<String>,
|
||||
limit_name: Option<String>,
|
||||
current_usage_limit_nudge: Option<UsageLimitNudgeStatePayload>,
|
||||
}
|
||||
|
||||
pub fn parse_rate_limit_event(payload: &str) -> Option<RateLimitSnapshot> {
|
||||
@@ -158,6 +161,7 @@ pub fn parse_rate_limit_event(payload: &str) -> Option<RateLimitSnapshot> {
|
||||
credits,
|
||||
plan_type: event.plan_type,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: event.current_usage_limit_nudge,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -365,4 +369,55 @@ mod tests {
|
||||
assert_eq!(updates[0].secondary, None);
|
||||
assert_eq!(updates[0].credits, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_rate_limit_event_preserves_active_current_usage_limit_nudge() {
|
||||
let snapshot = parse_rate_limit_event(
|
||||
r#"{
|
||||
"type": "codex.rate_limits",
|
||||
"current_usage_limit_nudge": {
|
||||
"type": "active",
|
||||
"key": "near_limit_90_upgrade",
|
||||
"threshold": 90,
|
||||
"action": "upgrade"
|
||||
}
|
||||
}"#,
|
||||
)
|
||||
.expect("snapshot");
|
||||
|
||||
assert_eq!(
|
||||
snapshot.current_usage_limit_nudge,
|
||||
Some(UsageLimitNudgeStatePayload::Active {
|
||||
key: "near_limit_90_upgrade".to_string(),
|
||||
threshold: 90,
|
||||
action: codex_protocol::protocol::UsageLimitNudgeAction::Upgrade,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_rate_limit_event_preserves_explicitly_inactive_current_usage_limit_nudge() {
|
||||
let snapshot = parse_rate_limit_event(
|
||||
r#"{
|
||||
"type": "codex.rate_limits",
|
||||
"current_usage_limit_nudge": {
|
||||
"type": "inactive"
|
||||
}
|
||||
}"#,
|
||||
)
|
||||
.expect("snapshot");
|
||||
|
||||
assert_eq!(
|
||||
snapshot.current_usage_limit_nudge,
|
||||
Some(UsageLimitNudgeStatePayload::Inactive)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_rate_limit_event_preserves_missing_current_usage_limit_nudge() {
|
||||
let snapshot =
|
||||
parse_rate_limit_event(r#"{ "type": "codex.rate_limits" }"#).expect("snapshot");
|
||||
|
||||
assert_eq!(snapshot.current_usage_limit_nudge, None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,3 +44,7 @@ pub use self::rate_limit_window_snapshot::RateLimitWindowSnapshot;
|
||||
|
||||
pub(crate) mod credit_status_details;
|
||||
pub use self::credit_status_details::CreditStatusDetails;
|
||||
|
||||
pub(crate) mod usage_limit_nudge;
|
||||
pub use self::usage_limit_nudge::UsageLimitNudgeAction;
|
||||
pub use self::usage_limit_nudge::UsageLimitNudgeState;
|
||||
|
||||
@@ -44,6 +44,12 @@ pub struct RateLimitStatusPayload {
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub rate_limit_reached_type: Option<Option<RateLimitReachedType>>,
|
||||
#[serde(
|
||||
rename = "current_usage_limit_nudge",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub current_usage_limit_nudge: Option<Box<models::UsageLimitNudgeState>>,
|
||||
}
|
||||
|
||||
impl RateLimitStatusPayload {
|
||||
@@ -54,6 +60,7 @@ impl RateLimitStatusPayload {
|
||||
credits: None,
|
||||
additional_rate_limits: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* codex-backend
|
||||
*
|
||||
* codex-backend
|
||||
*
|
||||
* The version of the OpenAPI document: 0.0.1
|
||||
*
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum UsageLimitNudgeState {
|
||||
Inactive,
|
||||
Active {
|
||||
#[serde(rename = "key")]
|
||||
key: String,
|
||||
#[serde(rename = "threshold")]
|
||||
threshold: u8,
|
||||
#[serde(rename = "action")]
|
||||
action: UsageLimitNudgeAction,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
pub enum UsageLimitNudgeAction {
|
||||
#[serde(rename = "add_credits")]
|
||||
AddCredits,
|
||||
#[serde(rename = "upgrade")]
|
||||
Upgrade,
|
||||
}
|
||||
@@ -2326,6 +2326,7 @@ async fn set_rate_limits_retains_previous_credits() {
|
||||
}),
|
||||
plan_type: Some(codex_protocol::account::PlanType::Plus),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
state.set_rate_limits(initial.clone());
|
||||
|
||||
@@ -2345,6 +2346,7 @@ async fn set_rate_limits_retains_previous_credits() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
state.set_rate_limits(update.clone());
|
||||
|
||||
@@ -2358,6 +2360,7 @@ async fn set_rate_limits_retains_previous_credits() {
|
||||
credits: initial.credits,
|
||||
plan_type: initial.plan_type,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -2432,6 +2435,7 @@ async fn set_rate_limits_updates_plan_type_when_present() {
|
||||
}),
|
||||
plan_type: Some(codex_protocol::account::PlanType::Plus),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
state.set_rate_limits(initial.clone());
|
||||
|
||||
@@ -2447,6 +2451,7 @@ async fn set_rate_limits_updates_plan_type_when_present() {
|
||||
credits: None,
|
||||
plan_type: Some(codex_protocol::account::PlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
state.set_rate_limits(update.clone());
|
||||
|
||||
@@ -2460,6 +2465,7 @@ async fn set_rate_limits_updates_plan_type_when_present() {
|
||||
credits: initial.credits,
|
||||
plan_type: update.plan_type,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ async fn set_rate_limits_defaults_limit_id_to_codex_when_missing() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -78,6 +79,7 @@ async fn set_rate_limits_defaults_to_codex_when_limit_id_missing_after_other_buc
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
});
|
||||
state.set_rate_limits(RateLimitSnapshot {
|
||||
limit_id: None,
|
||||
@@ -91,6 +93,7 @@ async fn set_rate_limits_defaults_to_codex_when_limit_id_missing_after_other_buc
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -123,6 +126,7 @@ async fn set_rate_limits_carries_credits_and_plan_type_from_codex_to_codex_other
|
||||
}),
|
||||
plan_type: Some(codex_protocol::account::PlanType::Plus),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
});
|
||||
|
||||
state.set_rate_limits(RateLimitSnapshot {
|
||||
@@ -137,6 +141,7 @@ async fn set_rate_limits_carries_credits_and_plan_type_from_codex_to_codex_other
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -157,6 +162,7 @@ async fn set_rate_limits_carries_credits_and_plan_type_from_codex_to_codex_other
|
||||
}),
|
||||
plan_type: Some(codex_protocol::account::PlanType::Plus),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ fn snapshot(
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ fn rate_limit_snapshot() -> RateLimitSnapshot {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2125,6 +2125,25 @@ pub struct RateLimitSnapshot {
|
||||
pub credits: Option<CreditsSnapshot>,
|
||||
pub plan_type: Option<crate::account::PlanType>,
|
||||
pub rate_limit_reached_type: Option<RateLimitReachedType>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub current_usage_limit_nudge: Option<UsageLimitNudgeStatePayload>,
|
||||
}
|
||||
|
||||
impl RateLimitSnapshot {
|
||||
pub fn current_usage_limit_nudge_state(&self) -> CurrentUsageLimitNudgeState {
|
||||
match &self.current_usage_limit_nudge {
|
||||
None => CurrentUsageLimitNudgeState::Unknown,
|
||||
Some(UsageLimitNudgeStatePayload::Inactive) => CurrentUsageLimitNudgeState::Inactive,
|
||||
Some(UsageLimitNudgeStatePayload::Active {
|
||||
key,
|
||||
threshold,
|
||||
action,
|
||||
}) => UsageLimitNudge::from_payload(key, *threshold, *action)
|
||||
.map(CurrentUsageLimitNudgeState::Active)
|
||||
.unwrap_or(CurrentUsageLimitNudgeState::Inactive),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, JsonSchema, TS)]
|
||||
@@ -2138,6 +2157,73 @@ pub enum RateLimitReachedType {
|
||||
WorkspaceMemberUsageLimitReached,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, JsonSchema, TS)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
#[ts(tag = "type")]
|
||||
pub enum UsageLimitNudgeStatePayload {
|
||||
Inactive,
|
||||
Active {
|
||||
key: String,
|
||||
threshold: u8,
|
||||
action: UsageLimitNudgeAction,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct UsageLimitNudge {
|
||||
pub key: String,
|
||||
pub threshold: UsageLimitNudgeThreshold,
|
||||
pub action: UsageLimitNudgeAction,
|
||||
}
|
||||
|
||||
impl UsageLimitNudge {
|
||||
fn from_payload(key: &str, threshold: u8, action: UsageLimitNudgeAction) -> Option<Self> {
|
||||
Some(Self {
|
||||
key: key.to_string(),
|
||||
threshold: UsageLimitNudgeThreshold::from_percent(threshold)?,
|
||||
action,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum CurrentUsageLimitNudgeState {
|
||||
Unknown,
|
||||
Inactive,
|
||||
Active(UsageLimitNudge),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum UsageLimitNudgeThreshold {
|
||||
Percent75,
|
||||
Percent90,
|
||||
}
|
||||
|
||||
impl UsageLimitNudgeThreshold {
|
||||
fn from_percent(percent: u8) -> Option<Self> {
|
||||
match percent {
|
||||
75 => Some(Self::Percent75),
|
||||
90 => Some(Self::Percent90),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_percent(self) -> u8 {
|
||||
match self {
|
||||
Self::Percent75 => 75,
|
||||
Self::Percent90 => 90,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, JsonSchema, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[ts(rename_all = "snake_case")]
|
||||
pub enum UsageLimitNudgeAction {
|
||||
AddCredits,
|
||||
Upgrade,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct RateLimitWindow {
|
||||
/// Percentage (0-100) of the window that has been consumed.
|
||||
@@ -3974,6 +4060,61 @@ mod tests {
|
||||
use tempfile::NamedTempFile;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn rate_limit_snapshot_with_nudge(
|
||||
current_usage_limit_nudge: Option<UsageLimitNudgeStatePayload>,
|
||||
) -> RateLimitSnapshot {
|
||||
RateLimitSnapshot {
|
||||
limit_id: Some("codex".to_string()),
|
||||
limit_name: None,
|
||||
primary: None,
|
||||
secondary: None,
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn current_usage_limit_nudge_state_distinguishes_unknown_inactive_and_active() {
|
||||
assert_eq!(
|
||||
rate_limit_snapshot_with_nudge(/*current_usage_limit_nudge*/ None)
|
||||
.current_usage_limit_nudge_state(),
|
||||
CurrentUsageLimitNudgeState::Unknown
|
||||
);
|
||||
assert_eq!(
|
||||
rate_limit_snapshot_with_nudge(Some(UsageLimitNudgeStatePayload::Inactive))
|
||||
.current_usage_limit_nudge_state(),
|
||||
CurrentUsageLimitNudgeState::Inactive
|
||||
);
|
||||
assert_eq!(
|
||||
rate_limit_snapshot_with_nudge(Some(UsageLimitNudgeStatePayload::Active {
|
||||
key: "near_limit_75_add_credits".to_string(),
|
||||
threshold: 75,
|
||||
action: UsageLimitNudgeAction::AddCredits,
|
||||
}))
|
||||
.current_usage_limit_nudge_state(),
|
||||
CurrentUsageLimitNudgeState::Active(UsageLimitNudge {
|
||||
key: "near_limit_75_add_credits".to_string(),
|
||||
threshold: UsageLimitNudgeThreshold::Percent75,
|
||||
action: UsageLimitNudgeAction::AddCredits,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_current_usage_limit_nudge_threshold_fails_closed() {
|
||||
assert_eq!(
|
||||
rate_limit_snapshot_with_nudge(Some(UsageLimitNudgeStatePayload::Active {
|
||||
key: "near_limit_80_upgrade".to_string(),
|
||||
threshold: 80,
|
||||
action: UsageLimitNudgeAction::Upgrade,
|
||||
}))
|
||||
.current_usage_limit_nudge_state(),
|
||||
CurrentUsageLimitNudgeState::Inactive
|
||||
);
|
||||
}
|
||||
|
||||
fn sorted_writable_roots(roots: Vec<WritableRoot>) -> Vec<(PathBuf, Vec<PathBuf>)> {
|
||||
let mut sorted_roots: Vec<(PathBuf, Vec<PathBuf>)> = roots
|
||||
.into_iter()
|
||||
|
||||
@@ -111,6 +111,7 @@ use codex_protocol::protocol::ReviewRequest;
|
||||
use codex_protocol::protocol::ReviewTarget as CoreReviewTarget;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_protocol::protocol::SessionNetworkProxyRuntime;
|
||||
use codex_protocol::protocol::UsageLimitNudgeStatePayload;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use color_eyre::eyre::ContextCompat;
|
||||
use color_eyre::eyre::Result;
|
||||
@@ -1464,6 +1465,19 @@ pub(crate) fn app_server_rate_limit_snapshot_to_core(
|
||||
credits: snapshot.credits.map(app_server_credits_snapshot_to_core),
|
||||
plan_type: snapshot.plan_type,
|
||||
rate_limit_reached_type: snapshot.rate_limit_reached_type.map(Into::into),
|
||||
current_usage_limit_nudge: match snapshot.current_usage_limit_nudge {
|
||||
codex_app_server_protocol::CurrentUsageLimitNudgeState::Unknown => None,
|
||||
codex_app_server_protocol::CurrentUsageLimitNudgeState::Inactive => {
|
||||
Some(UsageLimitNudgeStatePayload::Inactive)
|
||||
}
|
||||
codex_app_server_protocol::CurrentUsageLimitNudgeState::Active { nudge } => {
|
||||
Some(UsageLimitNudgeStatePayload::Active {
|
||||
key: nudge.key,
|
||||
threshold: nudge.threshold,
|
||||
action: nudge.action.into(),
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ pub(super) fn snapshot(percent: f64) -> RateLimitSnapshot {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -267,6 +267,7 @@ async fn rate_limit_snapshot_keeps_prior_credits_when_missing_from_headers() {
|
||||
}),
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}));
|
||||
let initial_balance = chat
|
||||
.rate_limit_snapshots_by_limit_id
|
||||
@@ -287,6 +288,7 @@ async fn rate_limit_snapshot_keeps_prior_credits_when_missing_from_headers() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}));
|
||||
|
||||
let display = chat
|
||||
@@ -326,6 +328,7 @@ async fn rate_limit_snapshot_updates_and_retains_plan_type() {
|
||||
credits: None,
|
||||
plan_type: Some(PlanType::Plus),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}));
|
||||
assert_eq!(chat.plan_type, Some(PlanType::Plus));
|
||||
|
||||
@@ -345,6 +348,7 @@ async fn rate_limit_snapshot_updates_and_retains_plan_type() {
|
||||
credits: None,
|
||||
plan_type: Some(PlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}));
|
||||
assert_eq!(chat.plan_type, Some(PlanType::Pro));
|
||||
|
||||
@@ -364,6 +368,7 @@ async fn rate_limit_snapshot_updates_and_retains_plan_type() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}));
|
||||
assert_eq!(chat.plan_type, Some(PlanType::Pro));
|
||||
}
|
||||
@@ -388,6 +393,7 @@ async fn rate_limit_snapshots_keep_separate_entries_per_limit_id() {
|
||||
}),
|
||||
plan_type: Some(PlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}));
|
||||
|
||||
chat.on_rate_limit_snapshot(Some(RateLimitSnapshot {
|
||||
@@ -402,6 +408,7 @@ async fn rate_limit_snapshots_keep_separate_entries_per_limit_id() {
|
||||
credits: None,
|
||||
plan_type: Some(PlanType::Pro),
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}));
|
||||
|
||||
let codex = chat
|
||||
@@ -455,6 +462,7 @@ async fn rate_limit_switch_prompt_skips_non_codex_limit() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
}));
|
||||
|
||||
assert!(matches!(
|
||||
|
||||
@@ -136,6 +136,7 @@ async fn status_snapshot_includes_reasoning_details() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
|
||||
@@ -317,6 +318,7 @@ async fn status_snapshot_includes_monthly_limit() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
|
||||
@@ -369,6 +371,7 @@ async fn status_snapshot_shows_unlimited_credits() {
|
||||
}),
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
let model_slug = crate::legacy_core::test_support::get_model_offline(config.model.as_deref());
|
||||
@@ -419,6 +422,7 @@ async fn status_snapshot_shows_positive_credits() {
|
||||
}),
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
let model_slug = crate::legacy_core::test_support::get_model_offline(config.model.as_deref());
|
||||
@@ -469,6 +473,7 @@ async fn status_snapshot_hides_zero_credits() {
|
||||
}),
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
let model_slug = crate::legacy_core::test_support::get_model_offline(config.model.as_deref());
|
||||
@@ -517,6 +522,7 @@ async fn status_snapshot_hides_when_has_no_credits_flag() {
|
||||
}),
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
let model_slug = crate::legacy_core::test_support::get_model_offline(config.model.as_deref());
|
||||
@@ -623,6 +629,7 @@ async fn status_snapshot_truncates_in_narrow_terminal() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
|
||||
@@ -787,6 +794,7 @@ async fn status_snapshot_shows_refreshing_limits_notice() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
|
||||
@@ -858,6 +866,7 @@ async fn status_snapshot_includes_credits_and_limits() {
|
||||
}),
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
|
||||
@@ -912,6 +921,7 @@ async fn status_snapshot_shows_unavailable_limits_message() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let captured_at = chrono::Local
|
||||
.with_ymd_and_hms(2024, 6, 7, 8, 9, 10)
|
||||
@@ -969,6 +979,7 @@ async fn status_snapshot_treats_refreshing_empty_limits_as_unavailable() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let captured_at = chrono::Local
|
||||
.with_ymd_and_hms(2024, 6, 7, 8, 9, 10)
|
||||
@@ -1040,6 +1051,7 @@ async fn status_snapshot_shows_stale_limits_message() {
|
||||
credits: None,
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
let now = captured_at + ChronoDuration::minutes(20);
|
||||
@@ -1111,6 +1123,7 @@ async fn status_snapshot_cached_limits_hide_credits_without_flag() {
|
||||
}),
|
||||
plan_type: None,
|
||||
rate_limit_reached_type: None,
|
||||
current_usage_limit_nudge: None,
|
||||
};
|
||||
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
|
||||
let now = captured_at + ChronoDuration::minutes(20);
|
||||
|
||||
Reference in New Issue
Block a user