From 4e29e04f24ddf094bf668127578cf5e766786c68 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 18 Aug 2026 23:52:36 -0400 Subject: [PATCH] sync --- packages/console/app/src/i18n/ar.ts | 3 + packages/console/app/src/i18n/br.ts | 3 + packages/console/app/src/i18n/da.ts | 3 + packages/console/app/src/i18n/de.ts | 3 + packages/console/app/src/i18n/en.ts | 3 +- packages/console/app/src/i18n/es.ts | 3 + packages/console/app/src/i18n/fr.ts | 3 + packages/console/app/src/i18n/it.ts | 3 + packages/console/app/src/i18n/ja.ts | 3 + packages/console/app/src/i18n/ko.ts | 3 + packages/console/app/src/i18n/no.ts | 3 + packages/console/app/src/i18n/pl.ts | 3 + packages/console/app/src/i18n/ru.ts | 3 + packages/console/app/src/i18n/th.ts | 3 + packages/console/app/src/i18n/tr.ts | 3 + packages/console/app/src/i18n/uk.ts | 3 + packages/console/app/src/i18n/zh.ts | 2 + packages/console/app/src/i18n/zht.ts | 2 + .../console/app/src/lib/request-country.ts | 69 +++++++++++++++++++ .../app/src/routes/zen/util/handler.ts | 8 ++- 20 files changed, 125 insertions(+), 4 deletions(-) diff --git a/packages/console/app/src/i18n/ar.ts b/packages/console/app/src/i18n/ar.ts index 958a3f25ca..5a6614c00b 100644 --- a/packages/console/app/src/i18n/ar.ts +++ b/packages/console/app/src/i18n/ar.ts @@ -385,6 +385,9 @@ export const dict = { "zen.api.error.modelDisabled": "النموذج معطل", "zen.api.error.regionNotAllowed": "لا يتوفر أحدث إصدار من هذا النموذج إلا مستضافًا في الصين، ويتطلب تفعيلًا صريحًا: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "هذا النموذج غير متاح في بلدك.", + "zen.api.error.trainingNotAllowed": + "يجمع هذا النموذج بيانات تُستخدم لتحسين جودته، ويتطلب موافقتك الصريحة: {{consoleGoUrl}}", "zen.api.error.trialEnded": "انتهى العرض المجاني لـ {{model}}. يمكنك مواصلة استخدام النموذج بالاشتراك في OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/br.ts b/packages/console/app/src/i18n/br.ts index 73442235f8..d3431f6ae0 100644 --- a/packages/console/app/src/i18n/br.ts +++ b/packages/console/app/src/i18n/br.ts @@ -394,6 +394,9 @@ export const dict = { "zen.api.error.modelDisabled": "O modelo está desabilitado", "zen.api.error.regionNotAllowed": "A versão mais recente deste modelo está disponível apenas com hospedagem na China e requer adesão explícita: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Este modelo não está disponível no seu país.", + "zen.api.error.trainingNotAllowed": + "Este modelo coleta dados usados para melhorar sua qualidade e exige seu consentimento explícito: {{consoleGoUrl}}", "zen.api.error.trialEnded": "A promoção gratuita do {{model}} terminou. Você pode continuar usando o modelo assinando o OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/da.ts b/packages/console/app/src/i18n/da.ts index d6c463ead0..ee2e9aaca3 100644 --- a/packages/console/app/src/i18n/da.ts +++ b/packages/console/app/src/i18n/da.ts @@ -391,6 +391,9 @@ export const dict = { "zen.api.error.modelDisabled": "Modellen er deaktiveret", "zen.api.error.regionNotAllowed": "Den nyeste version af denne model er kun tilgængelig som hostet i Kina og kræver, at du aktivt tilvælger den: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Denne model er ikke tilgængelig i dit land.", + "zen.api.error.trainingNotAllowed": + "Denne model indsamler data, der bruges til at forbedre dens kvalitet, og kræver, at du aktivt tilvælger den: {{consoleGoUrl}}", "zen.api.error.trialEnded": "Den gratis kampagne for {{model}} er afsluttet. Du kan fortsætte med at bruge modellen ved at abonnere på OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/de.ts b/packages/console/app/src/i18n/de.ts index c22855fcfc..e18faa80fb 100644 --- a/packages/console/app/src/i18n/de.ts +++ b/packages/console/app/src/i18n/de.ts @@ -393,6 +393,9 @@ export const dict = { "zen.api.error.modelDisabled": "Modell ist deaktiviert", "zen.api.error.regionNotAllowed": "Die neueste Version dieses Modells ist nur verfügbar, wenn sie in China gehostet wird, und muss ausdrücklich aktiviert werden: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Dieses Modell ist in deinem Land nicht verfügbar.", + "zen.api.error.trainingNotAllowed": + "Dieses Modell erfasst Daten, die zur Verbesserung seiner Qualität verwendet werden, und erfordert deine ausdrückliche Zustimmung: {{consoleGoUrl}}", "zen.api.error.trialEnded": "Die kostenlose Aktion für {{model}} ist beendet. Du kannst das Modell weiterhin nutzen, indem du OpenCode Go abonnierst - {{link}}", diff --git a/packages/console/app/src/i18n/en.ts b/packages/console/app/src/i18n/en.ts index 8340db93db..39c1942ef6 100644 --- a/packages/console/app/src/i18n/en.ts +++ b/packages/console/app/src/i18n/en.ts @@ -390,7 +390,8 @@ export const dict = { "zen.api.error.modelDisabled": "Model is disabled", "zen.api.error.regionNotAllowed": "The latest version of this model is only available hosted in China and requires explicit opt in: {{consoleGoUrl}}", - "zen.api.error.nonZdrNotAllowed": + "zen.api.error.countryNotAllowed": "This model is not available in your country.", + "zen.api.error.trainingNotAllowed": "This model collects data used to improve its quality and requires explicit opt in: {{consoleGoUrl}}", "zen.api.error.trialEnded": "Free promotion has ended for {{model}}. You can continue using the model by subscribing to OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/es.ts b/packages/console/app/src/i18n/es.ts index 1198aaf046..d5560b8def 100644 --- a/packages/console/app/src/i18n/es.ts +++ b/packages/console/app/src/i18n/es.ts @@ -394,6 +394,9 @@ export const dict = { "zen.api.error.modelDisabled": "El modelo está deshabilitado", "zen.api.error.regionNotAllowed": "La versión más reciente de este modelo solo está disponible alojada en China y requiere una aceptación explícita: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Este modelo no está disponible en tu país.", + "zen.api.error.trainingNotAllowed": + "Este modelo recopila datos que se utilizan para mejorar su calidad y requiere tu consentimiento explícito: {{consoleGoUrl}}", "zen.api.error.trialEnded": "La promoción gratuita de {{model}} ha finalizado. Puedes seguir usando el modelo suscribiéndote a OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/fr.ts b/packages/console/app/src/i18n/fr.ts index 9be9946602..a3c1e318da 100644 --- a/packages/console/app/src/i18n/fr.ts +++ b/packages/console/app/src/i18n/fr.ts @@ -395,6 +395,9 @@ export const dict = { "zen.api.error.modelDisabled": "Le modèle est désactivé", "zen.api.error.regionNotAllowed": "La dernière version de ce modèle est uniquement disponible avec un hébergement en Chine et nécessite votre consentement explicite : {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Ce modèle n’est pas disponible dans votre pays.", + "zen.api.error.trainingNotAllowed": + "Ce modèle collecte des données utilisées pour améliorer sa qualité et nécessite votre consentement explicite : {{consoleGoUrl}}", "zen.api.error.trialEnded": "La promotion gratuite de {{model}} est terminée. Vous pouvez continuer à utiliser le modèle en vous abonnant à OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/it.ts b/packages/console/app/src/i18n/it.ts index 7cded5431d..fde98101af 100644 --- a/packages/console/app/src/i18n/it.ts +++ b/packages/console/app/src/i18n/it.ts @@ -390,6 +390,9 @@ export const dict = { "zen.api.error.modelDisabled": "Il modello è disabilitato", "zen.api.error.regionNotAllowed": "La versione più recente di questo modello è disponibile solo con hosting in Cina e richiede un consenso esplicito: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Questo modello non è disponibile nel tuo paese.", + "zen.api.error.trainingNotAllowed": + "Questo modello raccoglie dati utilizzati per migliorarne la qualità e richiede il tuo consenso esplicito: {{consoleGoUrl}}", "zen.api.error.trialEnded": "La promozione gratuita di {{model}} è terminata. Puoi continuare a usare il modello abbonandoti a OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/ja.ts b/packages/console/app/src/i18n/ja.ts index dc46c24a65..e26c8169d3 100644 --- a/packages/console/app/src/i18n/ja.ts +++ b/packages/console/app/src/i18n/ja.ts @@ -389,6 +389,9 @@ export const dict = { "zen.api.error.modelDisabled": "モデルが無効です", "zen.api.error.regionNotAllowed": "このモデルの最新バージョンは中国でのみホスト提供されており、利用するには明示的なオプトインが必要です: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "このモデルはお住まいの国では利用できません。", + "zen.api.error.trainingNotAllowed": + "このモデルは品質向上のためのデータを収集します。利用するには明示的な同意が必要です: {{consoleGoUrl}}", "zen.api.error.trialEnded": "{{model}} の無料プロモーションは終了しました。OpenCode Go を購読するとモデルを引き続き使用できます - {{link}}", diff --git a/packages/console/app/src/i18n/ko.ts b/packages/console/app/src/i18n/ko.ts index a675389e99..4cf831e8fb 100644 --- a/packages/console/app/src/i18n/ko.ts +++ b/packages/console/app/src/i18n/ko.ts @@ -383,6 +383,9 @@ export const dict = { "zen.api.error.modelDisabled": "모델이 비활성화되었습니다", "zen.api.error.regionNotAllowed": "이 모델의 최신 버전은 중국에서 호스팅되는 경우에만 사용할 수 있으며, 명시적으로 사용에 동의해야 합니다: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "이 모델은 거주 국가에서 사용할 수 없습니다.", + "zen.api.error.trainingNotAllowed": + "이 모델은 품질 개선에 사용되는 데이터를 수집하며, 사용하려면 명시적으로 동의해야 합니다: {{consoleGoUrl}}", "zen.api.error.trialEnded": "{{model}}의 무료 프로모션이 종료되었습니다. OpenCode Go를 구독하면 모델을 계속 사용할 수 있습니다 - {{link}}", diff --git a/packages/console/app/src/i18n/no.ts b/packages/console/app/src/i18n/no.ts index 09c9629d0f..52669ee4e8 100644 --- a/packages/console/app/src/i18n/no.ts +++ b/packages/console/app/src/i18n/no.ts @@ -392,6 +392,9 @@ export const dict = { "zen.api.error.modelDisabled": "Modellen er deaktivert", "zen.api.error.regionNotAllowed": "Den nyeste versjonen av denne modellen er bare tilgjengelig som en tjeneste driftet i Kina og krever at du uttrykkelig samtykker: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Denne modellen er ikke tilgjengelig i landet ditt.", + "zen.api.error.trainingNotAllowed": + "Denne modellen samler inn data som brukes til å forbedre modellens kvalitet, og krever at du uttrykkelig samtykker: {{consoleGoUrl}}", "zen.api.error.trialEnded": "Den gratis kampanjen for {{model}} er avsluttet. Du kan fortsette å bruke modellen ved å abonnere på OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/pl.ts b/packages/console/app/src/i18n/pl.ts index 71890ac8b3..b6eb75b14b 100644 --- a/packages/console/app/src/i18n/pl.ts +++ b/packages/console/app/src/i18n/pl.ts @@ -392,6 +392,9 @@ export const dict = { "zen.api.error.modelDisabled": "Model jest wyłączony", "zen.api.error.regionNotAllowed": "Najnowsza wersja tego modelu jest dostępna wyłącznie jako usługa hostowana w Chinach i wymaga jawnej zgody użytkownika: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Ten model nie jest dostępny w Twoim kraju.", + "zen.api.error.trainingNotAllowed": + "Ten model zbiera dane wykorzystywane do poprawy jego jakości i wymaga wyraźnej zgody użytkownika: {{consoleGoUrl}}", "zen.api.error.trialEnded": "Bezpłatna promocja {{model}} dobiegła końca. Możesz dalej korzystać z modelu, subskrybując OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/ru.ts b/packages/console/app/src/i18n/ru.ts index 1662061fde..2fbe5c42d6 100644 --- a/packages/console/app/src/i18n/ru.ts +++ b/packages/console/app/src/i18n/ru.ts @@ -397,6 +397,9 @@ export const dict = { "zen.api.error.modelDisabled": "Модель отключена", "zen.api.error.regionNotAllowed": "Последняя версия этой модели размещена только в Китае. Чтобы использовать её, необходимо явно подтвердить согласие: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Эта модель недоступна в вашей стране.", + "zen.api.error.trainingNotAllowed": + "Эта модель собирает данные, которые используются для улучшения её качества, и требует явного согласия: {{consoleGoUrl}}", "zen.api.error.trialEnded": "Бесплатная акция для {{model}} завершена. Вы можете продолжить использование модели, подписавшись на OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/th.ts b/packages/console/app/src/i18n/th.ts index f72841b6d2..5223e7c0fe 100644 --- a/packages/console/app/src/i18n/th.ts +++ b/packages/console/app/src/i18n/th.ts @@ -387,6 +387,9 @@ export const dict = { "zen.api.error.modelDisabled": "โมเดลถูกปิดใช้งาน", "zen.api.error.regionNotAllowed": "โมเดลเวอร์ชันล่าสุดนี้ให้บริการเฉพาะผ่านระบบที่โฮสต์ในประเทศจีน และต้องให้ความยินยอมอย่างชัดแจ้งก่อนใช้งาน: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "โมเดลนี้ไม่พร้อมให้บริการในประเทศของคุณ", + "zen.api.error.trainingNotAllowed": + "โมเดลนี้เก็บรวบรวมข้อมูลที่ใช้เพื่อปรับปรุงคุณภาพของโมเดล และต้องได้รับความยินยอมอย่างชัดแจ้งก่อนใช้งาน: {{consoleGoUrl}}", "zen.api.error.trialEnded": "โปรโมชันฟรีสำหรับ {{model}} สิ้นสุดแล้ว คุณสามารถใช้โมเดลต่อได้โดยสมัครสมาชิก OpenCode Go - {{link}}", diff --git a/packages/console/app/src/i18n/tr.ts b/packages/console/app/src/i18n/tr.ts index abe65c93af..e2b132c94e 100644 --- a/packages/console/app/src/i18n/tr.ts +++ b/packages/console/app/src/i18n/tr.ts @@ -395,6 +395,9 @@ export const dict = { "zen.api.error.modelDisabled": "Model devre dışı", "zen.api.error.regionNotAllowed": "Bu modelin en son sürümü yalnızca Çin'de barındırılıyor ve kullanabilmek için açıkça onay vermeniz gerekiyor: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Bu model ülkenizde kullanılamıyor.", + "zen.api.error.trainingNotAllowed": + "Bu model, kalitesini artırmak için kullanılan verileri toplar. Modeli kullanabilmek için açıkça onay vermeniz gerekir: {{consoleGoUrl}}", "zen.api.error.trialEnded": "{{model}} için ücretsiz promosyon sona erdi. OpenCode Go'ya abone olarak modeli kullanmaya devam edebilirsiniz - {{link}}", diff --git a/packages/console/app/src/i18n/uk.ts b/packages/console/app/src/i18n/uk.ts index 688a68cdba..a8fdc60249 100644 --- a/packages/console/app/src/i18n/uk.ts +++ b/packages/console/app/src/i18n/uk.ts @@ -391,6 +391,9 @@ export const dict = { "zen.api.error.modelDisabled": "Модель вимкнено", "zen.api.error.regionNotAllowed": "Остання версія цієї моделі доступна лише на серверах у Китаї, і для її використання потрібно надати явну згоду: {{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "Ця модель недоступна у вашій країні.", + "zen.api.error.trainingNotAllowed": + "Ця модель збирає дані, які використовуються для покращення її якості; для її використання потрібна ваша явна згода: {{consoleGoUrl}}", "zen.api.error.trialEnded": "Безкоштовна акція для {{model}} закінчилася. Ви можете продовжити використання, підписавшись на OpenCode Go — {{link}}", diff --git a/packages/console/app/src/i18n/zh.ts b/packages/console/app/src/i18n/zh.ts index 6aa7cf2a03..b4a9516545 100644 --- a/packages/console/app/src/i18n/zh.ts +++ b/packages/console/app/src/i18n/zh.ts @@ -368,6 +368,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "您已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{membersUrl}}", "zen.api.error.modelDisabled": "模型已禁用", "zen.api.error.regionNotAllowed": "该模型的最新版本仅在中国提供托管服务,需明确选择启用:{{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "该模型在你所在的国家或地区不可用。", + "zen.api.error.trainingNotAllowed": "该模型会收集用于提升其质量的数据,使用前需要你明确同意:{{consoleGoUrl}}", "zen.api.error.trialEnded": "{{model}} 的限免活动已结束。您可以订阅 OpenCode Go 继续使用该模型 - {{link}}", "black.meta.title": "OpenCode Black | 访问全球顶尖编程模型", diff --git a/packages/console/app/src/i18n/zht.ts b/packages/console/app/src/i18n/zht.ts index 2786df150e..e261fa3386 100644 --- a/packages/console/app/src/i18n/zht.ts +++ b/packages/console/app/src/i18n/zht.ts @@ -368,6 +368,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "你已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{membersUrl}}", "zen.api.error.modelDisabled": "模型已停用", "zen.api.error.regionNotAllowed": "此模型的最新版本僅於中國託管,且需明確選擇啟用:{{consoleGoUrl}}", + "zen.api.error.countryNotAllowed": "此模型無法在你所在的國家或地區使用。", + "zen.api.error.trainingNotAllowed": "此模型會收集用於提升其品質的資料,使用前須經你明確同意:{{consoleGoUrl}}", "zen.api.error.trialEnded": "{{model}} 的限免活动已結束。您可以訂閱 OpenCode Go 繼續使用該模型 - {{link}}", "black.meta.title": "OpenCode Black | 存取全球最佳編碼模型", diff --git a/packages/console/app/src/lib/request-country.ts b/packages/console/app/src/lib/request-country.ts index a4e39eb607..0eb16722ac 100644 --- a/packages/console/app/src/lib/request-country.ts +++ b/packages/console/app/src/lib/request-country.ts @@ -1,5 +1,74 @@ +const MUSE_SPARK_BLOCKED_COUNTRIES = new Set([ + "AD", + "AF", + "AT", + "AU", + "BE", + "BG", + "BR", + "BY", + "CA", + "CH", + "CN", + "CU", + "CY", + "CZ", + "DE", + "DK", + "EE", + "EH", + "ER", + "ES", + "ET", + "FI", + "FR", + "GB", + "GR", + "HK", + "HR", + "HT", + "HU", + "IE", + "IQ", + "IR", + "IS", + "IT", + "KH", + "KP", + "KR", + "LI", + "LT", + "LU", + "LV", + "LY", + "MC", + "MM", + "MO", + "MT", + "NI", + "NL", + "NO", + "PK", + "PL", + "PT", + "RO", + "RU", + "SE", + "SI", + "SK", + "SM", + "SO", + "SY", + "VA", + "VE", +]) + export function countryFromRequest(request: Request | undefined) { if (!request) return undefined const cloudflareRequest = request as Request & { cf?: { country?: string } } return cloudflareRequest.cf?.country ?? request.headers.get("cf-ipcountry") ?? undefined } + +export function isModelCountryRestricted(model: string, country: string | undefined) { + return model === "muse-spark-1.2" && country !== undefined && MUSE_SPARK_BLOCKED_COUNTRIES.has(country.toUpperCase()) +} diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts index 699a00c483..d6b1dba6db 100644 --- a/packages/console/app/src/routes/zen/util/handler.ts +++ b/packages/console/app/src/routes/zen/util/handler.ts @@ -52,7 +52,7 @@ import { createModelTpsLimiter } from "./modelTpsLimiter" import { createProviderBudgetTracker } from "./providerBudgetTracker" import { accumulateUsage, HOT_WORKSPACES } from "./usageBatcher" import { Workspace } from "@opencode-ai/console-core/workspace.js" -import { countryFromRequest } from "~/lib/request-country" +import { countryFromRequest, isModelCountryRestricted } from "~/lib/request-country" type ZenData = Awaited> type RetryOptions = { @@ -122,6 +122,8 @@ export async function handler( }) const zenData = ZenData.list(opts.modelList) const modelInfo = validateModel(zenData, model) + const country = countryFromRequest(input.request) + if (isModelCountryRestricted(modelInfo.id, country)) throw new RegionError(t("zen.api.error.countryNotAllowed")) const trialLimiter = createTrialLimiter(modelInfo.trialProvider, ip) const trialProviders = await trialLimiter?.check() const rateLimiter = modelInfo.allowAnonymous @@ -131,7 +133,7 @@ export async function handler( const authInfo = await authenticate(modelInfo, zenApiKey) if (authInfo && opts.modelList === "lite" && modelInfo.id === "muse-spark-1.2" && !authInfo.allowTraining) throw new DataPolicyError( - t("zen.api.error.nonZdrNotAllowed", { + t("zen.api.error.trainingNotAllowed", { consoleGoUrl: `https://opencode.ai/workspace/${authInfo.workspaceID}/go`, }), ) @@ -140,7 +142,7 @@ export async function handler( : await (async () => { if (!authInfo) return return Actor.provide("system", { workspaceID: authInfo.workspaceID }, () => - Workspace.setDefaultRegion({ country: countryFromRequest(input.request) }), + Workspace.setDefaultRegion({ country }), ) })() if (