feat(codex): redeem banked usage-limit resets via /usage reset (#64280)

OpenAI lets ChatGPT-plan Codex users bank rate-limit reset credits, but
until now they could only be redeemed from the Codex CLI/app or the
website. This wires the same backend API into Hermes:

- /usage on the openai-codex provider now shows "You have N resets
  banked - use /usage reset to activate" (parsed from the
  rate_limit_reset_credits field the /usage endpoint already returns).
- New /usage reset subcommand (CLI + gateway) redeems one banked
  credit via POST .../rate-limit-reset-credits/consume with a UUID
  idempotency key, mirroring codex-rs backend-client semantics
  (PathStyle /wham vs /api/codex, ChatGPT-Account-Id header,
  reset/nothing_to_reset/no_credit/already_redeemed outcomes).
- Guard: redemption is refused while no rate-limit window is fully
  exhausted, since a banked reset restores the FULL 5h + weekly
  allowance and spending it early wastes it. /usage reset --force
  overrides. Zero banked credits and non-codex providers are refused
  with clear messages; nothing_to_reset reports the credit was NOT
  spent.
- i18n: new gateway.usage.unknown_subcommand / reset_wrong_provider
  keys across all 16 locales; docs updated (cli.md, messaging index).

Tested with unit tests plus a real-socket E2E against a local fake
Codex backend exercising redeem/guard/force and the /usage hint.
This commit is contained in:
Teknium
2026-07-14 03:23:19 -07:00
committed by GitHub
parent 8582f35d96
commit 89bd0fba90
24 changed files with 579 additions and 7 deletions
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Geskatte konteks: ~{count} tokens"
detailed_after_first: "_(Gedetailleerde gebruik beskikbaar na die eerste agent-antwoord)_"
no_data: "Geen gebruiksdata beskikbaar vir hierdie sessie nie."
unknown_subcommand: "Onbekende /usage subopdrag: `{args}`. Probeer `/usage` of `/usage reset [--force]`."
reset_wrong_provider: "Gebankte gebruikslimiet-terugstellings is slegs beskikbaar op die openai-codex verskaffer. Skakel eers oor met `/model`."
credits:
not_logged_in: "Nie by Nous Portal aangemeld nie. Meld aan om jou kredietsaldo te sien en op te laai."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Geschätzter Kontext: ~{count} Tokens"
detailed_after_first: "_(Detaillierte Nutzung nach der ersten Agentenantwort verfügbar)_"
no_data: "Keine Nutzungsdaten für diese Sitzung verfügbar."
unknown_subcommand: "Unbekannter /usage-Unterbefehl: `{args}`. Versuche `/usage` oder `/usage reset [--force]`."
reset_wrong_provider: "Gespeicherte Limit-Resets sind nur mit dem openai-codex-Anbieter verfügbar. Wechsle zuerst mit `/model`."
credits:
not_logged_in: "Nicht bei Nous Portal angemeldet. Melde dich an, um dein Guthaben zu sehen und aufzuladen."
+2
View File
@@ -376,6 +376,8 @@ gateway:
label_estimated_context: "Estimated context: ~{count} tokens"
detailed_after_first: "_(Detailed usage available after the first agent response)_"
no_data: "No usage data available for this session."
unknown_subcommand: "Unknown /usage subcommand: `{args}`. Try `/usage` or `/usage reset [--force]`."
reset_wrong_provider: "Banked usage resets are only available on the openai-codex provider. Switch with `/model` first."
credits:
not_logged_in: "Not logged into Nous Portal. Log in to see your credit balance and top up."
+2
View File
@@ -361,6 +361,8 @@ gateway:
label_estimated_context: "Contexto estimado: ~{count} tokens"
detailed_after_first: "_(Uso detallado disponible tras la primera respuesta del agente)_"
no_data: "No hay datos de uso disponibles para esta sesión."
unknown_subcommand: "Subcomando /usage desconocido: `{args}`. Prueba `/usage` o `/usage reset [--force]`."
reset_wrong_provider: "Los reinicios de límite acumulados solo están disponibles con el proveedor openai-codex. Cambia primero con `/model`."
credits:
not_logged_in: "No has iniciado sesión en Nous Portal. Inicia sesión para ver tu saldo de créditos y recargar."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Contexte estimé : ~{count} jetons"
detailed_after_first: "_(Utilisation détaillée disponible après la première réponse de l'agent)_"
no_data: "Aucune donnée d'utilisation disponible pour cette session."
unknown_subcommand: "Sous-commande /usage inconnue : `{args}`. Essayez `/usage` ou `/usage reset [--force]`."
reset_wrong_provider: "Les réinitialisations de limite en réserve ne sont disponibles qu'avec le fournisseur openai-codex. Changez d'abord avec `/model`."
credits:
not_logged_in: "Non connecté à Nous Portal. Connecte-toi pour voir ton solde de crédits et recharger."
+2
View File
@@ -368,6 +368,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Comhthéacs measta: ~{count} comhartha"
detailed_after_first: "_(Úsáid mhionsonraithe ar fáil tar éis chéad fhreagra an ghníomhaire)_"
no_data: "Níl aon sonraí úsáide ar fáil don seisiún seo."
unknown_subcommand: "Fo-ordú /usage anaithnid: `{args}`. Bain triail as `/usage` nó `/usage reset [--force]`."
reset_wrong_provider: "Níl athshocruithe teorann bainc ar fáil ach ar an soláthraí openai-codex. Athraigh le `/model` ar dtús."
credits:
not_logged_in: "Níl tú logáilte isteach i Nous Portal. Logáil isteach chun d'iarmhéid creidmheasa a fheiceáil agus breis a chur leis."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Becsült kontextus: ~{count} token"
detailed_after_first: "_(A részletes használat az első ügynökválasz után érhető el)_"
no_data: "Ehhez a munkamenethez nincsenek elérhető használati adatok."
unknown_subcommand: "Ismeretlen /usage alparancs: `{args}`. Próbáld: `/usage` vagy `/usage reset [--force]`."
reset_wrong_provider: "A félretett limit-visszaállítások csak az openai-codex szolgáltatónál érhetők el. Válts először a `/model` paranccsal."
credits:
not_logged_in: "Nincs bejelentkezve a Nous Portalra. Jelentkezz be a kreditegyenleg megtekintéséhez és feltöltéséhez."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Contesto stimato: ~{count} token"
detailed_after_first: "_(L'uso dettagliato sarà disponibile dopo la prima risposta dell'agente)_"
no_data: "Nessun dato di utilizzo disponibile per questa sessione."
unknown_subcommand: "Sottocomando /usage sconosciuto: `{args}`. Prova `/usage` o `/usage reset [--force]`."
reset_wrong_provider: "I reset dei limiti accumulati sono disponibili solo con il provider openai-codex. Cambia prima con `/model`."
credits:
not_logged_in: "Non hai effettuato l'accesso a Nous Portal. Accedi per vedere il saldo dei crediti e ricaricare."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "推定コンテキスト: ~{count} トークン"
detailed_after_first: "_(詳細な使用状況は最初のエージェント応答後に利用可能)_"
no_data: "このセッションの使用データはありません。"
unknown_subcommand: "不明な /usage サブコマンド: `{args}`。`/usage` または `/usage reset [--force]` をお試しください。"
reset_wrong_provider: "バンクされた使用制限リセットは openai-codex プロバイダーでのみ利用できます。まず `/model` で切り替えてください。"
credits:
not_logged_in: "Nous Portal にログインしていません。ログインすると残高の確認とチャージができます。"
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "예상 컨텍스트: 약 {count} 토큰"
detailed_after_first: "_(자세한 사용량은 첫 에이전트 응답 이후 확인할 수 있습니다)_"
no_data: "이 세션에 사용 가능한 사용량 데이터가 없습니다."
unknown_subcommand: "알 수 없는 /usage 하위 명령: `{args}`. `/usage` 또는 `/usage reset [--force]`를 사용해 보세요."
reset_wrong_provider: "적립된 사용량 한도 초기화는 openai-codex 공급자에서만 사용할 수 있습니다. 먼저 `/model`로 전환하세요."
credits:
not_logged_in: "Nous Portal에 로그인되어 있지 않습니다. 로그인하면 크레딧 잔액 확인 및 충전을 할 수 있습니다."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Contexto estimado: ~{count} tokens"
detailed_after_first: "_(Utilização detalhada disponível após a primeira resposta do agente)_"
no_data: "Não há dados de utilização disponíveis para esta sessão."
unknown_subcommand: "Subcomando /usage desconhecido: `{args}`. Tente `/usage` ou `/usage reset [--force]`."
reset_wrong_provider: "Os resets de limite acumulados só estão disponíveis no provedor openai-codex. Troque primeiro com `/model`."
credits:
not_logged_in: "Você não está conectado ao Nous Portal. Faça login para ver seu saldo de créditos e recarregar."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Ориентировочный контекст: ~{count} токенов"
detailed_after_first: "_(Подробное использование доступно после первого ответа агента)_"
no_data: "Данные об использовании для этого сеанса отсутствуют."
unknown_subcommand: "Неизвестная подкоманда /usage: `{args}`. Попробуйте `/usage` или `/usage reset [--force]`."
reset_wrong_provider: "Накопленные сбросы лимитов доступны только с провайдером openai-codex. Сначала переключитесь через `/model`."
credits:
not_logged_in: "Вы не вошли в Nous Portal. Войдите, чтобы увидеть баланс кредитов и пополнить его."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Tahmini bağlam: ~{count} token"
detailed_after_first: "_(Ayrıntılı kullanım, ilk ajan yanıtından sonra kullanılabilir)_"
no_data: "Bu oturum için kullanım verisi yok."
unknown_subcommand: "Bilinmeyen /usage alt komutu: `{args}`. `/usage` veya `/usage reset [--force]` deneyin."
reset_wrong_provider: "Biriktirilen limit sıfırlamaları yalnızca openai-codex sağlayıcısında kullanılabilir. Önce `/model` ile geçiş yapın."
credits:
not_logged_in: "Nous Portal'a giriş yapılmadı. Bakiyenizi görmek ve yükleme yapmak için giriş yapın."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "Орієнтовний контекст: ~{count} токенів"
detailed_after_first: "_(Детальне використання доступне після першої відповіді агента)_"
no_data: "Дані про використання для цього сеансу відсутні."
unknown_subcommand: "Невідома підкоманда /usage: `{args}`. Спробуйте `/usage` або `/usage reset [--force]`."
reset_wrong_provider: "Накопичені скидання лімітів доступні лише з провайдером openai-codex. Спочатку перемкніться через `/model`."
credits:
not_logged_in: "Ви не ввійшли в Nous Portal. Увійдіть, щоб переглянути баланс кредитів і поповнити його."
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "預估上下文:~{count} 個 token"
detailed_after_first: "_(首次代理回應後可檢視詳細使用情況)_"
no_data: "此工作階段沒有可用的使用資料。"
unknown_subcommand: "未知的 /usage 子命令:`{args}`。請嘗試 `/usage` 或 `/usage reset [--force]`。"
reset_wrong_provider: "儲存的用量重設僅在 openai-codex 提供者上可用。請先使用 `/model` 切換。"
credits:
not_logged_in: "未登入 Nous Portal。登入後即可查看額度餘額並儲值。"
+2
View File
@@ -364,6 +364,8 @@ Future messages in this room will use that transcript until `/reset` or another
label_estimated_context: "估计上下文:~{count} 个令牌"
detailed_after_first: "_(首次代理响应后可查看详细使用情况)_"
no_data: "此会话暂无使用数据。"
unknown_subcommand: "未知的 /usage 子命令:`{args}`。请尝试 `/usage` 或 `/usage reset [--force]`。"
reset_wrong_provider: "存储的用量重置仅在 openai-codex 提供商上可用。请先使用 `/model` 切换。"
credits:
not_logged_in: "未登录 Nous Portal。登录后即可查看额度余额并充值。"