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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ next Codex session. opencodex keeps these behaviors:
| Ollama / vLLM / LM Studio (local) | `openai-chat` | key (usually blank) |
| Any OpenAI-compatible endpoint | `openai-chat` | key |

Plus DeepSeek, Groq, OpenRouter, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax, Qwen Cloud, Tencent Cloud Coding Plan, SiliconFlow, and more. See the full list with `ocx init` or in the [provider docs](https://opencodex.me/reference/configuration/).
Plus Modelsell, DeepSeek, Groq, OpenRouter, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax, Qwen Cloud, Tencent Cloud Coding Plan, SiliconFlow, and more. See the full list with `ocx init` or in the [provider docs](https://opencodex.me/reference/configuration/).

Cursor support is a staged experimental bridge: it appears in `ocx init` and the dashboard Add
Provider picker as a local config with Cursor's static public model catalog. Live
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/content/docs/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ocx init

`ocx init` walks you through:

1. **Pick a provider** — choose one of the 50 built-in registry presets or `custom` to type a base
1. **Pick a provider** — choose one of the 61 built-in registry presets or `custom` to type a base
URL and adapter.
2. **API key** — paste a key, or reference an environment variable like `${ANTHROPIC_API_KEY}`.
3. **Default model** — for key, local, and custom providers, accept the preset or enter a model id.
Expand Down
3 changes: 2 additions & 1 deletion docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ diagnostics to bug reports.

## 3. API-key catalog

opencodex ships 53 built-in presets: 42 key-based, seven OAuth, three local, and the default
opencodex ships 61 built-in presets: 50 key-based, seven OAuth, three local, and the default
ChatGPT-forward preset. The dashboard's **Add provider** picker opens a key provider's dashboard,
validates the key, and stores it. Notable entries:

Expand All @@ -168,6 +168,7 @@ validates the key, and stores it. Notable entries:
| **OpenAI (API key)** | `https://api.openai.com/v1` |
| **Anthropic (API key)** | `https://api.anthropic.com` |
| **OpenRouter** | `https://openrouter.ai/api/v1` |
| **Modelsell** | `https://modelsell.com/v1` |
| **Ollama Cloud** | `https://ollama.com/v1` |
| Google Gemini · Google Vertex AI | `https://generativelanguage.googleapis.com` · `https://aiplatform.googleapis.com` |
| Azure OpenAI | `https://{resource}.openai.azure.com/openai` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ocx init

`ocx init` は次の手順を案内します:

1. **プロバイダー選択** — 組み込みレジストリのプリセット 50 個から一つを選ぶか、`custom` を選んで
1. **プロバイダー選択** — 組み込みレジストリのプリセット 61 個から一つを選ぶか、`custom` を選んで
base URL とアダプターを直接入力します。
2. **API キー** — キーを貼り付けるか、`${ANTHROPIC_API_KEY}` のような環境変数を参照します。
3. **デフォルトモデル** — API キー、ローカル、custom プロバイダーではプリセット値を使うかモデル ID を直接入力します。
Expand Down
3 changes: 2 additions & 1 deletion docs-site/src/content/docs/ja/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Providers ページでアカウントを追加し、別アカウントをログ

## 3. API キーカタログ

opencodex v2.7.1 には組み込みプリセットが 50 個含まれています。キー方式 40、OAuth 6、ローカル 3、
opencodex には組み込みプリセットが 61 個含まれています。キー方式 50、OAuth 7、ローカル 3、
デフォルト ChatGPT 転送プリセット 1 です。ダッシュボードの **Add provider** ピッカーはキー発行ページを開き、
入力したキーを検証した後保存します。主な項目は以下のとおりです:

Expand All @@ -105,6 +105,7 @@ opencodex v2.7.1 には組み込みプリセットが 50 個含まれていま
| **OpenAI (API キー)** | `https://api.openai.com/v1` |
| **Anthropic (API キー)** | `https://api.anthropic.com` |
| **OpenRouter** | `https://openrouter.ai/api/v1` |
| **Modelsell** | `https://modelsell.com/v1` |
| **Ollama Cloud** | `https://ollama.com/v1` |
| Google Gemini · Google Vertex AI | `https://generativelanguage.googleapis.com` · `https://aiplatform.googleapis.com` |
| Azure OpenAI | `https://{resource}.openai.azure.com/openai` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ocx init

`ocx init`은 다음 과정을 안내합니다:

1. **프로바이더 선택** — 내장 레지스트리 프리셋 50개 중 하나를 고르거나, `custom`을 선택해
1. **프로바이더 선택** — 내장 레지스트리 프리셋 61개 중 하나를 고르거나, `custom`을 선택해
base URL과 adapter를 직접 입력합니다.
2. **API 키** — 키를 붙여넣거나, `${ANTHROPIC_API_KEY}`와 같은 환경 변수를 참조합니다.
3. **기본 모델** — API 키, 로컬, custom 프로바이더에서는 프리셋 값을 쓰거나 모델 id를 직접 입력합니다.
Expand Down
3 changes: 2 additions & 1 deletion docs-site/src/content/docs/ko/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Providers 페이지에서 계정을 추가하고, 다른 계정을 로그아웃

## 3. API 키 카탈로그

opencodex v2.7.1에는 빌트인 프리셋이 50개 들어 있습니다. 키 방식 40개, OAuth 6개, 로컬 3개,
opencodex에는 빌트인 프리셋이 61개 들어 있습니다. 키 방식 50개, OAuth 7개, 로컬 3개,
기본 ChatGPT 포워드 프리셋 1개입니다. 대시보드의 **Add provider** 선택기는 키 발급 페이지를 열고,
입력한 키를 검증한 뒤 저장합니다. 주요 항목은 다음과 같습니다:

Expand All @@ -105,6 +105,7 @@ opencodex v2.7.1에는 빌트인 프리셋이 50개 들어 있습니다. 키 방
| **OpenAI (API key)** | `https://api.openai.com/v1` |
| **Anthropic (API key)** | `https://api.anthropic.com` |
| **OpenRouter** | `https://openrouter.ai/api/v1` |
| **Modelsell** | `https://modelsell.com/v1` |
| **Ollama Cloud** | `https://ollama.com/v1` |
| Google Gemini · Google Vertex AI | `https://generativelanguage.googleapis.com` · `https://aiplatform.googleapis.com` |
| Azure OpenAI | `https://{resource}.openai.azure.com/openai` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ocx init

`ocx init` проведёт вас по следующим шагам:

1. **Выбор провайдера** — выберите один из 50 встроенных пресетов реестра или `custom`, чтобы
1. **Выбор провайдера** — выберите один из 61 встроенного пресета реестра или `custom`, чтобы
ввести базовый URL и адаптер вручную.
2. **API-ключ** — вставьте ключ или сошлитесь на переменную окружения вида `${ANTHROPIC_API_KEY}`.
3. **Модель по умолчанию** — для провайдеров с ключом, локальных и `custom` примите значение из
Expand Down
3 changes: 2 additions & 1 deletion docs-site/src/content/docs/ru/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Kimi и Kiro без идентификатора заменяют свой ак

## 3. Каталог API-ключей

opencodex поставляется с 53 встроенными пресетами: 42 на основе ключей, семь OAuth, три локальных и
opencodex поставляется с 61 встроенным пресетом: 50 на основе ключей, семь OAuth, три локальных и
пресет ChatGPT-форварда по умолчанию. Селектор **Add provider** в дашборде открывает страницу
выдачи ключей провайдера, проверяет ключ и сохраняет его. Наиболее заметные записи:

Expand All @@ -115,6 +115,7 @@ opencodex поставляется с 53 встроенными пресетам
| **OpenAI (API key)** | `https://api.openai.com/v1` |
| **Anthropic (API key)** | `https://api.anthropic.com` |
| **OpenRouter** | `https://openrouter.ai/api/v1` |
| **Modelsell** | `https://modelsell.com/v1` |
| **Ollama Cloud** | `https://ollama.com/v1` |
| Google Gemini · Google Vertex AI | `https://generativelanguage.googleapis.com` · `https://aiplatform.googleapis.com` |
| Azure OpenAI | `https://{resource}.openai.azure.com/openai` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ocx init

`ocx init` 会引导你完成:

1. **选择 provider** —— 从内置 registry 的 50 个预设中选择一个,或选择 `custom` 手动输入
1. **选择 provider** —— 从内置 registry 的 61 个预设中选择一个,或选择 `custom` 手动输入
base URL 和 adapter。
2. **API key** —— 粘贴一个 key,或引用一个环境变量,例如 `${ANTHROPIC_API_KEY}`。
3. **默认模型** —— 对于 API key、本地和 custom provider,可接受预设值或输入模型 id。
Expand Down
3 changes: 2 additions & 1 deletion docs-site/src/content/docs/zh-cn/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ OAuth 凭据中带有稳定账号 id 或邮箱的提供商可以保存多个登

## 3. API 密钥目录

opencodex v2.7.1 内置 50 个预设:40 个密钥预设、6 个 OAuth 预设、3 个本地预设,以及默认的
opencodex 内置 61 个预设:50 个密钥预设、7 个 OAuth 预设、3 个本地预设,以及默认的
ChatGPT 转发预设。仪表盘的 **Add provider** 选择器会打开密钥提供商的控制台,验证并保存密钥。
主要条目包括:

Expand All @@ -98,6 +98,7 @@ ChatGPT 转发预设。仪表盘的 **Add provider** 选择器会打开密钥提
| **OpenAI (API key)** | `https://api.openai.com/v1` |
| **Anthropic (API key)** | `https://api.anthropic.com` |
| **OpenRouter** | `https://openrouter.ai/api/v1` |
| **Modelsell** | `https://modelsell.com/v1` |
| **Ollama Cloud** | `https://ollama.com/v1` |
| Google Gemini · Google Vertex AI | `https://generativelanguage.googleapis.com` · `https://aiplatform.googleapis.com` |
| Azure OpenAI | `https://{resource}.openai.azure.com/openai` |
Expand Down
1 change: 1 addition & 0 deletions gui/src/provider-icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const PROVIDER_DISPLAY_NAMES: Record<string, string> = {
github: "GitHub",
"github-copilot": "GitHub Copilot",
"gitlab-duo": "GitLab Duo",
modelsell: "Modelsell",
openrouter: "OpenRouter",
"opencode-go": "OpenCode Go",
"opencode-free": "OpenCode Free",
Expand Down
2 changes: 1 addition & 1 deletion readme/README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ opencodex は 2 つの動作を分離して保持します:
| Ollama / vLLM / LM Studio(ローカル) | `openai-chat` | key(通常は空欄) |
| 任意の OpenAI 互換エンドポイント | `openai-chat` | key |

このほか DeepSeek、Groq、OpenRouter、Together、Fireworks、Cerebras、Mistral、Hugging Face、NVIDIA NIM、MiniMax、Qwen Cloud、Tencent Cloud Coding Plan、SiliconFlow などがあります。完全な一覧は `ocx init` または[プロバイダードキュメント](https://opencodex.me/ja/reference/configuration/)で確認してください。
このほか Modelsell、DeepSeek、Groq、OpenRouter、Together、Fireworks、Cerebras、Mistral、Hugging Face、NVIDIA NIM、MiniMax、Qwen Cloud、Tencent Cloud Coding Plan、SiliconFlow などがあります。完全な一覧は `ocx init` または[プロバイダードキュメント](https://opencodex.me/ja/reference/configuration/)で確認してください。

Cursor サポートは段階的な実験的ブリッジです: `ocx init` とダッシュボードの Add Provider ピッカーに Cursor の静的公開モデルカタログを持つローカル config として表示されます。Cursor アクセストークンを設定するとライブ
HTTP/2 トランスポートが有効になります。Cursor サーバー駆動のネイティブ
Expand Down
2 changes: 1 addition & 1 deletion readme/README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ opencodex는 두 가지 동작을 분리해서 유지합니다:
| Ollama / vLLM / LM Studio (로컬) | `openai-chat` | key (보통 비워둠) |
| 모든 OpenAI 호환 엔드포인트 | `openai-chat` | key |

그 외에 DeepSeek, Groq, OpenRouter, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax, Qwen Cloud, Tencent Cloud Coding Plan, SiliconFlow 등이 있습니다. 전체 목록은 `ocx init` 또는 [프로바이더 문서](https://opencodex.me/ko/reference/configuration/)에서 확인하세요.
그 외에 Modelsell, DeepSeek, Groq, OpenRouter, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax, Qwen Cloud, Tencent Cloud Coding Plan, SiliconFlow 등이 있습니다. 전체 목록은 `ocx init` 또는 [프로바이더 문서](https://opencodex.me/ko/reference/configuration/)에서 확인하세요.

## CLI

Expand Down
2 changes: 1 addition & 1 deletion readme/README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ OpenAI API-ключа и OpenRouter (`gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-lu
| Ollama / vLLM / LM Studio (локально) | `openai-chat` | key (обычно пустой) |
| Любой OpenAI-совместимый эндпоинт | `openai-chat` | key |

А также DeepSeek, Groq, OpenRouter, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax, Qwen Cloud, Tencent Cloud Coding Plan, SiliconFlow и другие. Полный список — в `ocx init` или в [документации по провайдерам](https://opencodex.me/reference/configuration/).
А также Modelsell, DeepSeek, Groq, OpenRouter, Together, Fireworks, Cerebras, Mistral, Hugging Face, NVIDIA NIM, MiniMax, Qwen Cloud, Tencent Cloud Coding Plan, SiliconFlow и другие. Полный список — в `ocx init` или в [документации по провайдерам](https://opencodex.me/reference/configuration/).

Поддержка Cursor — поэтапный экспериментальный мост: он появляется в `ocx init` и в селекторе
Add Provider панели управления как локальная конфигурация со статическим публичным каталогом
Expand Down
2 changes: 1 addition & 1 deletion readme/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ opencodex 保持两种独立行为:
| Ollama / vLLM / LM Studio(本地) | `openai-chat` | key(通常留空) |
| 任意 OpenAI 兼容端点 | `openai-chat` | key |

此外还有 DeepSeek、Groq、OpenRouter、Together、Fireworks、Cerebras、Mistral、Hugging Face、NVIDIA NIM、MiniMax、Qwen Cloud、腾讯云 Coding Plan、SiliconFlow 等等。完整列表可通过 `ocx init` 查看,或参阅 [provider 文档](https://opencodex.me/zh-cn/reference/configuration/)。
此外还有 Modelsell、DeepSeek、Groq、OpenRouter、Together、Fireworks、Cerebras、Mistral、Hugging Face、NVIDIA NIM、MiniMax、Qwen Cloud、腾讯云 Coding Plan、SiliconFlow 等等。完整列表可通过 `ocx init` 查看,或参阅 [provider 文档](https://opencodex.me/zh-cn/reference/configuration/)。

## CLI

Expand Down
13 changes: 13 additions & 0 deletions src/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,19 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
preserveReasoningContentModels: NEURALWATT_REASONING_HISTORY_MODELS,
},
{ id: "openrouter", label: "OpenRouter", adapter: "openai-chat", baseUrl: "https://openrouter.ai/api/v1", authKind: "key", featured: true, dashboardUrl: "https://openrouter.ai/keys", jawcodeBundle: "openrouter", models: ["anthropic/claude-sonnet-5", ...OPENROUTER_GPT56_MODELS], modelContextWindows: { "anthropic/claude-sonnet-5": 1_000_000, ...OPENROUTER_GPT56_CONTEXT_WINDOWS } },
{
// Modelsell exposes an OpenAI-compatible multi-model API. Keep the catalog live instead of
// freezing an aggregator-wide model list: /v1/models is scoped by the authenticated API key.
// Evidence: https://modelsell.com/docs/api-reference and issue #561.
id: "modelsell",
label: "Modelsell",
adapter: "openai-chat",
baseUrl: "https://modelsell.com/v1",
authKind: "key",
dashboardUrl: "https://modelsell.com/console/token",
liveModels: true,
note: "OpenAI-compatible multi-model gateway with live model discovery.",
},
{
// OrcaRouter: OpenAI-compatible adaptive router (api.orcarouter.ai). Model ids are
// vendor-namespaced (`<vendor>/<model>`) and pass through to the upstream as-is.
Expand Down
72 changes: 72 additions & 0 deletions tests/modelsell-provider.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { describe, expect, test } from "bun:test";
import { createOpenAIChatAdapter } from "../src/adapters/openai-chat";
import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers";
import { deriveProviderPresets } from "../src/providers/derive";
import { PROVIDER_REGISTRY } from "../src/providers/registry";
import { routeModel } from "../src/router";
import type { OcxConfig, OcxParsedRequest } from "../src/types";
import { formatProviderDisplayName, isCatalogProviderId } from "../gui/src/provider-icons";

function minimalRequest(modelId: string): OcxParsedRequest {
return {
modelId,
stream: false,
context: { messages: [{ role: "user", content: "ping" }], tools: [] },
options: {},
};
}

describe("Modelsell provider", () => {
test("publishes the fixed OpenAI-compatible endpoint and live catalog", () => {
const entry = PROVIDER_REGISTRY.find(provider => provider.id === "modelsell");
expect(entry).toMatchObject({
label: "Modelsell",
adapter: "openai-chat",
baseUrl: "https://modelsell.com/v1",
authKind: "key",
dashboardUrl: "https://modelsell.com/console/token",
liveModels: true,
});
expect(entry).not.toHaveProperty("models");
expect(entry).not.toHaveProperty("defaultModel");
});

test("derives CLI, dashboard, and key-login metadata from the registry", () => {
expect(KEY_LOGIN_PROVIDERS.modelsell).toMatchObject({
label: "Modelsell",
adapter: "openai-chat",
baseUrl: "https://modelsell.com/v1",
dashboardUrl: "https://modelsell.com/console/token",
liveModels: true,
});
expect(deriveProviderPresets().find(provider => provider.id === "modelsell")).toMatchObject({
auth: "key",
adapter: "openai-chat",
baseUrl: "https://modelsell.com/v1",
});
expect(formatProviderDisplayName("modelsell")).toBe("Modelsell");
expect(isCatalogProviderId("modelsell")).toBe(true);
});

test("routes chat completions to the canonical Modelsell endpoint with bearer auth", () => {
const config: OcxConfig = {
port: 10100,
defaultProvider: "modelsell",
providers: {
modelsell: {
adapter: "openai-chat",
baseUrl: "https://user-supplied.example/v1",
apiKey: "test-key",
liveModels: true,
},
},
};
const route = routeModel(config, "modelsell/gpt-5.4-mini");
expect(route.modelId).toBe("gpt-5.4-mini");
expect(route.provider.baseUrl).toBe("https://modelsell.com/v1");

const request = createOpenAIChatAdapter(route.provider).buildRequest(minimalRequest(route.modelId));
expect(request.url).toBe("https://modelsell.com/v1/chat/completions");
expect(request.headers).toMatchObject({ Authorization: "Bearer test-key" });
});
});
2 changes: 1 addition & 1 deletion tests/provider-registry-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function nativeTemplate(): Record<string, unknown> {
}

const EXPECTED_KEY_PROVIDER_IDS = [
"anthropic-apikey", "openai-apikey", "umans", "opencode-go", "neuralwatt", "openrouter", "orcarouter", "bizrouter", "groq", "google", "google-vertex", "azure-openai",
"anthropic-apikey", "openai-apikey", "umans", "opencode-go", "neuralwatt", "openrouter", "modelsell", "orcarouter", "bizrouter", "groq", "google", "google-vertex", "azure-openai",
"deepseek", "cerebras", "together", "fireworks", "firepass", "moonshot",
"huggingface", "nvidia", "venice", "zai", "zhipu-bigmodel", "nanogpt", "synthetic", "siliconflow", "qwen-cloud", "tencent-coding-plan",
"qianfan", "alibaba", "alibaba-token-plan", "alibaba-token-plan-intl", "parallel", "zenmux", "litellm", "ollama-cloud", "mistral",
Expand Down
Loading