fix(tui): gate the OrcaRouter offer by region and disclose its terms (§46)

Hide the OrcaRouter offer row and F7 shortcut in zh-Hans (mainland), keep
it for zh-Hant and other locales, and disclose the offer terms in the
picker and docs/PROVIDERS.md. Localized in all 15 packs. Re-derived the
web agent-docs JSON from HEAD plus this patch only.

Patch authored by the Living Codewhale logo session.
Verified on the Boat farm (Linux, local tests, base 5ba1aa63 overlay):
codewhale-localization 55 passed, 0 failed; codewhale-tui --lib
provider_picker model_picker orca_offer 202 passed, 0 failed. Rerun on
this exact tree follows before push.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
CodeWhale BotandClaude Opus 5.5 committed 2026-11-07 16:56:27 -08:00
1 parent deefd0e0f8
commit b3d18fe6bc
21 files changed
+94 -27

No files matched your search

+3
View File
@@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- **OrcaRouter offer:** no longer shown when Codewhale is in Simplified Chinese
or your computer is set to mainland China, and its note now says the link is
part of a referral campaign.
- **Website:** recovered warm paper, clear-blue actions and original drawn water accents; added Computer Use and automatically refreshed terminal/plugin release links; shortened copy, clarified contribution paths and checked setup guidance against published versions.
## [0.10.3] - 2026-11-06
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Recomanat",
"OrcaRouterOfferAction": "Mostra l’oferta d’OrcaRouter a /provider o /model",
"OrcaRouterOfferBody": "Aconsegueix un 30% de crèdit addicional per a DeepSeek V4.1 Flash en les recàrregues amb l’oferta Codewhale × OrcaRouter. Consulta les condicions vigents a la pàgina de l’oferta.",
"OrcaRouterOfferDisclosure": "Codewhale rep una comissió de recomanació d’OrcaRouter.",
"OrcaRouterOfferDisclosure": "Aquest enllaç forma part d’una campanya de referits; Codewhale pot rebre una recompensa per les recàrregues fetes a través seu.",
"ShellWaitNoActive": "No s'està esperant cap ordre de l'intèrpret.",
"ShellWaitInteractive": "Les ordres interactives no poden continuar en segon pla. Cancel·la el torn o espera que acabin.",
"ShellWaitUnavailable": "Aquesta eina no pot continuar en segon pla. Cancel·la el torn o espera que acabi.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Empfohlen",
"OrcaRouterOfferAction": "OrcaRouter-Angebot in /provider oder /model anzeigen",
"OrcaRouterOfferBody": "Erhalte mit dem Angebot Codewhale × OrcaRouter bei Aufladungen 30% zusätzliches Guthaben für DeepSeek V4.1 Flash. Die aktuellen Bedingungen stehen auf der Angebotsseite.",
"OrcaRouterOfferDisclosure": "Codewhale erhält von OrcaRouter eine Vermittlungsprovision.",
"OrcaRouterOfferDisclosure": "Dieser Link gehört zu einer Empfehlungsaktion; Codewhale erhält für Aufladungen über diesen Link möglicherweise eine Prämie.",
"ShellWaitNoActive": "Aktuell wird auf keinen Shell-Befehl gewartet.",
"ShellWaitInteractive": "Interaktive Befehle können nicht im Hintergrund weiterlaufen. Brich den aktuellen Durchgang ab oder warte, bis der Befehl fertig ist.",
"ShellWaitUnavailable": "Dieses Werkzeug kann nicht im Hintergrund weiterlaufen. Brich den aktuellen Durchgang ab oder warte, bis es fertig ist.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Recommended",
"OrcaRouterOfferAction": "View OrcaRouter offer in /provider or /model",
"OrcaRouterOfferBody": "Get a 30% top-up match for DeepSeek V4.1 Flash with the Codewhale × OrcaRouter offer. Check the offer page for current terms.",
"OrcaRouterOfferDisclosure": "Codewhale earns a referral fee from OrcaRouter.",
"OrcaRouterOfferDisclosure": "This link is part of a referral campaign; Codewhale may earn a referral reward on top-ups made through it.",
"ShellWaitNoActive": "No shell wait is active.",
"ShellWaitInteractive": "Interactive commands cannot continue in the background. Cancel the turn, or wait for completion.",
"ShellWaitUnavailable": "This tool cannot continue in the background. Cancel the turn, or wait for completion.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Recomendado",
"OrcaRouterOfferAction": "Ver oferta de OrcaRouter en /provider o /model",
"OrcaRouterOfferBody": "Obtén un 30% de crédito extra para DeepSeek V4.1 Flash en tus recargas con la oferta Codewhale × OrcaRouter. Consulta las condiciones vigentes en la página de la oferta.",
"OrcaRouterOfferDisclosure": "Codewhale recibe una comisión por recomendación de OrcaRouter.",
"OrcaRouterOfferDisclosure": "Este enlace forma parte de una campaña de referidos; Codewhale puede recibir una recompensa por las recargas hechas a través de él.",
"ShellWaitNoActive": "No hay ninguna espera de shell activa.",
"ShellWaitInteractive": "Los comandos interactivos no pueden continuar en segundo plano. Cancela el turno o espera a que terminen.",
"ShellWaitUnavailable": "Esta herramienta no puede continuar en segundo plano. Cancela el turno o espera a que termine.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Recommandé",
"OrcaRouterOfferAction": "Voir l’offre OrcaRouter dans /provider ou /model",
"OrcaRouterOfferBody": "Obtenez 30% de crédit supplémentaire pour DeepSeek V4.1 Flash sur vos recharges avec l’offre Codewhale × OrcaRouter. Consultez les conditions en vigueur sur la page de l’offre.",
"OrcaRouterOfferDisclosure": "Codewhale reçoit une commission de recommandation d’OrcaRouter.",
"OrcaRouterOfferDisclosure": "Ce lien fait partie d’une campagne de parrainage ; Codewhale peut recevoir une récompense sur les recharges effectuées par ce lien.",
"ShellWaitNoActive": "Aucune attente de commande shell en cours.",
"ShellWaitInteractive": "Les commandes interactives ne peuvent pas continuer en arrière-plan. Annulez le tour ou attendez la fin de la commande.",
"ShellWaitUnavailable": "Cet outil ne peut pas continuer en arrière-plan. Annulez le tour ou attendez la fin de son exécution.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · सुझाया गया",
"OrcaRouterOfferAction": "/provider या /model में OrcaRouter का ऑफ़र देखें",
"OrcaRouterOfferBody": "Codewhale × OrcaRouter ऑफ़र के साथ टॉप-अप पर DeepSeek V4.1 Flash के लिए 30% अतिरिक्त क्रेडिट पाएँ। मौजूदा शर्तों के लिए ऑफ़र पेज देखें।",
"OrcaRouterOfferDisclosure": "Codewhale को OrcaRouter से रेफ़रल शुल्क मिलता है।",
"OrcaRouterOfferDisclosure": "यह लिंक एक रेफ़रल अभियान का हिस्सा है; इसके ज़रिए किए गए टॉप-अप पर Codewhale को रेफ़रल इनाम मिल सकता है।",
"ShellWaitNoActive": "अभी किसी शेल कमांड के पूरा होने का इंतज़ार नहीं हो रहा है।",
"ShellWaitInteractive": "इंटरैक्टिव कमांड बैकग्राउंड में जारी नहीं रह सकतीं। इस बारी को रद्द करें या कमांड पूरी होने की प्रतीक्षा करें।",
"ShellWaitUnavailable": "यह टूल बैकग्राउंड में जारी नहीं रह सकता। इस बारी को रद्द करें या इसके पूरा होने की प्रतीक्षा करें।",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Direkomendasikan",
"OrcaRouterOfferAction": "Lihat penawaran OrcaRouter di /provider atau /model",
"OrcaRouterOfferBody": "Dapatkan tambahan kredit DeepSeek V4.1 Flash sebesar 30% dari isi ulang melalui penawaran Codewhale × OrcaRouter. Lihat ketentuan terbaru di halaman penawaran.",
"OrcaRouterOfferDisclosure": "Codewhale menerima komisi rujukan dari OrcaRouter.",
"OrcaRouterOfferDisclosure": "Tautan ini bagian dari kampanye rujukan; Codewhale mungkin menerima imbalan atas isi ulang yang dilakukan melalui tautan ini.",
"ShellWaitNoActive": "Tidak ada perintah shell yang sedang ditunggu.",
"ShellWaitInteractive": "Perintah interaktif tidak dapat berjalan di latar belakang. Batalkan giliran atau tunggu hingga selesai.",
"ShellWaitUnavailable": "Alat ini tidak dapat berjalan di latar belakang. Batalkan giliran atau tunggu hingga selesai.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · おすすめ",
"OrcaRouterOfferAction": "/provider または /model で OrcaRouter の特典を表示",
"OrcaRouterOfferBody": "Codewhale × OrcaRouter の特典で、DeepSeek V4.1 Flash 向けチャージ額の30%が追加されます。最新の条件は特典ページでご確認ください。",
"OrcaRouterOfferDisclosure": "Codewhale は OrcaRouter から紹介料を受け取ります。",
"OrcaRouterOfferDisclosure": "このリンクは紹介キャンペーンの一部です。このリンク経由のチャージに対して、Codewhale が紹介報酬を受け取る場合があります。",
"ShellWaitNoActive": "待機中のシェルコマンドはありません。",
"ShellWaitInteractive": "対話型コマンドはバックグラウンドで続行できません。ターンをキャンセルするか、完了をお待ちください。",
"ShellWaitUnavailable": "このツールはバックグラウンドで続行できません。ターンをキャンセルするか、完了をお待ちください。",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · 추천",
"OrcaRouterOfferAction": "/provider 또는 /model에서 OrcaRouter 혜택 보기",
"OrcaRouterOfferBody": "Codewhale × OrcaRouter 혜택으로 충전 금액의 30%를 DeepSeek V4.1 Flash 크레딧으로 추가 적립하세요. 최신 조건은 혜택 페이지에서 확인하세요.",
"OrcaRouterOfferDisclosure": "Codewhale은 OrcaRouter로부터 추천 수수료를 받습니다.",
"OrcaRouterOfferDisclosure": "이 링크는 추천 캠페인의 일부이며, 이 링크를 통한 충전에 대해 Codewhale이 추천 보상을 받을 수 있습니다.",
"ShellWaitNoActive": "현재 완료를 기다리는 셸 명령이 없습니다.",
"ShellWaitInteractive": "대화형 명령은 백그라운드에서 계속 실행할 수 없습니다. 턴을 취소하거나 명령이 완료될 때까지 기다리세요.",
"ShellWaitUnavailable": "이 도구는 백그라운드에서 계속 실행할 수 없습니다. 턴을 취소하거나 완료될 때까지 기다리세요.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Recomendado",
"OrcaRouterOfferAction": "Ver oferta da OrcaRouter em /provider ou /model",
"OrcaRouterOfferBody": "Receba 30% de crédito extra para DeepSeek V4.1 Flash nas recargas com a oferta Codewhale × OrcaRouter. Confira os termos atuais na página da oferta.",
"OrcaRouterOfferDisclosure": "A Codewhale recebe uma comissão por indicação da OrcaRouter.",
"OrcaRouterOfferDisclosure": "Este link faz parte de uma campanha de indicação; a Codewhale pode receber uma recompensa pelas recargas feitas por meio dele.",
"ShellWaitNoActive": "Não há espera ativa por um comando do shell.",
"ShellWaitInteractive": "Comandos interativos não podem continuar em segundo plano. Cancele o turno ou aguarde a conclusão.",
"ShellWaitUnavailable": "Esta ferramenta não pode continuar em segundo plano. Cancele o turno ou aguarde a conclusão.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Рекомендуем",
"OrcaRouterOfferAction": "Посмотреть предложение OrcaRouter в /provider или /model",
"OrcaRouterOfferBody": "Получите 30% дополнительного кредита для DeepSeek V4.1 Flash при пополнении по предложению Codewhale × OrcaRouter. Актуальные условия указаны на странице предложения.",
"OrcaRouterOfferDisclosure": "Codewhale получает от OrcaRouter комиссию за рекомендации.",
"OrcaRouterOfferDisclosure": "Эта ссылка — часть реферальной кампании; Codewhale может получить вознаграждение за пополнения, сделанные по ней.",
"ShellWaitNoActive": "Сейчас нет ожидания команды оболочки.",
"ShellWaitInteractive": "Интерактивные команды не могут продолжать работу в фоне. Отмените ход или дождитесь завершения команды.",
"ShellWaitUnavailable": "Этот инструмент не может продолжать работу в фоне. Отмените ход или дождитесь его завершения.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Рекомендуємо",
"OrcaRouterOfferAction": "Переглянути пропозицію OrcaRouter у /provider або /model",
"OrcaRouterOfferBody": "Отримайте 30% додаткового кредиту для DeepSeek V4.1 Flash за поповнення з пропозицією Codewhale × OrcaRouter. Актуальні умови наведено на сторінці пропозиції.",
"OrcaRouterOfferDisclosure": "Codewhale отримує від OrcaRouter комісію за рекомендації.",
"OrcaRouterOfferDisclosure": "Це посилання є частиною реферальної кампанії; Codewhale може отримати винагороду за поповнення, зроблені через нього.",
"ShellWaitNoActive": "Зараз немає очікування команди оболонки.",
"ShellWaitInteractive": "Інтерактивні команди не можуть продовжувати роботу у фоні. Скасуйте хід або дочекайтеся завершення команди.",
"ShellWaitUnavailable": "Цей інструмент не може продовжувати роботу у фоні. Скасуйте хід або дочекайтеся його завершення.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · Đề xuất",
"OrcaRouterOfferAction": "Xem ưu đãi OrcaRouter trong /provider hoặc /model",
"OrcaRouterOfferBody": "Nhận thêm 30% tín dụng DeepSeek V4.1 Flash khi nạp tiền với ưu đãi Codewhale × OrcaRouter. Xem điều kiện hiện hành trên trang ưu đãi.",
"OrcaRouterOfferDisclosure": "Codewhale nhận phí giới thiệu từ OrcaRouter.",
"OrcaRouterOfferDisclosure": "Liên kết này thuộc một chiến dịch giới thiệu; Codewhale có thể nhận thưởng cho các lần nạp tiền qua liên kết này.",
"ShellWaitNoActive": "Không có lệnh shell nào đang được chờ.",
"ShellWaitInteractive": "Lệnh tương tác không thể tiếp tục chạy nền. Hãy hủy lượt hoặc chờ lệnh hoàn tất.",
"ShellWaitUnavailable": "Công cụ này không thể tiếp tục chạy nền. Hãy hủy lượt hoặc chờ công cụ hoàn tất.",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · 推荐",
"OrcaRouterOfferAction": "在 /provider 或 /model 中查看 OrcaRouter 优惠",
"OrcaRouterOfferBody": "通过 Codewhale × OrcaRouter 优惠,充值可额外获得 30% 的 DeepSeek V4.1 Flash 额度。最新条款请查看优惠页面。",
"OrcaRouterOfferDisclosure": "Codewhale 会从 OrcaRouter 获得推荐佣金。",
"OrcaRouterOfferDisclosure": "此链接属于一项推广活动;通过此链接充值时,Codewhale 可能获得推广奖励。",
"ShellWaitNoActive": "当前没有正在等待的 shell 命令。",
"ShellWaitInteractive": "交互式命令无法在后台继续运行。请取消当前回合,或等待命令完成。",
"ShellWaitUnavailable": "此工具无法在后台继续运行。请取消当前回合,或等待它完成。",
+1 -1
View File
@@ -8,7 +8,7 @@
"OrcaRouterOfferRecommended": "OrcaRouter · 推薦",
"OrcaRouterOfferAction": "在 /provider 或 /model 中查看 OrcaRouter 優惠",
"OrcaRouterOfferBody": "透過 Codewhale × OrcaRouter 優惠,儲值可額外獲得 30% 的 DeepSeek V4.1 Flash 額度。最新條款請查看優惠頁面。",
"OrcaRouterOfferDisclosure": "Codewhale 會從 OrcaRouter 獲得推薦佣金。",
"OrcaRouterOfferDisclosure": "此連結屬於一項推廣活動;透過此連結儲值時,Codewhale 可能獲得推廣獎勵。",
"ShellWaitNoActive": "目前沒有正在等待的 shell 命令。",
"ShellWaitInteractive": "互動式命令無法在背景繼續執行。請取消目前回合,或等待命令完成。",
"ShellWaitUnavailable": "此工具無法在背景繼續執行。請取消目前回合,或等待它完成。",
+1
View File
@@ -72,6 +72,7 @@ pub mod mouse_ui;
pub mod notifications;
pub mod ocean;
pub mod onboarding;
pub mod orca_offer;
pub mod output_rows_cache;
pub mod pager;
pub mod paste;
+61
View File
@@ -0,0 +1,61 @@
//! The Codewhale × OrcaRouter offer. It is hidden when the interface is in
//! Simplified Chinese or the computer is set to a mainland China time zone or
//! locale. A VPN, a remote shell or a time zone set by hand elsewhere is not
//! detected.
use std::sync::OnceLock;
use codewhale_localization::Locale;
pub(crate) const OFFER_URL: &str =
"https://www.orcarouter.ai/redeem/1a6250545fdc4e0aaccb0a4470159e67";
const MAINLAND_ZONES: &[&str] = &[
"Asia/Shanghai",
"Asia/Chongqing",
"Asia/Chungking",
"Asia/Harbin",
"Asia/Urumqi",
"Asia/Kashgar",
"PRC",
];
pub(crate) fn available(locale: Locale) -> bool {
locale != Locale::ZhHans && !mainland_china()
}
fn mainland_china() -> bool {
static MAINLAND: OnceLock<bool> = OnceLock::new();
*MAINLAND.get_or_init(|| {
let zone = std::env::var("TZ")
.ok()
.filter(|zone| !zone.is_empty())
.or_else(|| {
std::fs::read_link("/etc/localtime")
.ok()
.map(|link| link.to_string_lossy().into_owned())
});
let locale = ["LC_ALL", "LC_MESSAGES", "LANG"]
.iter()
.filter_map(|name| std::env::var(name).ok())
.find(|value| !value.is_empty());
mainland(zone.as_deref(), locale.as_deref())
})
}
fn mainland(zone: Option<&str>, locale: Option<&str>) -> bool {
let zone_is_mainland = zone.is_some_and(|zone| {
let zone = zone.trim_start_matches(':');
MAINLAND_ZONES.iter().any(|name| {
zone == *name
|| zone
.strip_suffix(name)
.is_some_and(|prefix| prefix.ends_with('/'))
})
});
let locale_is_mainland = locale.is_some_and(|value| {
let tag = value.split(['.', '@']).next().unwrap_or_default();
tag.ends_with("_CN") || tag.ends_with("-CN")
});
zone_is_mainland || locale_is_mainland
}
+8 -9
View File
@@ -75,9 +75,6 @@ use codewhale_config::descriptors::defaults::{
DS4_BASE_URL, DS4_DEFAULT_MODEL, LM_STUDIO_BASE_URL,
};
pub(crate) const ORCAROUTER_OFFER_URL: &str =
"https://www.orcarouter.ai/redeem/1a6250545fdc4e0aaccb0a4470159e67";
#[derive(Default)]
pub(crate) struct ProviderOffer {
hitbox: RefCell<Option<Rect>>,
@@ -93,18 +90,20 @@ impl ProviderOffer {
ViewAction::Emit(ViewEvent::OpenTextPager {
title: tr(locale, MessageId::OrcaRouterOfferRecommended).into_owned(),
content: format!(
"{}\n\n{}\n\n{ORCAROUTER_OFFER_URL}",
"{}\n\n{}\n\n{}",
tr(locale, MessageId::OrcaRouterOfferBody),
tr(locale, MessageId::OrcaRouterOfferDisclosure),
crate::tui::orca_offer::OFFER_URL,
),
})
}
pub(crate) fn key_action(locale: Locale, key: &KeyEvent) -> Option<ViewAction> {
crate::tui::shell_key_routing::binding(
crate::tui::shell_key_routing::ShellBindingId::ProviderOffer,
)
.matches(key)
(crate::tui::orca_offer::available(locale)
&& crate::tui::shell_key_routing::binding(
crate::tui::shell_key_routing::ShellBindingId::ProviderOffer,
)
.matches(key))
.then(|| Self::open(locale))
}
@@ -121,7 +120,7 @@ impl ProviderOffer {
pub(crate) fn render(&self, locale: Locale, area: Rect, buf: &mut Buffer) -> Rect {
self.clear();
if area.height < 4 || area.width < 20 {
if area.height < 4 || area.width < 20 || !crate::tui::orca_offer::available(locale) {
return area;
}
let chord = crate::tui::shell_key_routing::display_chord(
+4 -1
View File
@@ -15,10 +15,13 @@ The `/provider` and `/model` pickers recommend OrcaRouter as a partner option.
Click the recommendation or press F7 to view the Codewhale × OrcaRouter offer:
a **30% top-up match for DeepSeek V4.1 Flash**. The pager includes the
[redemption link](https://www.orcarouter.ai/redeem/1a6250545fdc4e0aaccb0a4470159e67)
and can copy its text. Codewhale earns a referral fee from OrcaRouter.
and can copy its text. This link is part of a referral campaign; Codewhale may
earn a referral reward on top-ups made through it.
Current eligibility and terms are owned by the linked offer page. Viewing it
preserves the current provider, model and credentials; redemption happens on
OrcaRouter's site.
The recommendation is not shown when the interface is in Simplified Chinese or
the computer is set to a mainland China time zone or locale.
DeepSeek remains the default provider, but every entry in `ProviderKind::ALL`
is a first-class selectable provider route. `ALL` is the catalog/picker
+2 -2
View File
@@ -48,8 +48,8 @@
"sources": [
{
"path": "docs/PROVIDERS.md",
"sha256": "109ae691105d322a97b0540731715ad0accc3d9eb4f20cb456b8e6d67739e5f8",
"content": "# Provider Registry\n\n> 阅读简体中文版:[zh_hans/PROVIDERS.md](zh_hans/PROVIDERS.md)\n\nSpeech recognition, synthesis, translation and video have separate execution\npaths. See [media models](MEDIA_MODELS.md) for current support and reviewed\nupstream candidates; a chat catalogue row alone does not add a media backend.\n\nThis registry describes provider behavior that is wired into the current\nCodewhale codebase. It is intentionally conservative: shipped entries are\nlimited to provider IDs, config keys, auth paths, base URLs, model resolution,\nand capability metadata that the code already knows about.\n\nThe `/provider` and `/model` pickers recommend OrcaRouter as a partner option.\nClick the recommendation or press F7 to view the Codewhale × OrcaRouter offer:\na **30% top-up match for DeepSeek V4.1 Flash**. The pager includes the\n[redemption link](https://www.orcarouter.ai/redeem/1a6250545fdc4e0aaccb0a4470159e67)\nand can copy its text. Codewhale earns a referral fee from OrcaRouter.\nCurrent eligibility and terms are owned by the linked offer page. Viewing it\npreserves the current provider, model and credentials; redemption happens on\nOrcaRouter's site.\n\nDeepSeek remains the default provider, but every entry in `ProviderKind::ALL`\nis a first-class selectable provider route. `ALL` is the catalog/picker\nsurface — one identity per vendor. Dual-wire dialect kinds (`*Anthropic`, e.g.\n`deepseek-anthropic`) and the Model Studio plan variants stay on the enum for\nserde and `provider_for_kind` but are deliberately **not** catalog rows:\na plan is `mode`/`base_url` and a dialect is `wire = openai|anthropic` on the\nprimary provider config (`crates/config/src/provider_kind.rs:221-226`). Hosted\nroutes, generic OpenAI-compatible endpoints, the OpenAI Codex/ChatGPT route,\nnative Anthropic, and local runtimes all run the same terminal harness against\nthe selected provider/model/base URL.\n\nA host reached over plain Chat Completions is an ordinary named provider,\nnot a `ProviderKind`: enum variants are reserved for distinct *wires*\n(Anthropic Messages, Codex Responses, Google thought signatures). Any such\nhost is a `[providers.<name>]` table with a base URL, a model, and a key env\n(`docs/CONFIGURATION.md`); `/provider` and `/setup` keep a \"paste a Base URL\nand a key\" path for exactly this. Where available, offerings come from live\n`GET /v1/models` plus the Codewhale catalog (#5350, #6289).\n\nBundled compatible hosts. These ship as descriptor rows in\n`crates/config/assets/provider_descriptors.json` (compiled in by\n`crates/config/src/descriptors.rs`): each row says how to reach the host — wire,\nbase URL, key env, aliases — while model IDs come from configured models, the\nCodewhale catalog, and a live `GET /v1/models` when supported. The example model\nis only a bootstrap hint. Verify\nagainst the vendor's own docs before trusting any value here:\n\n| Host | Base URL | Example models | API key env |\n| --- | --- | --- | --- |\n| Thinking Machines Tinker (beta) | `https://tinker.thinkingmachines.dev/services/tinker-prod/oai/api/v1` | `thinkingmachines/Inkling-2-Small:peft:262144:sampling-nvfp4` | `TINKER_API_KEY` |\n| SenseNova | `https://token.sensenova.cn/v1` | `deepseek-v4-flash` | `SENSENOVA_API_KEY` |\n| Baseten | `https://inference.baseten.co/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `BASETEN_API_KEY` |\n| Groq | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` | `GROQ_API_KEY` |\n| Cerebras | `https://api.cerebras.ai/v1` | `llama-3.3-70b` | `CEREBRAS_API_KEY` |\n| Command Code | `https://api.commandcode.ai/provider/v1` | `deepseek/deepseek-v4-flash` | `COMMAND_CODE_API_KEY` |\n| Alibaba Model Studio (DashScope) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `qwen3.8-flash` | `DASHSCOPE_API_KEY` |\n| AICraft | `https://aicraftapi.com/v1` | `claude-4.6-sonnet`; DeepSeek / Claude / Gemini / Qwen / GLM / MiniMax / Doubao families | `AICRAFT_API_KEY` |\n| Tsubasa | `https://api.tsubasa.sh/v1` | `tsubasa-pro`, `tsubasa-fast` (32,768-token context) | `TSUBASA_API_KEY` |\n| Cheaper Inference | `https://api.cheaperinference.com/v1` | `gpt-5.4-mini`, `claude-sonnet-5`, `gemini-3.1-pro` | `CHEAPER_INFERENCE_API_KEY` |\n| Yolo-Auto | `https://yolo-auto.com/v1` | `qwen3.8-flash`; `yolo` / `yolo-small` | `YOLO_AUTO_API_KEY` |\n| Standard Compute | `https://api.stdcmpt.com/v1` | `standardcompute` (router); `deepseek/deepseek-v4-pro`, `anthropic/claude-sonnet-5.5` | `STANDARDCOMPUTE_API_KEY` |\n| Runcrate | `https://api.runcrate.ai/v1` | `deepseek-ai/DeepSeek-V4.1-Flash`, `zai-org/GLM-5.3`, `openai/gpt-oss-120b` | `RUNCRATE_API_KEY` |\n| Opper | `https://api.opper.ai/v3/compat` | `claude-sonnet-4-6`, `gpt-5.4-mini` (pool names); `anthropic/claude-sonnet-4-6` | `OPPER_API_KEY` |\n| Tencent TokenHub | `https://tokenhub-intl.tencentcloudmaas.com/v1` | `hy4` | `TENCENT_API_KEY` |\n\nTinker's OpenAI-compatible API and serverless inference are beta. SelLine truncated
"sha256": "57dece0ceb6ba40a64cfc504f175de4749ff704084634a566533f4c70b863789",
"content": "# Provider Registry\n\n> 阅读简体中文版:[zh_hans/PROVIDERS.md](zh_hans/PROVIDERS.md)\n\nSpeech recognition, synthesis, translation and video have separate execution\npaths. See [media models](MEDIA_MODELS.md) for current support and reviewed\nupstream candidates; a chat catalogue row alone does not add a media backend.\n\nThis registry describes provider behavior that is wired into the current\nCodewhale codebase. It is intentionally conservative: shipped entries are\nlimited to provider IDs, config keys, auth paths, base URLs, model resolution,\nand capability metadata that the code already knows about.\n\nThe `/provider` and `/model` pickers recommend OrcaRouter as a partner option.\nClick the recommendation or press F7 to view the Codewhale × OrcaRouter offer:\na **30% top-up match for DeepSeek V4.1 Flash**. The pager includes the\n[redemption link](https://www.orcarouter.ai/redeem/1a6250545fdc4e0aaccb0a4470159e67)\nand can copy its text. This link is part of a referral campaign; Codewhale may\nearn a referral reward on top-ups made through it.\nCurrent eligibility and terms are owned by the linked offer page. Viewing it\npreserves the current provider, model and credentials; redemption happens on\nOrcaRouter's site.\nThe recommendation is not shown when the interface is in Simplified Chinese or\nthe computer is set to a mainland China time zone or locale.\n\nDeepSeek remains the default provider, but every entry in `ProviderKind::ALL`\nis a first-class selectable provider route. `ALL` is the catalog/picker\nsurface — one identity per vendor. Dual-wire dialect kinds (`*Anthropic`, e.g.\n`deepseek-anthropic`) and the Model Studio plan variants stay on the enum for\nserde and `provider_for_kind` but are deliberately **not** catalog rows:\na plan is `mode`/`base_url` and a dialect is `wire = openai|anthropic` on the\nprimary provider config (`crates/config/src/provider_kind.rs:221-226`). Hosted\nroutes, generic OpenAI-compatible endpoints, the OpenAI Codex/ChatGPT route,\nnative Anthropic, and local runtimes all run the same terminal harness against\nthe selected provider/model/base URL.\n\nA host reached over plain Chat Completions is an ordinary named provider,\nnot a `ProviderKind`: enum variants are reserved for distinct *wires*\n(Anthropic Messages, Codex Responses, Google thought signatures). Any such\nhost is a `[providers.<name>]` table with a base URL, a model, and a key env\n(`docs/CONFIGURATION.md`); `/provider` and `/setup` keep a \"paste a Base URL\nand a key\" path for exactly this. Where available, offerings come from live\n`GET /v1/models` plus the Codewhale catalog (#5350, #6289).\n\nBundled compatible hosts. These ship as descriptor rows in\n`crates/config/assets/provider_descriptors.json` (compiled in by\n`crates/config/src/descriptors.rs`): each row says how to reach the host — wire,\nbase URL, key env, aliases — while model IDs come from configured models, the\nCodewhale catalog, and a live `GET /v1/models` when supported. The example model\nis only a bootstrap hint. Verify\nagainst the vendor's own docs before trusting any value here:\n\n| Host | Base URL | Example models | API key env |\n| --- | --- | --- | --- |\n| Thinking Machines Tinker (beta) | `https://tinker.thinkingmachines.dev/services/tinker-prod/oai/api/v1` | `thinkingmachines/Inkling-2-Small:peft:262144:sampling-nvfp4` | `TINKER_API_KEY` |\n| SenseNova | `https://token.sensenova.cn/v1` | `deepseek-v4-flash` | `SENSENOVA_API_KEY` |\n| Baseten | `https://inference.baseten.co/v1` | `deepseek-ai/DeepSeek-V4-Pro` | `BASETEN_API_KEY` |\n| Groq | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` | `GROQ_API_KEY` |\n| Cerebras | `https://api.cerebras.ai/v1` | `llama-3.3-70b` | `CEREBRAS_API_KEY` |\n| Command Code | `https://api.commandcode.ai/provider/v1` | `deepseek/deepseek-v4-flash` | `COMMAND_CODE_API_KEY` |\n| Alibaba Model Studio (DashScope) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` | `qwen3.8-flash` | `DASHSCOPE_API_KEY` |\n| AICraft | `https://aicraftapi.com/v1` | `claude-4.6-sonnet`; DeepSeek / Claude / Gemini / Qwen / GLM / MiniMax / Doubao families | `AICRAFT_API_KEY` |\n| Tsubasa | `https://api.tsubasa.sh/v1` | `tsubasa-pro`, `tsubasa-fast` (32,768-token context) | `TSUBASA_API_KEY` |\n| Cheaper Inference | `https://api.cheaperinference.com/v1` | `gpt-5.4-mini`, `claude-sonnet-5`, `gemini-3.1-pro` | `CHEAPER_INFERENCE_API_KEY` |\n| Yolo-Auto | `https://yolo-auto.com/v1` | `qwen3.8-flash`; `yolo` / `yolo-small` | `YOLO_AUTO_API_KEY` |\n| Standard Compute | `https://api.stdcmpt.com/v1` | `standardcompute` (router); `deepseek/deepseek-v4-pro`, `anthropic/claude-sonnet-5.5` | `STANDARDCOMPUTE_API_KEY` |\n| Runcrate | `https://api.runcrate.ai/v1` | `deepseek-ai/DeepSeek-V4.1-Flash`, `zai-org/GLM-5.3`, `openai/gpt-oss-120b` | `RUNCRATE_API_KEY` |\n| Opper | `https://api.opper.ai/v3/compat` | `claude-sonnet-4-6`, `gpt-5.4-mini` (pool names); `anthropic/claude-soLine truncated
},
{
"path": "docs/MODEL_LAB.md",