diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index 33af1a1fd78..b5b02e5d216 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -2645,7 +2645,7 @@ dependencies = [ [[package]] name = "opencodex-desktop" -version = "2.74.0-preview.20260930" +version = "2.75.0-preview.20261001" dependencies = [ "base64 0.22.1", "dbus", diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml index 3c1ecdab9a8..9354e8fb2dd 100644 --- a/desktop/src-tauri/Cargo.toml +++ b/desktop/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "opencodex-desktop" -version = "2.74.0-preview.20260930" +version = "2.75.0-preview.20261001" description = "OpenCodex desktop shell" authors = ["OpenCodex contributors"] license = "MIT" diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index 00661cb7999..9d9354015bc 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "OpenCodex", - "version": "2.74.0-preview.20260930", + "version": "2.75.0-preview.20261001", "identifier": "com.opencodex.desktop", "build": { "frontendDist": "../ui", diff --git a/docs-site/src/content/docs/fr/guides/claude-code.md b/docs-site/src/content/docs/fr/guides/claude-code.md index cdc60bf5320..e2f9b6ece52 100644 --- a/docs-site/src/content/docs/fr/guides/claude-code.md +++ b/docs-site/src/content/docs/fr/guides/claude-code.md @@ -28,8 +28,7 @@ Comportement lorsque cette option est activée : - Un **429** en amont place le compte en temporisation selon `Retry-After` lorsqu'il est présent, ou selon un délai de repli, efface ses affinités et peut faire basculer la requête vers un autre compte admissible, dans les limites prévues. - L'affinité est **locale au processus** et disparaît au redémarrage du proxy. -- Les erreurs d'identification **401/403** mettent le compte en quarantaine (`needsReauth`) afin de l'exclure de la - sélection jusqu'à sa réauthentification. +- Les erreurs de renouvellement du jeton conservent la règle `needsReauth`. Un 403 confirmé lié à un abonnement ou à la facturation du compte peut déclencher un basculement avant la sortie, avec une temporisation selon `Retry-After` ou de dix minutes. Un refus d’autorisation ordinaire reste terminal. Voir la [reprise des comptes](/guides/claude-code/). - Si chaque compte éligible est en temporisation, le proxy renvoie **429** (et non 401) avec `Retry-After` lorsqu'il est connu. - La récupération, y compris le basculement 429, utilise `quotaWindow` pour classer les comptes de diff --git a/docs-site/src/content/docs/fr/reference/configuration/providers.md b/docs-site/src/content/docs/fr/reference/configuration/providers.md index 9549a6fbc94..7b285f3d9bd 100644 --- a/docs-site/src/content/docs/fr/reference/configuration/providers.md +++ b/docs-site/src/content/docs/fr/reference/configuration/providers.md @@ -246,8 +246,7 @@ rotation automatique peut déclencher des restrictions du fournisseur. | `anthropicAccountPool.stickyLimit?` | `number` | `1` | Liaisons de nouvelle session réussies conservées sur une sélection à tour de rôle. Portée 1–100. | Lorsque cette option est activée, un 429 enregistre une temporisation bornée à partir de `Retry-After` ou d'un délai de repli, puis peut -faire basculer la requête vers un autre compte. L'affinité est locale au processus et de taille bornée. Un 401/403 lié aux identifiants marque le compte -comme devant être réauthentifié. Si tous les comptes admissibles sont en temporisation, les clients reçoivent un 429 accompagné de +faire basculer la requête vers un autre compte. L'affinité est locale au processus et de taille bornée. Les erreurs de renouvellement du jeton suivent les règles de réauthentification existantes. Un 403 confirmé lié à un abonnement ou à la facturation du compte permet un basculement avant la sortie, avec une temporisation selon `Retry-After` ou de dix minutes par défaut. Un refus d’autorisation ordinaire ne déclenche pas de basculement. Si tous les comptes admissibles sont en temporisation, les clients reçoivent un 429 accompagné de `Retry-After` lorsqu'il est connu, et non une erreur d'authentification. :::caution[Expérimental] diff --git a/docs-site/src/content/docs/guides/claude-code.md b/docs-site/src/content/docs/guides/claude-code.md index 1d3394163fe..88eae2b4083 100644 --- a/docs-site/src/content/docs/guides/claude-code.md +++ b/docs-site/src/content/docs/guides/claude-code.md @@ -7,6 +7,13 @@ opencodex serves `POST /v1/messages` (plus `count_tokens`) alongside `/v1/respon Code can use every routed provider — OAuth logins, account pools, key failover and sidecars included — with zero extra auth work. +On Devin routes (including SWE-2) reached through the Messages API, text and tool calls wait +for the upstream turn to complete so its late reasoning signature can precede the answer. This prevents Claude Code's final +result from becoming empty; reasoning and keepalive progress still flow during generation. +The buffer shares the request's 32 MiB translation limit and cancellation stops the producer. +This output-order fix does not resolve Cognition's separate refusal of some generated system +text. It preserves system instructions and safety constraints. + For an Anthropic route on stored OAuth or an Anthropic API key, native Fast is available on `claude-opus-5-5`, `claude-opus-5`, and `claude-opus-4-8`: pick the model's `--fast` row (listed when Fast rows are enabled) or set `fastMode: true`. Claude Code's own `/fast` toggle is not @@ -54,8 +61,15 @@ Operational contract when enabled: whose known reset time has passed are discarded as unknown, including retained model-specific windows. Values without a known reset are preserved; missing data is never reported as zero usage. - Affinity is **process-local** (lost on proxy restart). -- **401/403** credential failures quarantine the account (`needsReauth`) so it is excluded from - selection until re-authenticated. +- A complete, structured **403** account-entitlement or billing refusal can rotate before + output. Recognized cases include no Claude Code access, an expired/inactive subscription, + and an insufficient Anthropic credit balance. The refused account loses its affinities and + cools for `Retry-After`, or ten minutes without a deadline. Generic permission, model/resource + access, policy and unrecognized errors stay terminal. Recovery respects model routes and + send limits; if no replacement is eligible, the original 403 is returned. This also works + with proactive pooling off. A 403 after assistant output starts never switches accounts. +- Token-refresh credential failures retain the existing `needsReauth` policy. Subscription + renewal does not require reauthentication, but the account waits for its cooldown to expire. - If every eligible account is cooling, the proxy returns **429** (not 401) with `Retry-After` when known. - Recovery, including 429 failover, uses `quotaWindow` to rank eligible replacements without diff --git a/docs-site/src/content/docs/guides/codex-integration.md b/docs-site/src/content/docs/guides/codex-integration.md index 27881bc9c5d..3ca45b32568 100644 --- a/docs-site/src/content/docs/guides/codex-integration.md +++ b/docs-site/src/content/docs/guides/codex-integration.md @@ -940,6 +940,8 @@ threshold. The Desktop/main account keeps its separate 98% hard lock. Set `codexPool.lowQuotaProtection` in configuration to pause accounts, record a log-and-API alert, or both; see [routing configuration](/reference/configuration/routing/#codex-pool-low-quota-protection). A pause takes effect for the next selection immediately, while saving it to disk is deferred. +Pool quota responses can authorize a pause only with valid usage and a captured credential +that is still current. A response without that proof may refresh displayed usage without pausing an account. Check this server’s authenticated `GET /api/codex-auth/low-quota-events` history for `logged` alerts or save failures. Manual resume remains in force for the current quota episode. The default alert reaches only the log and API; it does not produce a desktop or OS notification. diff --git a/docs-site/src/content/docs/guides/model-routing.md b/docs-site/src/content/docs/guides/model-routing.md index 74f08b67ec0..acb84ddd43e 100644 --- a/docs-site/src/content/docs/guides/model-routing.md +++ b/docs-site/src/content/docs/guides/model-routing.md @@ -85,6 +85,11 @@ Routing and catalog visibility are separate controls: - Fresh installs set `modelDiscovery.newModelPolicy` to `"off"`. After the first successful live fetch establishes a baseline, later arrivals are appended to `disabledModels` and carry a **NEW** dashboard badge until enabled or acknowledged. Existing installs remain `"on"` until opted in. + The policy applies before publishing newly discovered models through `/v1/models`, the dashboard, + client configuration exports, or a Codex catalog sync (including service startup). + Enabling an arrival manually keeps it enabled on later refreshes and exports. + If the running provider configuration differs from disk, model lists still apply the policy + using a temporary projection; they leave the running configuration and saved choices untouched. Use `ocx models new-policy off` globally, add `--provider ` for an override, and inspect `ocx models new-arrivals [--json]`. Failed/degraded fetches never change the baseline. Providers with a non-empty `selectedModels` (including preset mode) are already curated, so this policy is diff --git a/docs-site/src/content/docs/guides/providers.md b/docs-site/src/content/docs/guides/providers.md index 0e98269a586..3608bea9e46 100644 --- a/docs-site/src/content/docs/guides/providers.md +++ b/docs-site/src/content/docs/guides/providers.md @@ -569,6 +569,8 @@ OpenAI-compatible API gateway at [tokenlab.sh](https://tokenlab.sh/r/OPENCODEX), operated by TOKENLAB AI INC. Create a workspace [API key](https://tokenlab.sh/dashboard/api?tab=keys), then run `ocx provider add tokenlab` or select **TokenLab** in the dashboard's **Add provider** picker. +TokenLab maintains a step-by-step [OpenCodex integration guide](https://docs.tokenlab.sh/integrations/opencodex) +([한국어](https://docs.tokenlab.sh/ko/integrations/opencodex)) covering setup and per-model routing. The preset uses [Chat Completions](https://docs.tokenlab.sh/quickstart) and discovers models at `GET /v1/models?category=chat`, keeping only entries that declare `tool-use` capability. Image, video, audio, embedding and decision models are excluded from this chat preset. diff --git a/docs-site/src/content/docs/guides/web-dashboard.md b/docs-site/src/content/docs/guides/web-dashboard.md index 3645ae7c1d3..7af6c4dc4c9 100644 --- a/docs-site/src/content/docs/guides/web-dashboard.md +++ b/docs-site/src/content/docs/guides/web-dashboard.md @@ -87,9 +87,12 @@ is visible) and never forces an upstream refresh. provider-named window or prepaid credits. - A chip turns amber at 70% used and red at 90% used. - Hover or keyboard-focus a chip to see every reported window with its reset time and the time the - reading was taken. On a touch screen, the first tap shows those details. + reading was taken. The details stay open as the pointer moves from the chip into the popover, + including across the small visual gap. On a touch screen, the first tap shows those details. - Click a chip (or tap it a second time) to open that provider's Accounts tab in Providers, where - its accounts or API keys are managed. + its accounts or API keys are managed. The popover's **Open account management** link opens the + same tab; keyboard users can Tab from the chip to this link and press Enter. Escape closes the + popover and returns focus to the chip when focus was inside the popover. - The bar always stays on one line. When the chips do not fit, scroll it sideways or use the « and » buttons at either end. - Providers that report no quota window are left out. The bar is hidden when no provider reports one. diff --git a/docs-site/src/content/docs/ja/guides/claude-code.md b/docs-site/src/content/docs/ja/guides/claude-code.md index b657396615f..609ff3c85c9 100644 --- a/docs-site/src/content/docs/ja/guides/claude-code.md +++ b/docs-site/src/content/docs/ja/guides/claude-code.md @@ -7,6 +7,13 @@ opencodex は `/v1/responses` と共に `POST /v1/messages`(`count_tokens` も) Code から OAuth ログイン、アカウントプール、キーフェイルオーバー、サイドカーを含むすべてのルーティングプロバイダーを別途の 認証作業なしで使えます。 +Messages API 経由の Devin ルート(SWE-2 を含む)では、テキストとツール呼び出しの送信を +上流のターンが完了するまで待ち、遅れて届く推論署名を回答より先に送ります。これにより Claude Code の +最終結果が空になるのを防ぎます。生成中も推論と keepalive による進行通知は送信されます。 +バッファはリクエストの 32 MiB の変換上限を共有し、キャンセルすると生成処理も停止します。 +この出力順序の修正は、生成された一部のシステムテキストを Cognition が拒否する別の問題を解決するものではありません。 +システム指示と安全上の制約は保持されます。 + ## クイックスタート ```bash diff --git a/docs-site/src/content/docs/ja/guides/model-routing.md b/docs-site/src/content/docs/ja/guides/model-routing.md index 7dda1864c0a..900185715a3 100644 --- a/docs-site/src/content/docs/ja/guides/model-routing.md +++ b/docs-site/src/content/docs/ja/guides/model-routing.md @@ -83,6 +83,15 @@ model ID は変更しません。`openai-apikey/` は API key transport ブロックしません。 - プロバイダーの `selectedModels` が空でなければカタログ許可リストとして動作します。ライブモデル探索と 直接ルーティングはそのままに、カタログと `/v1/models` に公開するモデルだけ絞ります。 +- `modelDiscovery.newModelPolicy` が `"off"` の場合、最初の成功したライブ探索で基準を確立し、 + その後に追加されたモデルを `disabledModels` に入れます。これは `/v1/models`、ダッシュボード、 + クライアント設定のエクスポート、サービス起動時を含む Codex カタログ同期で公開する前に + 適用されます。手動で有効化したモデルは、その後の更新やエクスポートでも有効なままです。 + 新規インストールの既定値は `"off"`、既存のインストールは変更するまで `"on"` です。 + `ocx models new-policy off` で全体に適用し、`--provider ` で個別に上書きします。 + `ocx models new-arrivals [--json]` で追加モデルを確認できます。失敗または縮退した探索では + 基準は変わりません。`selectedModels` が空でないプロバイダーはすでに選別済みのため、 + このポリシーによる自動無効化は行いません。 - `provider.disabled: true` のプロバイダーはカタログ探索から除外されます。明示的 `provider/model` リクエストは 失敗し、`defaultModel` / `models[]` 検査でもスキップします。 - `providerContextCaps` はプロバイダーごとに Codex に表示するコンテキスト上限を指定します。 diff --git a/docs-site/src/content/docs/ja/reference/configuration/providers.md b/docs-site/src/content/docs/ja/reference/configuration/providers.md index 115a801138f..18b16e9331e 100644 --- a/docs-site/src/content/docs/ja/reference/configuration/providers.md +++ b/docs-site/src/content/docs/ja/reference/configuration/providers.md @@ -222,7 +222,7 @@ affinity を維持します。これらの戦略は provider enforcement を回 | `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` |使用量ベースのアカウント選択で使う、プロバイダー報告のキャッシュ済み使用率です。`five-hour` は従来の動作を維持します。`weekly` は週次使用量を使い、他に対象アカウントが残る間だけ 5 時間使用量が上限に達したアカウントを除外し、残らない場合はそれらへフォールバックします。`max-utilization` は判明している値のうち最も高いものを使うため、週次使用量が未取得でも 5 時間使用量を利用できます。どちらも不明なら unknown の順位付けに従います。既知の使用量は unknown より先ですが、対象がすべて unknown でも対象順の先頭を選択します。記載した 5 時間使用量による同点判定後も完全に同点なら、対象順を維持します。正常な affinity セッションを先回りして再配置することはありません。新規セッションの割り当てと、対象となる 429 代替後のルーティング復旧では、`quota` はこの期間で対象候補を直接順位付けし、`fill-first` はこの期間のしきい値と上限到達ルールを使って安定順に進み、`round-robin` はこの設定を無視します。クールダウン、フェイルオーバー上限、再認証の適格性は別のローカル状態です。アカウント別の週次使用量は、ダッシュボードのプロバイダーページで取得した後にのみ利用できます。 | | `anthropicAccountPool.stickyLimit?` | `number` | `1` |成功した新しいセッションのバインドは 1 つのラウンドロビン選択で保持されます。範囲は 1 ~ 100。 | -有効にすると、429 レコードは `Retry-After` またはデフォルトのバックオフからの制限されたクールダウンを記録し、リクエスト内でローテーションする可能性があります。アフィニティはプロセスローカルであり、サイズ制限があります。資格情報 401/403 は、アカウントに再認証が必要であることをマークします。すべての対象となるアカウントが冷却されている場合、クライアントは、既知の場合、認証エラーではなく、`Retry-After` を含む 429 を受け取ります。 +有効にすると、429 レコードは `Retry-After` またはデフォルトのバックオフからの制限されたクールダウンを記録し、リクエスト内でローテーションする可能性があります。アフィニティはプロセスローカルであり、サイズ制限があります。トークン更新の失敗は既存の再認証ルールに従います。確認済みの契約・アカウント請求の 403 は出力前に別アカウントへ切り替え、`Retry-After` または既定の10分間のクールダウンを記録します。一般的な権限拒否では切り替えません。すべての対象となるアカウントが冷却されている場合、クライアントは、既知の場合、認証エラーではなく、`Retry-After` を含む 429 を受け取ります。 :::caution[実験的] Anthropic アカウント ポリシーのリスクを理解していない限り、これは無効のままにしてください。不明な場合は、`ocx account use anthropic ` を手動で切り替えることをお勧めします。 diff --git a/docs-site/src/content/docs/ko/guides/claude-code.md b/docs-site/src/content/docs/ko/guides/claude-code.md index d45ed65f471..c33e412dc3b 100644 --- a/docs-site/src/content/docs/ko/guides/claude-code.md +++ b/docs-site/src/content/docs/ko/guides/claude-code.md @@ -7,6 +7,13 @@ opencodex는 `/v1/responses`와 함께 `POST /v1/messages`(및 `count_tokens`) Code에서 OAuth 로그인, 계정 풀, 키 장애 조치, 사이드카를 포함한 모든 라우팅 제공자를 별도의 인증 작업 없이 사용할 수 있어요. +Messages API를 통해 사용하는 Devin 경로(SWE-2 포함)에서는 늦게 도착하는 추론 서명을 답변보다 먼저 +보낼 수 있도록, 상위 제공자의 턴이 완료될 때까지 텍스트와 도구 호출 전송을 기다려요. 이렇게 하면 Claude Code의 +최종 결과가 비어 버리는 것을 막을 수 있어요. 생성 중에도 추론과 keepalive 진행 알림은 계속 전달돼요. +버퍼에는 요청의 32 MiB 변환 한도가 함께 적용되며, 요청을 취소하면 생성 작업도 중단돼요. +이 출력 순서 수정으로 Cognition이 생성된 일부 시스템 텍스트를 거부하는 별개의 문제가 해결되지는 않아요. +시스템 지시와 안전 제약은 그대로 유지해요. + ## 빠른 시작 ```bash diff --git a/docs-site/src/content/docs/ko/guides/model-routing.md b/docs-site/src/content/docs/ko/guides/model-routing.md index ac6425f3423..d20f8320c7d 100644 --- a/docs-site/src/content/docs/ko/guides/model-routing.md +++ b/docs-site/src/content/docs/ko/guides/model-routing.md @@ -82,6 +82,15 @@ fallback하지 않습니다. 막지는 않습니다. - 프로바이더의 `selectedModels`가 비어 있지 않으면 카탈로그 허용 목록으로 동작합니다. 실시간 모델 탐색과 직접 라우팅은 그대로 두고, 카탈로그와 `/v1/models`에 내보낼 모델만 줄입니다. +- `modelDiscovery.newModelPolicy`가 `"off"`이면 첫 실시간 탐색 성공 시 기준을 만들고, + 이후 추가된 모델을 `disabledModels`에 넣습니다. 이 정책은 `/v1/models`, 대시보드, + 클라이언트 설정 내보내기, 서비스 시작을 포함한 Codex 카탈로그 동기화에서 새 모델을 공개하기 + 전에 적용됩니다. 수동으로 활성화한 모델은 이후 새로고침과 내보내기에서도 활성 상태를 유지합니다. + 새 설치의 기본값은 `"off"`이며, 기존 설치는 직접 바꾸기 전까지 `"on"`을 유지합니다. + `ocx models new-policy off`로 전역 정책을 설정하고, `--provider `으로 프로바이더별 + 정책을 지정합니다. `ocx models new-arrivals [--json]`으로 새 모델을 확인할 수 있습니다. + 실패하거나 제한된 탐색은 기준을 바꾸지 않습니다. `selectedModels`가 비어 있지 않은 + 프로바이더는 이미 선택 목록을 사용하므로 이 정책으로 모델을 자동 비활성화하지 않습니다. - `provider.disabled: true`인 프로바이더는 카탈로그 탐색에서 제외됩니다. 명시적 `provider/model` 요청은 실패하고, `defaultModel` / `models[]` 검사에서도 건너뜁니다. - `providerContextCaps`는 공급자별로 Codex에 표시할 컨텍스트 상한을 지정합니다. diff --git a/docs-site/src/content/docs/ko/reference/configuration/providers.md b/docs-site/src/content/docs/ko/reference/configuration/providers.md index 9d3c91587a8..3a003a48b5a 100644 --- a/docs-site/src/content/docs/ko/reference/configuration/providers.md +++ b/docs-site/src/content/docs/ko/reference/configuration/providers.md @@ -224,7 +224,7 @@ affinity 초기화 뒤의 기존 작업도 포함될 수 있습니다. 출력 | `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | 사용량 기반 계정 선택에 사용하는, 공급자가 보고한 캐시 사용률 막대입니다. `five-hour`는 기존 동작을 유지합니다. `weekly`는 주간 막대를 사용하며 다른 사용 가능한 계정이 남아 있을 때만 5시간 막대가 소진된 계정을 건너뛰고, 아무 계정도 남지 않으면 해당 계정으로 폴백합니다. `max-utilization`은 알려진 값 중 가장 높은 값을 사용하므로 주간 사용량을 알기 전에도 5시간 사용량을 쓸 수 있고, 둘 다 모르면 unknown 순서를 따릅니다. 알려진 사용량은 unknown보다 앞서지만, 사용 가능한 계정이 모두 unknown이어도 사용 가능한 순서의 계정을 선택합니다. 앞서 설명한 5시간 사용량 동점 판정 뒤에도 완전히 같으면 사용 가능한 순서를 유지합니다. 정상 affinity 세션을 선제적으로 재배치하지 않습니다. 새 세션 배정과 가능한 429 대체 이후 라우팅 복구에서 `quota`는 이 창으로 사용 가능한 후보의 순위를 직접 매기고, `fill-first`는 이 창의 임계값과 소진 규칙에 따라 안정 순서로 이동하며, `round-robin`은 이 설정을 무시합니다. 쿨다운, failover 한도, 재인증 가능 여부는 별도의 로컬 상태로 유지됩니다. 계정별 주간 막대는 대시보드의 프로바이더 페이지에서 조회한 뒤에만 알 수 있습니다. | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | 성공한 새 세션 결속이 한 번의 라운드로빈 선택에 유지되는 횟수입니다. 범위는 1–100입니다. | -활성화되면 429 레코드가 `Retry-After` 또는 기본 backoff에서 제한된 쿨다운을 기록하고, 요청 안에서 회전할 수 있습니다. 결속은 프로세스 로컬이며 크기가 제한됩니다. 자격 증명 401/403은 해당 계정이 재인증이 필요함을 표시합니다. 적격한 계정이 모두 쿨다운 중이면, 클라이언트는 인증 오류가 아니라 알려진 경우 `Retry-After`가 포함된 429를 받습니다. +활성화되면 429 레코드가 `Retry-After` 또는 기본 backoff에서 제한된 쿨다운을 기록하고, 요청 안에서 회전할 수 있습니다. 결속은 프로세스 로컬이며 크기가 제한됩니다. 토큰 갱신 실패는 기존 재인증 규칙을 따릅니다. 확인된 구독 또는 계정 결제 403은 출력 전에 다른 계정으로 전환하며 `Retry-After` 또는 기본 10분 동안 냉각합니다. 일반 권한 거부는 전환하지 않습니다. 적격한 계정이 모두 쿨다운 중이면, 클라이언트는 인증 오류가 아니라 알려진 경우 `Retry-After`가 포함된 429를 받습니다. :::caution[실험적 기능] Anthropic 계정 정책 위험을 이해하지 못한다면 이 기능은 꺼두십시오. 확신이 없으면 수동 `ocx account use anthropic ` 전환을 우선하십시오. diff --git a/docs-site/src/content/docs/reference/configuration/providers.md b/docs-site/src/content/docs/reference/configuration/providers.md index 7a15ef01c81..33371d1104f 100644 --- a/docs-site/src/content/docs/reference/configuration/providers.md +++ b/docs-site/src/content/docs/reference/configuration/providers.md @@ -880,7 +880,7 @@ from a usable `Retry-After`, otherwise from the latest valid reset time among ra Anthropic reports as `rejected`, including weekly windows. Valid upstream deadlines are not shortened to a fixed cooldown ceiling; non-finite or unrepresentable deadlines are ignored. A refusal with no usable deadline falls back to a 60-second default backoff. Affinity is process-local -and size-bounded. Credential 401/403 marks the account as needing reauthentication. If all eligible accounts are cooling, clients receive 429 with +and size-bounded. Token-refresh credential failures retain the existing reauthentication policy. Classified pre-output account-entitlement/billing 403s clear affinity and cool the account for `Retry-After`, or ten minutes by default, before trying an eligible replacement. Generic or request-level 403s remain terminal; see [Claude account recovery](/guides/claude-code/). If all eligible accounts are cooling, clients receive 429 with `Retry-After` when known, not an authentication error. Anthropic responses also report the serving account's 5-hour and weekly utilization, and whichever diff --git a/docs-site/src/content/docs/ru/guides/claude-code.md b/docs-site/src/content/docs/ru/guides/claude-code.md index 7df5ba2bbec..7f0ef98641b 100644 --- a/docs-site/src/content/docs/ru/guides/claude-code.md +++ b/docs-site/src/content/docs/ru/guides/claude-code.md @@ -8,6 +8,14 @@ Claude Code может использовать все маршрутизиру аккаунтов, отказоустойчивое переключение (failover) ключей и сайдкары — без какой-либо дополнительной работы по аутентификации. +На маршрутах Devin (включая SWE-2), доступных через Messages API, отправка текста и вызовов +инструментов откладывается до завершения хода у провайдера, чтобы поздно поступившая подпись +рассуждений могла предшествовать ответу. Это предотвращает пустой итоговый результат в Claude Code; +рассуждения и уведомления keepalive продолжают поступать во время генерации. +Буфер использует общий с запросом лимит преобразования в 32 MiB, а отмена запроса останавливает генерацию. +Это исправление порядка вывода не решает отдельную проблему отказа Cognition принимать некоторые +сгенерированные системные тексты. Системные инструкции и ограничения безопасности сохраняются. + ## Быстрый старт ```bash diff --git a/docs-site/src/content/docs/ru/guides/model-routing.md b/docs-site/src/content/docs/ru/guides/model-routing.md index ce96fc95b8d..117802629dc 100644 --- a/docs-site/src/content/docs/ru/guides/model-routing.md +++ b/docs-site/src/content/docs/ru/guides/model-routing.md @@ -88,6 +88,15 @@ description: Как opencodex решает, какой провайдер буд - Непустой `selectedModels` провайдера — ещё один список разрешённых для каталога. Живое обнаружение и прямая маршрутизация продолжают работать; сужается только вывод в каталог и `/v1/models`. +- При `modelDiscovery.newModelPolicy: "off"` первое успешное живое обнаружение задаёт базовый + список; последующие новые модели добавляются в `disabledModels` до публикации в `/v1/models`, + дашборде, экспорте конфигурации клиентов и синхронизации каталога Codex, включая запуск сервиса. + Модель, включённая вручную, остаётся включённой при последующих обновлениях и экспортах. + Новые установки используют `"off"`; существующие сохраняют `"on"`, пока пользователь не изменит + политику. `ocx models new-policy off` задаёт общую политику; `--provider ` переопределяет + её для провайдера. `ocx models new-arrivals [--json]` показывает новые модели. Неудачное или + деградировавшее обнаружение не меняет базовый список. Для провайдеров с непустым `selectedModels` + автоматическое отключение по этой политике не применяется: их список уже отобран. - `provider.disabled: true` убирает провайдера из обнаружения каталога. Явные запросы `provider/model` завершаются ошибкой, а проверки `defaultModel` / `models[]` его пропускают. - `providerContextCaps` задаёт видимые для Codex лимиты контекста по провайдерам. diff --git a/docs-site/src/content/docs/ru/reference/configuration/providers.md b/docs-site/src/content/docs/ru/reference/configuration/providers.md index da501fe9a03..8c1f6e22c5d 100644 --- a/docs-site/src/content/docs/ru/reference/configuration/providers.md +++ b/docs-site/src/content/docs/ru/reference/configuration/providers.md @@ -258,7 +258,7 @@ reauth или эффективного порога исчерпания это Если функция включена, 429 записывает ограниченный cooldown из `Retry-After` или из default backoff и может переключить аккаунт уже внутри текущего запроса. Affinity локальна для процесса и -ограничена по размеру. Credential 401/403 помечает аккаунт как нуждающийся в переавторизации. +ограничена по размеру. Ошибки обновления токена сохраняют существующие правила повторной аутентификации. Подтверждённый 403 из-за подписки или оплаты аккаунта допускает переключение до вывода и cooldown по `Retry-After` либо на десять минут. Обычный отказ в доступе не переключает аккаунт. Если все eligible-аккаунты в cooldown, клиент получает 429 с `Retry-After`, если он известен, а не authentication error. diff --git a/docs-site/src/content/docs/tr/guides/claude-code.md b/docs-site/src/content/docs/tr/guides/claude-code.md index e88cd7f0ac7..54c702c2665 100644 --- a/docs-site/src/content/docs/tr/guides/claude-code.md +++ b/docs-site/src/content/docs/tr/guides/claude-code.md @@ -34,8 +34,7 @@ Etkinleştirildiğinde operasyonel sözleşme: içinde uygun başka bir hesaba dönebilir (sınırlı). - Bağlılık **işleme özeldir (process-local)** (proxy yeniden başlatıldığında kaybolur). -- **401/403** kimlik bilgisi hataları hesabı karantinaya alır (`needsReauth`), - böylece yeniden kimlik doğrulanana kadar seçimden hariç tutulur. +- Token yenileme hataları mevcut `needsReauth` kuralını korur. Doğrulanmış abonelik veya hesap ödeme 403 hatası çıktı başlamadan hesap değiştirebilir; soğuma `Retry-After` veya varsayılan on dakikadır. Genel izin reddi terminal kalır. Bkz. [hesap kurtarma](/guides/claude-code/). - Uygun tüm hesaplar soğutuluyorsa, proxy bilindiğinde `Retry-After` ile birlikte **429** (401 değil) döndürür. - 429 yük devretmesi dahil kurtarma, mevcut soğuma ve yük devretme sınırlarını diff --git a/docs-site/src/content/docs/tr/reference/configuration/providers.md b/docs-site/src/content/docs/tr/reference/configuration/providers.md index f9316a269f8..989ec7af701 100644 --- a/docs-site/src/content/docs/tr/reference/configuration/providers.md +++ b/docs-site/src/content/docs/tr/reference/configuration/providers.md @@ -277,8 +277,7 @@ ve otomatik rotasyon sağlayıcı kısıtlamalarını tetikleyebilir. Etkinleştirildiğinde 429, `Retry-After`'dan veya varsayılan bir geri çekilmeden sınırlı soğuma kaydeder ve istek içinde dönebilir. Bağlılık işleme özeldir ve -boyut sınırlıdır. Kimlik bilgisi 401/403, hesabı yeniden kimlik doğrulama -gerektiriyor olarak işaretler. Uygun tüm hesaplar soğuyorsa istemciler bir +boyut sınırlıdır. Token yenileme hataları mevcut yeniden kimlik doğrulama kurallarını korur. Doğrulanmış abonelik veya hesap ödeme 403 hatası çıktı başlamadan hesap değiştirebilir ve `Retry-After` veya varsayılan on dakika soğuma uygular. Genel izin reddi hesap değiştirmez. Uygun tüm hesaplar soğuyorsa istemciler bir kimlik doğrulama hatası değil, bilindiğinde `Retry-After` ile 429 alır. :::caution[Deneysel] diff --git a/docs-site/src/content/docs/troubleshooting/codex-cannot-sign-in.md b/docs-site/src/content/docs/troubleshooting/codex-cannot-sign-in.md index a5971443b34..9bff3814fdb 100644 --- a/docs-site/src/content/docs/troubleshooting/codex-cannot-sign-in.md +++ b/docs-site/src/content/docs/troubleshooting/codex-cannot-sign-in.md @@ -75,6 +75,23 @@ comment above other keys it manages, such as an injected `developer_instructions`, and deleting those will not help you sign in while costing you configuration you may want back. +Repeated standalone ownership comments do not change TOML values or routing. +Provider-table reinjection and removal consume the exact bare marker or its +`(undo: ocx restore)` form immediately above `[model_providers.opencodex]`. +Marker text inside another user comment or a multiline string is preserved; +existing comments separated from the table are not claimed by that transform. +Root routing ownership uses an exact adjacent marker at a structural root +assignment. A matching injected value recorded in the journal also proves +ownership after a Codex app rewrite drops comments. Quoting the marker in a +user comment or a multiline string does not prove ownership. Managed +`web_search` replacements record the complete original assignment, including +multiline values, so switching it back on or fallback restore can put it back. +Removal and capture validate complete assignments without converting a valid +64-bit integer into a JavaScript number. Value-based ownership still requires +successful value decoding; invalid or incomplete assignments are refused. +Fallback removal compacts document +blank lines outside multiline values, preserving blank lines within those values. + Delete the `model_catalog_json` line **with** the routing, not on its own. A `model_catalog_json` that names a file which no longer exists makes Codex fail to load its configuration at all, which looks like the same lockout for a diff --git a/docs-site/src/content/docs/zh-cn/guides/claude-code.md b/docs-site/src/content/docs/zh-cn/guides/claude-code.md index 1695a8a6ad7..efd959d4cc5 100644 --- a/docs-site/src/content/docs/zh-cn/guides/claude-code.md +++ b/docs-site/src/content/docs/zh-cn/guides/claude-code.md @@ -7,6 +7,13 @@ opencodex 在 `/v1/responses` 之外还提供 `POST /v1/messages`(以及 `coun Code 可以使用每一个已路由的提供商——包括 OAuth 登录、账户池、密钥故障转移和 sidecar—— 而无需进行任何额外的身份验证配置。 +通过 Messages API 使用 Devin 路由(包括 SWE-2)时,文本和工具调用会等到上游轮次完成后再发送, +以便将晚到的推理签名放在答案之前。这样可以避免 Claude Code 的最终结果为空; +生成期间,推理内容和 keepalive 进度通知仍会持续传输。 +缓冲区与请求共用 32 MiB 的转换上限,取消请求会停止生成过程。 +这项输出顺序修复不会解决 Cognition 拒绝部分生成的系统文本这一独立问题。 +系统指令和安全约束会保持不变。 + ## 快速开始 ```bash diff --git a/docs-site/src/content/docs/zh-cn/guides/model-routing.md b/docs-site/src/content/docs/zh-cn/guides/model-routing.md index 5bfe9d28bcb..1b51859ec35 100644 --- a/docs-site/src/content/docs/zh-cn/guides/model-routing.md +++ b/docs-site/src/content/docs/zh-cn/guides/model-routing.md @@ -72,6 +72,13 @@ transport;这些凭证路径互不 fallback。 仍保留在目录中,但会改为 `visibility: "hide"`。它**不会**拒绝对该模型的直接请求。 - 提供商的非空 `selectedModels` 是另一层目录 allowlist。实时发现和直接路由仍然有效;它只会缩小 目录和 `/v1/models` 输出的模型范围。 +- 当 `modelDiscovery.newModelPolicy` 为 `"off"` 时,首次成功的实时发现建立基准,后续新增 + 模型会加入 `disabledModels`。此策略会在通过 `/v1/models`、仪表盘、客户端配置导出或 + Codex 目录同步(包括服务启动)发布新模型之前生效。手动启用的模型在后续刷新和导出中仍保持 + 启用。新安装默认使用 `"off"`,已有安装在主动更改前保持 `"on"`。使用 + `ocx models new-policy off` 设置全局策略,添加 `--provider ` 覆盖单个提供商的设置; + 使用 `ocx models new-arrivals [--json]` 查看新增模型。失败或降级的发现不会改变基准。 + 非空 `selectedModels` 已经限定了提供商的模型列表,因此此策略不会再自动禁用模型。 - `provider.disabled: true` 会把该提供商排除在目录发现之外。显式 `provider/model` 请求会失败, `defaultModel` / `models[]` 扫描也会跳过它。 - `providerContextCaps` 为各提供商设置 Codex 可见的上下文上限。`contextCapValue` 是仪表盘的默认值, diff --git a/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md b/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md index 6f76d17d511..92225c1226d 100644 --- a/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md +++ b/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md @@ -248,7 +248,7 @@ affinity。这些策略不能规避 provider enforcement。 | `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | 基于用量选择账户时使用的、由提供商报告并缓存的用量条。`five-hour` 保持原有行为。`weekly` 使用每周用量条,并在仍有其他可用账户时跳过 5 小时用量已耗尽的账户;若没有其他账户,则回退使用这些账户。`max-utilization` 使用已知值中的最高值,因此每周用量尚不可用时仍可使用 5 小时用量;两者都未知时,账户遵循 unknown 用量排序。已知用量排在 unknown 之前,但如果所有可用账户都未知,仍会按可用顺序选择一个账户。在前述较低 5 小时用量的同分判定之后,完全相同时也保留可用顺序。不会主动重新平衡健康且已建立亲和性的会话。在新会话分配和符合条件的 429 替代后的路由恢复中,`quota` 直接按此窗口对可用候选账户排序;`fill-first` 按此窗口的阈值和耗尽规则以稳定顺序前进;`round-robin` 忽略此设置。冷却状态、故障转移上限和重新认证资格仍是独立的本地状态。各账户的每周用量只有在控制面板的提供商页面完成查询后才可用。 | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | 在一次轮询选择中保留的成功新会话绑定次数。范围 1–100。 | -启用后,429 会根据 `Retry-After` 记录有界冷却,或者使用默认退避,并且可能在同一请求内轮换。亲和性是进程本地的,并且有大小上限。凭据 401/403 会将账户标记为需要重新认证。如果所有合格账户都在冷却,客户端会在已知时收到带 `Retry-After` 的 429,而不是身份验证错误。 +启用后,429 会根据 `Retry-After` 记录有界冷却,或者使用默认退避,并且可能在同一请求内轮换。亲和性是进程本地的,并且有大小上限。令牌刷新失败保留原有重新认证规则。明确的订阅或账户计费 403 可在输出前切换账户,并按 `Retry-After` 或默认十分钟冷却;普通权限拒绝不会切换。如果所有合格账户都在冷却,客户端会在已知时收到带 `Retry-After` 的 429,而不是身份验证错误。 :::caution[Experimental] 除非你理解 Anthropic 账户策略风险,否则请保持关闭。若不确定,优先手动使用 `ocx account use anthropic ` 切换。 diff --git a/docs-site/src/content/docs/zh-tw/guides/claude-code.md b/docs-site/src/content/docs/zh-tw/guides/claude-code.md index 3d8e58d7f55..47ec6f2e7ca 100644 --- a/docs-site/src/content/docs/zh-tw/guides/claude-code.md +++ b/docs-site/src/content/docs/zh-tw/guides/claude-code.md @@ -26,7 +26,7 @@ sticky session affinity 與依用量的新工作階段選擇。它**不**控制 - 上游 **429** 會讓該帳號冷卻(有 `Retry-After` 時使用它,否則用預設 backoff)、清除其 affinity, 並可能在同一個請求內輪換到另一個合格帳號(有上限)。 - Affinity 是**程序本機**的(proxy 重啟後就會遺失)。 -- **401/403** 憑證失敗會隔離該帳號(`needsReauth`),直到重新認證前都不會參與選擇。 +- Token 更新失敗保留既有 `needsReauth` 規則。明確的訂閱或帳號計費 403 可在輸出前切換帳號,冷卻遵循 `Retry-After` 或預設十分鐘;一般權限拒絕不切換。詳見[帳號復原](/guides/claude-code/)。 - 如果每個合格帳號都在冷卻,proxy 會回傳 **429**(不是 401),並在已知時附上 `Retry-After`。 - 復原(包括 429 容錯移轉)會使用 `quotaWindow` 為合格的替代帳號排序,且不改變現有的冷卻或 容錯移轉上限;`round-robin` 會忽略 `quotaWindow`。 diff --git a/docs-site/src/content/docs/zh-tw/reference/configuration/providers.md b/docs-site/src/content/docs/zh-tw/reference/configuration/providers.md index 3771ec64272..d583396414c 100644 --- a/docs-site/src/content/docs/zh-tw/reference/configuration/providers.md +++ b/docs-site/src/content/docs/zh-tw/reference/configuration/providers.md @@ -182,7 +182,7 @@ API-key 供應商可持有字面值金鑰或環境參考。OAuth 供應商使用 | `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | 使用量型帳號選擇所採用、由供應商回報並快取的用量列。`five-hour` 保留原有行為。`weekly` 使用每週用量列,並在仍有其他可用帳號時略過 5 小時用量已用盡的帳號;若沒有其他帳號,則退回使用這些帳號。`max-utilization` 使用已知值中的最高值,因此每週用量尚未取得時仍可使用 5 小時用量;兩者都未知時,帳號遵循 unknown 用量排序。已知用量排在 unknown 之前,但若所有可用帳號都是 unknown,仍會依可用順序選出一個。完成前述較低 5 小時用量的同分判定後,完全相同時也保留可用順序。不會主動重新平衡健康且已有 affinity 的 session。在分配新 session 與符合條件的 429 替代後進行路由復原時,`quota` 直接依此視窗排序可用候選帳號;`fill-first` 依此視窗的門檻與用盡規則按穩定順序前進;`round-robin` 忽略此設定。冷卻狀態、容錯移轉上限與重新驗證資格仍是獨立的本機狀態。每個帳號的每週用量只有在 dashboard 的供應商頁面完成查詢後才可得知。 | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | 在一次 round-robin 選擇上保留的成功新 session 綁定。範圍 1–100。 | -啟用時,429 記錄來自 `Retry-After` 或預設 backoff 的有界冷卻,並可能在請求內輪換。親和性為行程本地且有界。憑證 401/403 將帳號標記為需要重新認證。若所有合格帳號都在冷卻,客戶端收到附帶已知 `Retry-After` 的 429,而非認證錯誤。 +啟用時,429 記錄來自 `Retry-After` 或預設 backoff 的有界冷卻,並可能在請求內輪換。親和性為行程本地且有界。Token 更新失敗保留原有重新認證規則。已分類的訂閱或帳號計費 403 可在輸出前切換帳號,並按 `Retry-After` 或預設十分鐘冷卻;一般權限拒絕不切換。若所有合格帳號都在冷卻,客戶端收到附帶已知 `Retry-After` 的 429,而非認證錯誤。 :::caution[實驗性] 除非你了解 Anthropic 帳號政策風險,否則保持停用。不確定時偏好手動 `ocx account use anthropic ` 切換。 diff --git a/gui/README.md b/gui/README.md index e55b038fb64..6029356e5e5 100644 --- a/gui/README.md +++ b/gui/README.md @@ -53,6 +53,18 @@ bun run setup:hooks # pre-push runs doctor when gui/ changed Fix ESLint errors first. Use `doctor` / `doctor:full` for deeper React triage. +## Quota popover hover browser regression + +```bash +cd gui +bun run build +bun run test:quota-hover +``` + +This opt-in check is not part of CI. It moves a real pointer from a quota chip into its popover in an +installed Chrome/Chromium (`CHROME_BIN` when not on PATH), which happy-dom unit tests cannot hit-test. +Rebuild after changing CSS: it uses the production CSS in `dist`. + ## Sidebar version browser regression ```bash diff --git a/gui/package.json b/gui/package.json index cd9d7fcf917..d7000ade3d2 100644 --- a/gui/package.json +++ b/gui/package.json @@ -12,7 +12,8 @@ "doctor": "npx --yes react-doctor@0.9.11 --verbose --scope changed --base origin/main --no-telemetry", "doctor:full": "npx --yes react-doctor@0.9.11 --verbose --scope full --no-telemetry", "preview": "vite preview", - "test:sidebar-version": "bun tests/sidebar-version-browser.ts" + "test:sidebar-version": "bun tests/sidebar-version-browser.ts", + "test:quota-hover": "bun tests/quota-summary-hover-browser.ts" }, "dependencies": { "@tanstack/react-virtual": "^3.14.9", diff --git a/gui/src/components/quota-summary-bar/QuotaSummaryBar.tsx b/gui/src/components/quota-summary-bar/QuotaSummaryBar.tsx index 957694475f6..5be2df49c64 100644 --- a/gui/src/components/quota-summary-bar/QuotaSummaryBar.tsx +++ b/gui/src/components/quota-summary-bar/QuotaSummaryBar.tsx @@ -28,7 +28,7 @@ interface QuotaSummaryData { const POLL_MS = 60_000; /** Gap between the chip and its fixed-position popover, and the popover's viewport margin. */ -const POPOVER_GAP = 4; +const POPOVER_GAP = 7; const VIEWPORT_MARGIN = 8; /** A « / » press pages the strip by this share of its visible width. */ const PAGE_FRACTION = 0.8; @@ -83,6 +83,12 @@ function usePopoverPlacement(open: boolean, anchorRef: RefObject { - if (event.key === "Escape") close(); + if (event.key === "Escape") { + const returnFocus = popoverRef.current?.contains(document.activeElement); + close(); + if (returnFocus) { + chipRef.current?.focus(); + setSuppressed(true); + } + } }; document.addEventListener("pointerdown", onPointer); document.addEventListener("keydown", onKey); @@ -169,19 +182,23 @@ function QuotaSummaryItem({ row, t, locale }: { row: QuotaSummaryRow; t: TFn; lo className={`quota-summary-item quota-summary-item--${row.severity}`} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave} + onFocus={event => { + if (!isKeyboardFocus(event.target)) return; + setSuppressed(false); + setFocused(true); + }} + onBlur={event => { + if (!event.currentTarget.contains(event.relatedTarget)) setFocused(false); + }} > { pointerTypeRef.current = event.pointerType; }} - onFocus={event => { - if (!isKeyboardFocus(event.currentTarget)) return; - setSuppressed(false); - setFocused(true); - }} - onBlur={() => setFocused(false)} onClick={onClick} > {row.label} @@ -191,12 +208,12 @@ function QuotaSummaryItem({ row, t, locale }: { row: QuotaSummaryRow; t: TFn; lo {t("quotaSummary.openAccounts")} {open && ( -