diff --git a/docs-site/src/content/docs/guides/providers.md b/docs-site/src/content/docs/guides/providers.md index 5fce1c79cc..e49aa93e63 100644 --- a/docs-site/src/content/docs/guides/providers.md +++ b/docs-site/src/content/docs/guides/providers.md @@ -24,6 +24,26 @@ Auth page can restore it: absent rows are created from the canonical preset, dis rows are re-enabled without replacing saved mode or model settings, and noncanonical `openai` rows are not offered that recovery path. +### Providers overview pool capacity + +For Codex login in Pool mode, the Providers overview shows a configured-weight estimate of the +pool's used capacity rather than presenting one arbitrary account as the provider total. The same +row also shows the current effective account's raw quota percentage, so you can distinguish the +pool estimate from the account that a new request would use. + +When reset information is available, the overview shows the next reset time and the capacity that +reset is expected to recover as `+N% pool capacity`. **Incomplete coverage** means one or more pool +accounts could not safely contribute to the estimate, for example because their plan or quota is +unknown, their reading is stale, or the account is paused or needs reauthentication. + +A **partial window coverage** warning means some included accounts reported one quota window but +not another. The overview keeps those windows separate and marks each affected window incomplete +instead of treating the missing reading as usage for that window. + +This estimate is display-only. It does not change account selection, session affinity, automatic +switching, cooldowns, or any other routing decision. Use the [Codex Auth account pool](/guides/web-dashboard/#codex-auth-and-account-pools) +for the individual account state and routing controls. + Shipped v1 configs migrate automatically to marker 2 and one option-aware row. The original config is retained once at `~/.opencodex/config.json.pre-openai-tiers-v2.bak`; restore it with `cp ~/.opencodex/config.json.pre-openai-tiers-v2.bak ~/.opencodex/config.json`. diff --git a/docs-site/src/content/docs/guides/web-dashboard.md b/docs-site/src/content/docs/guides/web-dashboard.md index d2efdfa186..660fbcfdac 100644 --- a/docs-site/src/content/docs/guides/web-dashboard.md +++ b/docs-site/src/content/docs/guides/web-dashboard.md @@ -119,6 +119,11 @@ The **Codex Auth** page manages the native ChatGPT/Codex route: values. - Pool request logs use opaque labels such as `p3fa91c`, never account emails. +The Providers overview separately summarizes Pool-mode usage as a display-only weighted capacity +estimate, alongside the effective account's raw quota and the next capacity recovery. See +[Providers overview pool capacity](/guides/providers/#providers-overview-pool-capacity) for the +visible fields, incomplete-coverage meaning, and routing boundary. + ## Starring is yours to decide, not an agent's The sidebar's star button — and the one-time question `ocx start` asks in an interactive diff --git a/docs-site/src/content/docs/ja/guides/providers.md b/docs-site/src/content/docs/ja/guides/providers.md index d55a8a843f..87cb363b8c 100644 --- a/docs-site/src/content/docs/ja/guides/providers.md +++ b/docs-site/src/content/docs/ja/guides/providers.md @@ -20,6 +20,25 @@ max input 922,000 で `*-pro` virtual ID は公開状態を維持し、wire で 組み込み `openai` が欠落または無効な場合、ダッシュボードの Accounts ピッカーと Codex Auth から復元できます。欠落行は正規プリセットから作成され、正規の無効行は保存済みのモードやモデル設定を置き換えずに再有効化され、非正規の `openai` 行にはその復元経路は出ません。 +### プロバイダー概要のプール容量 + +Codex login を Pool モードで使うと、Providers の概要には任意の 1 アカウントではなく、 +プール全体の使用済み容量の推定値が表示されます。同じ行には現在の有効アカウントの +生のクォータ使用率も表示されるため、プールの推定値と次のリクエストで使われる +アカウントの状態を区別できます。 + +リセット情報がある場合は、次のリセット時刻と、その時点で回復するプール容量が表示されます。 +**対象範囲が不完全**という警告は、プランやクォータが不明、読み取りが古い、アカウントが +一時停止中、または再認証が必要などの理由で、安全に推定へ含められないアカウントがあることを示します。 + +**期間別の対象範囲が一部不完全**という警告は、含まれるアカウントの一部が、表示中の +クォータ期間のうち一部だけを報告したことを示します。概要では各期間を分けたまま、影響を受ける +期間を個別に不完全と表示し、欠けた値をその期間の使用量として扱いません。 + +この推定値は表示専用です。アカウント選択、セッション affinity、自動切り替え、cooldown、 +その他のルーティング判断には影響しません。個別アカウントの状態とルーティング設定は +[Codex Auth のアカウントプール](/ja/guides/web-dashboard/#codex-auth-and-account-pools)を参照してください。 + 出荷版 v1 config は marker 2 の単一オプション行に自動移行されます。オリジナルは `~/.opencodex/config.json.pre-openai-tiers-v2.bak` に一度保存され、次のコマンドで復元します: `cp ~/.opencodex/config.json.pre-openai-tiers-v2.bak ~/.opencodex/config.json`。 diff --git a/docs-site/src/content/docs/ja/guides/web-dashboard.md b/docs-site/src/content/docs/ja/guides/web-dashboard.md index 912badc71e..5dd87b4bdd 100644 --- a/docs-site/src/content/docs/ja/guides/web-dashboard.md +++ b/docs-site/src/content/docs/ja/guides/web-dashboard.md @@ -83,6 +83,8 @@ Codex タスクだけに適用され、このオプション自体が委任を 選んだ強度がグローバル段階にあるか検査し、Codex は再び対象カタログ項目がその強度をサポートするか 検査します。 + + ## Codex 認証とアカウントプール **Codex 認証**ページはネイティブ ChatGPT/Codex ルートを管理します。 @@ -97,6 +99,10 @@ Codex タスクだけに適用され、このオプション自体が委任を - **クォータ更新**はアカウント使用量を即座に再読み込みし、ルーティングと画面のアカウントカードが同じ値を見るようにします。 - プールリクエストログにはメールの代わりに `p3fa91c` のような不透明なラベルを使います。 +Providers の概要は、Pool モードの使用状況を表示専用の重み付き容量推定値として別途まとめ、現在の +有効アカウントの生のクォータと次の容量回復も併せて表示します。表示される項目、不完全な対象範囲の +意味、ルーティング上の境界については、[プロバイダー概要のプール容量](/ja/guides/providers/#プロバイダー概要のプール容量)を参照してください。 + ## ダッシュボードがプロキシと通信する方式 GUI はプロキシの JSON 管理 API を使うシンクライアントです。主なエンドポイントは次のとおりです。 diff --git a/docs-site/src/content/docs/ko/guides/providers.md b/docs-site/src/content/docs/ko/guides/providers.md index ce1609aba3..84e093b67a 100644 --- a/docs-site/src/content/docs/ko/guides/providers.md +++ b/docs-site/src/content/docs/ko/guides/providers.md @@ -20,6 +20,24 @@ max input 922,000이며 `*-pro` virtual id는 공개 상태에 유지되고 wire 내장 `openai` 제공자가 없거나 비활성화된 경우 대시보드 Accounts 선택기와 Codex Auth 페이지에서 복구할 수 있습니다. 없는 항목은 정규 프리셋으로 만들고, 비활성화된 정규 항목은 저장된 모드/모델 설정을 바꾸지 않고 다시 켜며, 비정규 `openai` 항목에는 그 복구 경로를 제공하지 않습니다. +### 프로바이더 개요의 풀 용량 + +Codex 로그인을 Pool 모드로 사용하면 Providers 개요에는 임의의 한 계정이 아니라 풀 전체의 +사용 용량 추정치가 표시됩니다. 같은 행에는 현재 유효 계정의 원본 quota 사용률도 표시되므로, +풀 추정치와 다음 요청에서 사용할 계정의 상태를 구분할 수 있습니다. + +리셋 정보가 있으면 다음 리셋 시각과 그때 회복되는 풀 용량을 표시합니다. **불완전한 범위**는 +요금제나 quota를 알 수 없거나, 측정값이 오래되었거나, 계정이 일시 중지되었거나 재인증이 필요한 +등의 이유로 일부 계정을 안전하게 추정치에 포함하지 못했음을 뜻합니다. + +**일부 기간의 범위가 불완전함**은 포함된 계정 중 일부가 표시된 quota 기간을 모두 보고하지 +않았음을 뜻합니다. 개요는 각 기간을 서로 분리한 채 영향을 받은 기간을 개별적으로 불완전하다고 +표시하며, 누락된 값을 해당 기간의 사용량으로 간주하지 않습니다. + +이 추정치는 표시 전용입니다. 계정 선택, 세션 affinity, 자동 전환, cooldown 또는 다른 라우팅 +판단을 변경하지 않습니다. 개별 계정 상태와 라우팅 제어는 +[Codex Auth 계정 풀](/ko/guides/web-dashboard/#codex-auth-and-account-pools)을 참고하세요. + shipped v1 config는 marker 2의 단일 옵션 행으로 자동 이관됩니다. 원본은 `~/.opencodex/config.json.pre-openai-tiers-v2.bak`에 한 번 보존되며 다음 명령으로 복원합니다: `cp ~/.opencodex/config.json.pre-openai-tiers-v2.bak ~/.opencodex/config.json`. diff --git a/docs-site/src/content/docs/ko/guides/web-dashboard.md b/docs-site/src/content/docs/ko/guides/web-dashboard.md index 43080714e0..aedea3b6c3 100644 --- a/docs-site/src/content/docs/ko/guides/web-dashboard.md +++ b/docs-site/src/content/docs/ko/guides/web-dashboard.md @@ -83,6 +83,8 @@ Dashboard의 **Sub-agent delegation** 선택기는 `injectionModel`과 선택적 선택한 강도가 전역 단계에 있는지 검사하고, Codex는 다시 대상 카탈로그 항목이 그 강도를 지원하는지 검사합니다. + + ## Codex Auth와 계정 풀 **Codex Auth** 페이지는 네이티브 ChatGPT/Codex 라우트를 관리합니다. @@ -99,6 +101,10 @@ Dashboard의 **Sub-agent delegation** 선택기는 `injectionModel`과 선택적 - **Refresh quotas**는 계정 사용량을 즉시 다시 읽어 라우팅과 화면의 계정 카드가 같은 값을 보게 합니다. - 풀 요청 로그에는 이메일 대신 `p3fa91c` 같은 불투명한 라벨을 사용합니다. +Providers 개요는 Pool 모드 사용량을 표시 전용 가중 용량 추정치로 별도 요약하고, 현재 유효 계정의 +원본 quota와 다음 용량 회복도 함께 표시합니다. 표시 필드, 불완전한 범위의 의미, 라우팅 경계는 +[프로바이더 개요의 풀 용량](/ko/guides/providers/#프로바이더-개요의-풀-용량)을 참고하세요. + ## 스타는 에이전트가 아니라 사용자가 결정합니다 사이드바의 스타 버튼, 그리고 `ocx start`가 대화형 터미널에서 한 번 묻는 질문은 모두 diff --git a/docs-site/src/content/docs/ru/guides/providers.md b/docs-site/src/content/docs/ru/guides/providers.md index 2ef2dfdb18..64926e0a7d 100644 --- a/docs-site/src/content/docs/ru/guides/providers.md +++ b/docs-site/src/content/docs/ru/guides/providers.md @@ -25,6 +25,27 @@ description: Все способы, которыми opencodex аутентиф канонические записи включаются без замены сохранённого режима и настроек моделей, а неканонические записи `openai` этот путь восстановления не получают. +### Ёмкость пула в обзоре провайдеров + +Для входа Codex в режиме Pool обзор Providers показывает оценку использованной ёмкости всего пула, +а не показатель произвольного аккаунта. В той же строке отображается исходный процент квоты текущего +активного аккаунта, поэтому оценку пула можно отличить от состояния аккаунта, который будет использован +для следующего запроса. + +Когда доступны сведения о сбросе, обзор показывает время следующего сброса и ёмкость пула, которая +восстановится в этот момент. **Неполное покрытие** означает, что некоторые аккаунты нельзя безопасно +включить в оценку, например из-за неизвестного плана или квоты, устаревшего показания, приостановки +аккаунта либо необходимости повторной аутентификации. + +Предупреждение **о частичном покрытии окон** означает, что некоторые включённые аккаунты сообщили данные +только для части показанных окон квоты. Обзор сохраняет окна раздельными, отмечает каждое затронутое +окно как неполное и не считает отсутствующее значение использованием в этом окне. + +Эта оценка предназначена только для отображения. Она не меняет выбор аккаунта, привязку сессии, +автоматическое переключение, cooldown или другие решения маршрутизации. Состояние отдельных аккаунтов +и настройки маршрутизации описаны в разделе +[пула аккаунтов Codex Auth](/ru/guides/web-dashboard/#codex-auth-and-account-pools). + Поставляемые v1-конфигурации автоматически мигрируют на маркер 2 и одну строку с поддержкой опций. Исходная конфигурация один раз сохраняется в `~/.opencodex/config.json.pre-openai-tiers-v2.bak`; восстановить её можно командой diff --git a/docs-site/src/content/docs/ru/guides/web-dashboard.md b/docs-site/src/content/docs/ru/guides/web-dashboard.md index 9fb5622e70..bb825211c2 100644 --- a/docs-site/src/content/docs/ru/guides/web-dashboard.md +++ b/docs-site/src/content/docs/ru/guides/web-dashboard.md @@ -86,6 +86,8 @@ bun run dev:gui рассуждений Codex. API валидирует выбранный уровень глобально; Codex дополнительно валидирует уровень порождения по целевой записи каталога. + + ## Codex Auth и пулы аккаунтов Страница **Codex Auth** управляет нативным маршрутом ChatGPT/Codex: @@ -103,6 +105,11 @@ bun run dev:gui карточки аккаунтов опирались на одни и те же значения. - Логи запросов пула используют непрозрачные метки вида `p3fa91c` и никогда — email аккаунтов. +Обзор Providers дополнительно сводит использование Pool-режима в оценочную взвешенную ёмкость +только для отображения, рядом с исходной квотой текущего активного аккаунта и следующим восстановлением +ёмкости. Поля, значение неполного покрытия и границы маршрутизации описаны в разделе +[ёмкость пула в обзоре провайдеров](/ru/guides/providers/#ёмкость-пула-в-обзоре-провайдеров). + ## Как дашборд взаимодействует с прокси GUI — это тонкий клиент поверх JSON-API управления прокси. Полезные эндпоинты: diff --git a/docs-site/src/content/docs/zh-cn/guides/providers.md b/docs-site/src/content/docs/zh-cn/guides/providers.md index 2680857dc2..b46f8a7f28 100644 --- a/docs-site/src/content/docs/zh-cn/guides/providers.md +++ b/docs-site/src/content/docs/zh-cn/guides/providers.md @@ -19,6 +19,22 @@ bare `gpt-5.6-sol` 遵循 Providers 页面中的 Pool/Direct 选项, 若内置 `openai` 提供商缺失或已禁用,可在仪表盘 Accounts 选择器或 Codex Auth 页面恢复:缺失行会从规范预设创建,已禁用的规范行会在不替换已保存模式/模型设置的情况下重新启用,非规范的 `openai` 行不会提供该恢复路径。 +### 提供商概览中的账户池容量 + +Codex 登录使用 Pool 模式时,Providers 概览显示整个账户池的已用容量估算,而不是任意一个 +账户的数值。同一行还会显示当前有效账户的原始配额使用率,便于区分账户池估算与下一次请求 +将使用的账户状态。 + +如果有重置信息,概览会显示下一次重置时间以及届时恢复的账户池容量。**覆盖不完整**表示某些 +账户无法安全计入估算,例如套餐或配额未知、读数过旧、账户已暂停或需要重新认证。 + +**部分窗口覆盖不完整**表示某些已计入账户只报告了部分显示的配额窗口。概览会保持各窗口相互 +独立,逐一标记受影响的窗口,并且不会把缺失值当作该窗口的使用量。 + +此估算仅用于显示,不会改变账户选择、会话关联、自动切换、cooldown 或任何其他路由决策。 +各账户状态和路由控制请参阅 +[Codex Auth 账户池](/zh-cn/guides/web-dashboard/#codex-auth-and-account-pools)。 + shipped v1 配置自动迁移到 marker 2 的单一选项行。原配置只保留一次到 `~/.opencodex/config.json.pre-openai-tiers-v2.bak`;恢复命令: `cp ~/.opencodex/config.json.pre-openai-tiers-v2.bak ~/.opencodex/config.json`。 diff --git a/docs-site/src/content/docs/zh-cn/guides/web-dashboard.md b/docs-site/src/content/docs/zh-cn/guides/web-dashboard.md index 7a09d8b061..4a3eb55053 100644 --- a/docs-site/src/content/docs/zh-cn/guides/web-dashboard.md +++ b/docs-site/src/content/docs/zh-cn/guides/web-dashboard.md @@ -77,6 +77,8 @@ Dashboard 的 **Sub-agent delegation** 选择器会保存 `injectionModel`,以 选择器会列出已启用的原生与路由模型,以及全局 Codex reasoning 阶梯。API 会先验证所选强度是否 属于全局阶梯;Codex 仍会根据目标目录条目再次校验该 spawn 强度。 + + ## Codex Auth 与账号池 **Codex Auth** 页面用于管理原生 ChatGPT/Codex 路由: @@ -91,6 +93,10 @@ Dashboard 的 **Sub-agent delegation** 选择器会保存 `injectionModel`,以 - **Refresh quotas** 会立即重新读取账号 usage,使路由逻辑与页面上的账号卡片使用同一份数据。 - 池账号的请求日志使用 `p3fa91c` 这类不透明标签,不会记录账号邮箱。 +Providers 概览会单独汇总 Pool 模式的显示专用加权容量估算,并同时显示当前有效账户的原始配额和 +下一次容量恢复。可见字段、覆盖不完整的含义以及路由边界,请参阅 +[提供商概览中的账户池容量](/zh-cn/guides/providers/#提供商概览中的账户池容量)。 + ## 仪表盘如何与代理通信 GUI 是代理 JSON 管理 API 之上的轻量客户端。常用 endpoint 包括: diff --git a/gui/src/components/QuotaBars.tsx b/gui/src/components/QuotaBars.tsx index 8669deafb1..da782d0d02 100644 --- a/gui/src/components/QuotaBars.tsx +++ b/gui/src/components/QuotaBars.tsx @@ -7,7 +7,15 @@ import { type AccountQuota, normalizeQuotaForPlan } from "../codex-quota-utils"; /* Helpers are co-located with QuotaBars for overview sorting / stacked layout. */ /* eslint-disable react-refresh/only-export-components */ -export type QuotaBarRow = { label: string; limitLabel: string; percent: number; resetAt?: number }; +export type QuotaWindowKey = "fiveHour" | "weekly" | "monthly"; +export type QuotaBarRow = { + windowKey?: QuotaWindowKey; + customLabel?: string; + label: string; + limitLabel: string; + percent: number; + resetAt?: number; +}; /** * Window ordering is computed from RAW wire identities BEFORE localization @@ -43,6 +51,7 @@ export function buildQuotaRows(quota: AccountQuota | null, plan: string | null | ranked.push({ rank: 0, row: { + windowKey: "fiveHour", label: t("codexAuth.fiveHour"), limitLabel: t("quota.fiveHourLimit"), percent: displayQuota.fiveHourPercent, @@ -54,6 +63,7 @@ export function buildQuotaRows(quota: AccountQuota | null, plan: string | null | ranked.push({ rank: 1, row: { + windowKey: "weekly", label: t("codexAuth.weekly"), limitLabel: t("quota.weeklyLimit"), percent: displayQuota.weeklyPercent, @@ -65,6 +75,7 @@ export function buildQuotaRows(quota: AccountQuota | null, plan: string | null | ranked.push({ rank: 4, row: { + windowKey: "monthly", label: t("codexAuth.monthly"), limitLabel: t("quota.monthlyLimit"), percent: displayQuota.monthlyPercent, @@ -76,7 +87,13 @@ export function buildQuotaRows(quota: AccountQuota | null, plan: string | null | const localized = localizeCustomQuotaLabel(w.label, t); ranked.push({ rank: rawCustomWindowRank(w.label), - row: { label: localized, limitLabel: localized, percent: w.percent, resetAt: w.resetAt }, + row: { + customLabel: w.label, + label: localized, + limitLabel: localized, + percent: w.percent, + resetAt: w.resetAt, + }, }); } return ranked.sort((a, b) => a.rank - b.rank).map(entry => entry.row); @@ -138,7 +155,17 @@ function barFillStyle(percent: number): CSSProperties { return { ["--bar-scale" as string]: String(barWidth(percent) / 100) }; } -export default function QuotaBars({ quota, plan, threshold, t, className, layout = "compact", pending = false }: { +export default function QuotaBars({ + quota, + plan, + threshold, + t, + className, + layout = "compact", + pending = false, + incompleteWindowKeys, + incompleteCustomWindowLabels, +}: { quota: AccountQuota | null; plan?: string | null; threshold: number; @@ -151,6 +178,9 @@ export default function QuotaBars({ quota, plan, threshold, t, className, layout * bar slot so deferred fill does not shove the page down. */ pending?: boolean; + /** Optional overview-only coverage status. Other quota surfaces remain unchanged when omitted. */ + incompleteWindowKeys?: ReadonlySet; + incompleteCustomWindowLabels?: ReadonlySet; }) { const { locale } = useI18n(); const rows = buildQuotaRows(quota, plan, t); @@ -201,7 +231,16 @@ export default function QuotaBars({ quota, plan, threshold, t, className, layout return (
{rows.map(row => ( - + ))}
); @@ -254,11 +293,12 @@ function QuotaRow({ label, percent, resetAt, threshold, t, locale }: { ); } -function StackedQuotaRow({ row, threshold, t, locale }: { +function StackedQuotaRow({ row, threshold, t, locale, incomplete }: { row: QuotaBarRow; threshold: number; t: TFn; locale: Locale; + incomplete: boolean; }) { const exhausted = isQuotaExhausted(row.percent); const warn = isQuotaWarn(row.percent, threshold); @@ -267,7 +307,19 @@ function StackedQuotaRow({ row, threshold, t, locale }: { return (
- {row.limitLabel} + + {row.limitLabel} + {incomplete && ( + + {t("pws.capacity.windowPartial")} + + )} + {resetText}
diff --git a/gui/src/components/provider-workspace/ProviderOverviewDashboard.tsx b/gui/src/components/provider-workspace/ProviderOverviewDashboard.tsx index b4d188da50..b2741a851f 100644 --- a/gui/src/components/provider-workspace/ProviderOverviewDashboard.tsx +++ b/gui/src/components/provider-workspace/ProviderOverviewDashboard.tsx @@ -7,7 +7,12 @@ import { useMemo } from "react"; import { useT, useI18n } from "../../i18n/shared"; import { IconAlert, IconChevron } from "../../icons"; import type { WorkspaceSections, WorkspaceItem } from "../../provider-workspace/catalog"; -import { accountQuotaFromReport, type ProviderQuotaReportView } from "../../provider-workspace/report"; +import { + accountQuotaFromReport, + capacityAggregationFromReport, + type CapacityWindowView, + type ProviderQuotaReportView, +} from "../../provider-workspace/report"; import { attentionReasonKey, buildAttentionItems, @@ -17,7 +22,7 @@ import { relativeTimeLabelsFromT, type ProviderUsageTotals, } from "../../provider-workspace/usage"; -import { maxQuotaUtilisation } from "../QuotaBars"; +import { maxQuotaUtilisation, type QuotaWindowKey } from "../QuotaBars"; import { ProviderIcon } from "./ProviderRail"; import { formatProviderDisplayName } from "../../provider-icons"; import QuotaBars from "../QuotaBars"; @@ -64,8 +69,9 @@ export default function ProviderOverviewDashboard({ for (const item of allItems) { const report = quotaReports[item.name]; const quota = report ? accountQuotaFromReport(report) : null; - if (report && quota) { - result.push({ item, report, urgency: maxQuotaUtilisation(quota) }); + const aggregation = report ? capacityAggregationFromReport(report) : null; + if (report && (quota || aggregation?.presentation === "coverage-only")) { + result.push({ item, report, urgency: quota ? maxQuotaUtilisation(quota) : -1 }); } } return result.sort((a, b) => b.urgency - a.urgency || a.item.name.localeCompare(b.item.name)); @@ -162,13 +168,7 @@ export default function ProviderOverviewDashboard({