diff --git a/README.md b/README.md index 4cbd50f62..11e708299 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs-site/src/content/docs/getting-started/quickstart.md b/docs-site/src/content/docs/getting-started/quickstart.md index ed8d79858..1e8d9ec84 100644 --- a/docs-site/src/content/docs/getting-started/quickstart.md +++ b/docs-site/src/content/docs/getting-started/quickstart.md @@ -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. diff --git a/docs-site/src/content/docs/guides/providers.md b/docs-site/src/content/docs/guides/providers.md index 8314f0ddc..86cf5855d 100644 --- a/docs-site/src/content/docs/guides/providers.md +++ b/docs-site/src/content/docs/guides/providers.md @@ -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: @@ -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` | diff --git a/docs-site/src/content/docs/ja/getting-started/quickstart.md b/docs-site/src/content/docs/ja/getting-started/quickstart.md index dbf80359e..ce659483d 100644 --- a/docs-site/src/content/docs/ja/getting-started/quickstart.md +++ b/docs-site/src/content/docs/ja/getting-started/quickstart.md @@ -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 を直接入力します。 diff --git a/docs-site/src/content/docs/ja/guides/providers.md b/docs-site/src/content/docs/ja/guides/providers.md index f1133444c..680173a19 100644 --- a/docs-site/src/content/docs/ja/guides/providers.md +++ b/docs-site/src/content/docs/ja/guides/providers.md @@ -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** ピッカーはキー発行ページを開き、 入力したキーを検証した後保存します。主な項目は以下のとおりです: @@ -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` | diff --git a/docs-site/src/content/docs/ko/getting-started/quickstart.md b/docs-site/src/content/docs/ko/getting-started/quickstart.md index d478de1a2..df6c39f0e 100644 --- a/docs-site/src/content/docs/ko/getting-started/quickstart.md +++ b/docs-site/src/content/docs/ko/getting-started/quickstart.md @@ -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를 직접 입력합니다. diff --git a/docs-site/src/content/docs/ko/guides/providers.md b/docs-site/src/content/docs/ko/guides/providers.md index c2a3f2480..d3db724b3 100644 --- a/docs-site/src/content/docs/ko/guides/providers.md +++ b/docs-site/src/content/docs/ko/guides/providers.md @@ -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** 선택기는 키 발급 페이지를 열고, 입력한 키를 검증한 뒤 저장합니다. 주요 항목은 다음과 같습니다: @@ -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` | diff --git a/docs-site/src/content/docs/ru/getting-started/quickstart.md b/docs-site/src/content/docs/ru/getting-started/quickstart.md index 74023c3a0..de1187710 100644 --- a/docs-site/src/content/docs/ru/getting-started/quickstart.md +++ b/docs-site/src/content/docs/ru/getting-started/quickstart.md @@ -13,7 +13,7 @@ ocx init `ocx init` проведёт вас по следующим шагам: -1. **Выбор провайдера** — выберите один из 50 встроенных пресетов реестра или `custom`, чтобы +1. **Выбор провайдера** — выберите один из 61 встроенного пресета реестра или `custom`, чтобы ввести базовый URL и адаптер вручную. 2. **API-ключ** — вставьте ключ или сошлитесь на переменную окружения вида `${ANTHROPIC_API_KEY}`. 3. **Модель по умолчанию** — для провайдеров с ключом, локальных и `custom` примите значение из diff --git a/docs-site/src/content/docs/ru/guides/providers.md b/docs-site/src/content/docs/ru/guides/providers.md index bd8985942..71b899e1a 100644 --- a/docs-site/src/content/docs/ru/guides/providers.md +++ b/docs-site/src/content/docs/ru/guides/providers.md @@ -106,7 +106,7 @@ Kimi и Kiro без идентификатора заменяют свой ак ## 3. Каталог API-ключей -opencodex поставляется с 53 встроенными пресетами: 42 на основе ключей, семь OAuth, три локальных и +opencodex поставляется с 61 встроенным пресетом: 50 на основе ключей, семь OAuth, три локальных и пресет ChatGPT-форварда по умолчанию. Селектор **Add provider** в дашборде открывает страницу выдачи ключей провайдера, проверяет ключ и сохраняет его. Наиболее заметные записи: @@ -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` | diff --git a/docs-site/src/content/docs/zh-cn/getting-started/quickstart.md b/docs-site/src/content/docs/zh-cn/getting-started/quickstart.md index 4c2f69e49..be5f979d5 100644 --- a/docs-site/src/content/docs/zh-cn/getting-started/quickstart.md +++ b/docs-site/src/content/docs/zh-cn/getting-started/quickstart.md @@ -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。 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 93caa2a63..d2b812775 100644 --- a/docs-site/src/content/docs/zh-cn/guides/providers.md +++ b/docs-site/src/content/docs/zh-cn/guides/providers.md @@ -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** 选择器会打开密钥提供商的控制台,验证并保存密钥。 主要条目包括: @@ -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` | diff --git a/gui/src/provider-icons.ts b/gui/src/provider-icons.ts index 6249a91ca..d8e989ec9 100644 --- a/gui/src/provider-icons.ts +++ b/gui/src/provider-icons.ts @@ -68,6 +68,7 @@ const PROVIDER_DISPLAY_NAMES: Record = { github: "GitHub", "github-copilot": "GitHub Copilot", "gitlab-duo": "GitLab Duo", + modelsell: "Modelsell", openrouter: "OpenRouter", "opencode-go": "OpenCode Go", "opencode-free": "OpenCode Free", diff --git a/readme/README.ja.md b/readme/README.ja.md index fc8fdc020..91ebf811e 100644 --- a/readme/README.ja.md +++ b/readme/README.ja.md @@ -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 サーバー駆動のネイティブ diff --git a/readme/README.ko.md b/readme/README.ko.md index ddb900a20..f65832ffb 100644 --- a/readme/README.ko.md +++ b/readme/README.ko.md @@ -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 diff --git a/readme/README.ru.md b/readme/README.ru.md index 2f04d0634..4fbe26f16 100644 --- a/readme/README.ru.md +++ b/readme/README.ru.md @@ -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 панели управления как локальная конфигурация со статическим публичным каталогом diff --git a/readme/README.zh-CN.md b/readme/README.zh-CN.md index b4ef7a8de..dffff1e7d 100644 --- a/readme/README.zh-CN.md +++ b/readme/README.zh-CN.md @@ -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 diff --git a/src/providers/registry.ts b/src/providers/registry.ts index c55b544fb..4f0e8772e 100644 --- a/src/providers/registry.ts +++ b/src/providers/registry.ts @@ -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 (`/`) and pass through to the upstream as-is. diff --git a/tests/modelsell-provider.test.ts b/tests/modelsell-provider.test.ts new file mode 100644 index 000000000..89bbf230d --- /dev/null +++ b/tests/modelsell-provider.test.ts @@ -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" }); + }); +}); diff --git a/tests/provider-registry-parity.test.ts b/tests/provider-registry-parity.test.ts index 9dfa5e5e0..1cd5d6bf8 100644 --- a/tests/provider-registry-parity.test.ts +++ b/tests/provider-registry-parity.test.ts @@ -30,7 +30,7 @@ function nativeTemplate(): Record { } 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",