Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ The ChatGPT passthrough catalog also layers in the bare GPT-5.6 Sol/Terra/Luna s

## 2. Account login (OAuth)

Seven provider presets use OAuth login — plus GitHub Copilot via an experimental unofficial
Eight provider presets use OAuth login — plus GitHub Copilot via an experimental unofficial
device-flow bridge. opencodex stores their credentials in
`~/.opencodex/auth.json` and refreshes them automatically. `chatgpt` is also accepted by the login
CLI; it acquires a ChatGPT credential while creating a `forward`-mode provider entry.
Expand All @@ -98,6 +98,7 @@ CLI; it acquires a ChatGPT credential while creating a `forward`-mode provider e
ocx login xai # xAI Grok
ocx login anthropic # Anthropic Claude (Pro/Max)
ocx login kimi # Moonshot Kimi
ocx login nous # Nous Portal (device grant; free + paid models)
ocx login kiro # import kiro-cli credentials (or token fallback)
ocx login google-antigravity
ocx login cursor # standalone Cursor PKCE login
Expand All @@ -112,6 +113,7 @@ ocx logout <provider>
| `xai` | `openai-chat` | `https://api.x.ai/v1` | Live-first Grok catalog; `grok-4.5` is the fallback default. |
| `anthropic` | `anthropic` | `https://api.anthropic.com` | Claude models; live model list fetched from `/v1/models`. |
| `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 coding models. |
| `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research subscription gateway (same backend Hermes Agent uses). Device-grant login against `portal.nousresearch.com`; the access token is the per-request inference JWT. Mixed paid + `:free` model catalog (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, ...) discovered live from the signed-in account. Refresh tokens are single-use and rotated on every refresh. |
| `kiro` | `kiro` | `https://runtime.us-east-1.kiro.dev` | Initial login imports the installed, signed-in `kiro-cli` session (on Unix, install with `curl -fsSL https://cli.kiro.dev/install | bash`; on Windows PowerShell, use `irm 'https://cli.kiro.dev/install.ps1' | iex`; then run `kiro-cli login`). **Add account** logs `kiro-cli` out, starts a fresh browser login that switches the account used by `kiro-cli`, and stores account-scoped profile metadata. Existing OpenCodex accounts are preserved, and cancellation or failure restores the previous `kiro-cli` session. |
| `google-antigravity` | `google` | `https://daily-cloudcode-pa.googleapis.com` | Google OAuth over the Cloud Code Assist wire. Live discovery uses CCA's authenticated `v1internal:fetchAvailableModels` endpoint and publishes the agent models available to the signed-in account; the maintained catalog remains the fallback. |
| `cursor` | `cursor` | `https://api2.cursor.sh` | Experimental PKCE login, live HTTP/2 transport, and account-filtered model discovery. |
Expand Down Expand Up @@ -506,4 +508,3 @@ Providers with a live probe: OpenAI/Codex, Anthropic, xAI, Cursor, Kimi,
Google Antigravity, OpenRouter, DeepSeek, ClinePass, Z.AI, MiniMax,
Moonshot, Venice, Synthetic, DeepInfra, Neuralwatt, and any a6api-backed
custom provider.

2 changes: 1 addition & 1 deletion docs-site/src/content/docs/ja/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Codex login を Pool モードで使うと、Providers の概要には任意の
| --- | --- | --- |
| `key` | API キーを送信します(`Authorization: Bearer …`、またはアダプターにより `x-api-key` / `api-key`)。キーはリテラルまたは `${ENV_VAR}` 参照です。 | 大半のプロバイダー。 |
| `forward` | **受け取った Codex 認証ヘッダーを**プロバイダーにそのまま中継します — キーを保存しません。ChatGPT ログインのパススルーです。 | OpenAI(`openai-responses` アダプター)。 |
| `oauth` | 保存された OAuth アクセストークンを読み込み bearer キーとして使い、期限切れ前に自動更新します。 | xAI、Anthropic、Kimi、Kiro、Google Antigravity、Cursor。 |
| `oauth` | 保存された OAuth アクセストークンを読み込み bearer キーとして使い、期限切れ前に自動更新します。 | xAI、Anthropic、Kimi、Kiro、Google Antigravity、Cursor、Nous Portal。 |

[`retryOn429`](/ja/reference/configuration/)(同一キーでの 429 リトライ)は API キー プロバイダー
(`authMode: "key"`)のみに適用されます。OAuth・forward・ローカル プリセットは除外されます —
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/ko/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ shipped v1 config는 marker 2의 단일 옵션 행으로 자동 이관됩니다.
| --- | --- | --- |
| `key` | API 키를 전송합니다(`Authorization: Bearer …`, 또는 어댑터에 따라 `x-api-key` / `api-key`). 키는 리터럴이거나 `${ENV_VAR}` 참조일 수 있습니다. | 대부분의 프로바이더. |
| `forward` | **수신된 Codex 인증 헤더를** 프로바이더에 그대로 중계합니다 — 키를 저장하지 않습니다. ChatGPT 로그인 패스스루입니다. | OpenAI (`openai-responses` 어댑터). |
| `oauth` | 저장된 OAuth 액세스 토큰을 불러와 bearer 키로 사용하며, 만료 전에 자동 갱신합니다. | xAI, Anthropic, Kimi, Kiro, Google Antigravity, Cursor. |
| `oauth` | 저장된 OAuth 액세스 토큰을 불러와 bearer 키로 사용하며, 만료 전에 자동 갱신합니다. | xAI, Anthropic, Kimi, Kiro, Google Antigravity, Cursor, Nous Portal. |

[`retryOn429`](/ko/reference/configuration/)(동일 키 429 재시도)는 API 키 프로바이더
(`authMode: "key"`)에만 적용됩니다. OAuth·forward·로컬 프리셋은 제외됩니다 — 같은 토큰을
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/ru/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ description: Все способы, которыми opencodex аутентиф
| --- | --- | --- |
| `key` | Отправляет ваш API-ключ (`Authorization: Bearer …` либо `x-api-key` / `api-key` в зависимости от адаптера). Ключ может быть литералом или ссылкой вида `${ENV_VAR}`. | Большинство провайдеров. |
| `forward` | Передаёт провайдеру **входящие заголовки аутентификации Codex** без изменений — ключ не хранится. Это сквозной режим (passthrough) входа через ChatGPT. | OpenAI (адаптер `openai-responses`). |
| `oauth` | Берёт сохранённый OAuth-токен доступа (автоматически обновляется до истечения срока) и использует его как bearer-ключ. | xAI, Anthropic, Kimi, Kiro, Google Antigravity, Cursor, GitHub Copilot. |
| `oauth` | Берёт сохранённый OAuth-токен доступа (автоматически обновляется до истечения срока) и использует его как bearer-ключ. | xAI, Anthropic, Kimi, Kiro, Google Antigravity, Cursor, GitHub Copilot, Nous Portal. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Complete the Russian Nous documentation.

This line adds Nous Portal to the OAuth provider list, but docs-site/src/content/docs/ru/guides/providers.md still says “Семь пресетов” on Lines 96-99, omits ocx login nous from Lines 101-112, and omits the nous provider row from Lines 114-122.

Update those sections to match the English source: use eight OAuth presets, add the device-grant login command, and document the openai-chat adapter, inference endpoint, live paid/free model discovery, and rotated refresh tokens.

As per path instructions, translated provider documentation must not contradict the English source.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs-site/src/content/docs/ru/guides/providers.md` at line 63, Update the
Russian providers documentation sections around the preset count, login
commands, and provider table to match the English source: change the OAuth total
to eight, add the ocx login nous device-grant command, and add the Nous provider
row covering the openai-chat adapter, inference endpoint, live paid/free model
discovery, and rotated refresh tokens.

Source: Path instructions


Повтор при 429 на том же ключе ([`retryOn429`](/ru/reference/configuration/)) применим только к
провайдерам с API-ключом (`authMode: "key"`). Пресеты OAuth, forward и local исключены — их
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/zh-cn/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ shipped v1 配置自动迁移到 marker 2 的单一选项行。原配置只保
| --- | --- | --- |
| `key` | 发送你的 API 密钥(`Authorization: Bearer …`,或按 adapter 使用 `x-api-key` / `api-key`)。密钥可以是字面值,也可以是 `${ENV_VAR}` 引用。 | 大多数提供商。 |
| `forward` | 将**你传入的 Codex 认证请求头**原样转发给提供商——不存储任何密钥。这就是 ChatGPT 登录的透传方式。 | OpenAI(`openai-responses` adapter)。 |
| `oauth` | 读取已存储的 OAuth 访问令牌(过期前自动刷新),并将其用作 bearer 密钥。 | xAI、Anthropic、Kimi、Kiro、Google Antigravity、Cursor。 |
| `oauth` | 读取已存储的 OAuth 访问令牌(过期前自动刷新),并将其用作 bearer 密钥。 | xAI、Anthropic、Kimi、Kiro、Google Antigravity、Cursor、Nous Portal。 |

[`retryOn429`](/zh-cn/reference/configuration/)(同 key 的 429 重试)仅适用于 API-key 提供商
(`authMode: "key"`)。OAuth、forward 与本地预设均被排除——同一 token 绝不可重放,本地运行时
Expand Down
13 changes: 13 additions & 0 deletions src/oauth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { getAccountCredential, getAccountSet, removeAccount, saveAccountCredenti
import { loginXai, refreshXaiToken, XAI_LOCAL_CLI_DETACH_WARNING, XaiTokenRequestError } from "./xai";
import { ANTHROPIC_OAUTH_BETA, AnthropicTokenError, loginAnthropic, refreshAnthropicToken } from "./anthropic";
import { loginKimi, refreshKimiToken } from "./kimi";
import { loginNous, NousTokenError, refreshNousToken } from "./nous";
import { loginChatGPT, refreshChatGPTToken } from "./chatgpt";
import { loginAntigravity, refreshAntigravityToken } from "./google-antigravity";
import { loginCursor, refreshCursorToken } from "./cursor";
Expand Down Expand Up @@ -194,6 +195,17 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderDef> = {
providerConfig: oauthConfig("kimi"),
defaultModel: oauthDefaultModel("kimi"),
},
nous: {
// Nous Portal device-grant login (RFC 8628) against portal.nousresearch.com.
// The access token is the per-request inference JWT (scope inference:invoke).
// Refresh tokens are single-use and rotated server-side on every refresh:
// keep background refresh lazy-only (the default) so concurrent refreshes
// cannot trip the Portal's token-reuse revocation.
login: (ctrl) => loginNous(ctrl),
refresh: (rt, signal) => refreshNousToken(rt, signal),
providerConfig: oauthConfig("nous"),
defaultModel: oauthDefaultModel("nous"),
},
kiro: {
login: (ctrl, opts) => loginKiro(ctrl, { forceLogin: opts?.forceLogin }),
refresh: (rt, signal, credential) => refreshKiroToken(rt, signal, credential),
Expand Down Expand Up @@ -436,6 +448,7 @@ function terminal(error:unknown):boolean{
if(error instanceof XaiTokenRequestError)return ["invalid_grant","refresh_token_reused","revoked_token"].includes(error.oauthError??"");
if(error instanceof AnthropicTokenError)return (error.httpStatus===400||error.httpStatus===401)&&["invalid_grant","refresh_token_reused","revoked","revoked_token","refresh_token_revoked"].includes(error.oauthError??"");
if(error instanceof KiroTokenRefreshError)return (error.httpStatus===400||error.httpStatus===401)&&error.oauthError!==undefined;
if(error instanceof NousTokenError)return ["invalid_grant","refresh_token_reused","revoked","revoked_token","expired_token"].includes(error.oauthError??"");
return isTerminalRefreshError(error);
}
function authoritative(stored:OAuthCredentials,active:boolean,now:()=>number):OAuthCredentials{if(stored.source!=="local-cli")return stored;const disk=detectGrokCliToken();if(!disk)return stored;const allowed=isSameGrokIdentity(stored,disk)||(active&&!hasComparableGrokIdentity(stored,disk));return allowed&&shouldAdoptGrokGeneration(stored,disk,now(),REFRESH_SKEW_MS)?disk:stored;}
Expand Down
Loading
Loading