diff --git a/packages/console/app/src/i18n/ar.ts b/packages/console/app/src/i18n/ar.ts index 32610c22e5..3a172c5d9b 100644 --- a/packages/console/app/src/i18n/ar.ts +++ b/packages/console/app/src/i18n/ar.ts @@ -369,6 +369,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "لقد وصلت إلى حد الإنفاق الشهري البالغ ${{amount}}. إدارة حدودك هنا: {{membersUrl}}", "zen.api.error.modelDisabled": "النموذج معطل", + "zen.api.error.regionNotAllowed": + "هذا النموذج مستضاف في الصين. إذا كنت ترغب في استخدام هذا النموذج، فعّله في إعداداتك: {{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 98b91bdb2a..2c1b81c5b4 100644 --- a/packages/console/app/src/i18n/br.ts +++ b/packages/console/app/src/i18n/br.ts @@ -377,6 +377,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Você atingiu seu limite de gastos mensais de ${{amount}}. Gerencie seus limites aqui: {{membersUrl}}", "zen.api.error.modelDisabled": "O modelo está desabilitado", + "zen.api.error.regionNotAllowed": + "Este modelo está hospedado na China. Se você quiser usar este modelo, ative-o nas suas configurações: {{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 de6f0e5594..8df09f3dba 100644 --- a/packages/console/app/src/i18n/da.ts +++ b/packages/console/app/src/i18n/da.ts @@ -373,6 +373,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Du har nået din månedlige forbrugsgrænse på ${{amount}}. Administrer dine grænser her: {{membersUrl}}", "zen.api.error.modelDisabled": "Modellen er deaktiveret", + "zen.api.error.regionNotAllowed": + "Denne model hostes i Kina. Hvis du vil bruge denne model, skal du aktivere den i dine indstillinger: {{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 0453e9f0bf..fd8060e545 100644 --- a/packages/console/app/src/i18n/de.ts +++ b/packages/console/app/src/i18n/de.ts @@ -376,6 +376,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Du hast dein monatliches Ausgabenlimit von ${{amount}} erreicht. Verwalte deine Limits hier: {{membersUrl}}", "zen.api.error.modelDisabled": "Modell ist deaktiviert", + "zen.api.error.regionNotAllowed": + "Dieses Modell wird in China gehostet. Wenn du dieses Modell verwenden möchtest, aktiviere es in deinen Einstellungen: {{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 f740d5cd12..88b710ac37 100644 --- a/packages/console/app/src/i18n/en.ts +++ b/packages/console/app/src/i18n/en.ts @@ -370,6 +370,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "You have reached your monthly spending limit of ${{amount}}. Manage your limits here: {{membersUrl}}", "zen.api.error.modelDisabled": "Model is disabled", + "zen.api.error.regionNotAllowed": + "This model is hosted in China. If you would like to use this model, enable it in your settings: {{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 a59b7f3fc7..3f5cfe1422 100644 --- a/packages/console/app/src/i18n/es.ts +++ b/packages/console/app/src/i18n/es.ts @@ -377,6 +377,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Has alcanzado tu límite de gasto mensual de ${{amount}}. Gestiona tus límites aquí: {{membersUrl}}", "zen.api.error.modelDisabled": "El modelo está deshabilitado", + "zen.api.error.regionNotAllowed": + "Este modelo está alojado en China. Si quieres usar este modelo, actívalo en tu configuración: {{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 5ac4816bd7..7e3de42b8d 100644 --- a/packages/console/app/src/i18n/fr.ts +++ b/packages/console/app/src/i18n/fr.ts @@ -377,6 +377,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Vous avez atteint votre limite de dépense mensuelle de {{amount}} $. Gérez vos limites ici : {{membersUrl}}", "zen.api.error.modelDisabled": "Le modèle est désactivé", + "zen.api.error.regionNotAllowed": + "Ce modèle est hébergé en Chine. Si vous souhaitez utiliser ce modèle, activez-le dans vos paramètres : {{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 8509816477..39d4c3626b 100644 --- a/packages/console/app/src/i18n/it.ts +++ b/packages/console/app/src/i18n/it.ts @@ -373,6 +373,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Hai raggiunto il tuo limite di spesa mensile di ${{amount}}. Gestisci i tuoi limiti qui: {{membersUrl}}", "zen.api.error.modelDisabled": "Il modello è disabilitato", + "zen.api.error.regionNotAllowed": + "Questo modello è ospitato in Cina. Se vuoi usare questo modello, abilitalo nelle tue impostazioni: {{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 3cb6f53985..fc124adc1b 100644 --- a/packages/console/app/src/i18n/ja.ts +++ b/packages/console/app/src/i18n/ja.ts @@ -374,6 +374,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "月額の利用上限 ${{amount}} に達しました。こちらから上限を管理してください: {{membersUrl}}", "zen.api.error.modelDisabled": "モデルが無効です", + "zen.api.error.regionNotAllowed": + "このモデルは中国でホストされています。このモデルを使用したい場合は、設定で有効にしてください: {{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 6ca91d25c7..db21a40cc3 100644 --- a/packages/console/app/src/i18n/ko.ts +++ b/packages/console/app/src/i18n/ko.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.trialEnded": "{{model}}의 무료 프로모션이 종료되었습니다. OpenCode Go를 구독하면 모델을 계속 사용할 수 있습니다 - {{link}}", diff --git a/packages/console/app/src/i18n/no.ts b/packages/console/app/src/i18n/no.ts index 6c13b546fe..0cf394ce8b 100644 --- a/packages/console/app/src/i18n/no.ts +++ b/packages/console/app/src/i18n/no.ts @@ -374,6 +374,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Du har nådd din månedlige utgiftsgrense på ${{amount}}. Administrer grensene dine her: {{membersUrl}}", "zen.api.error.modelDisabled": "Modellen er deaktivert", + "zen.api.error.regionNotAllowed": + "Denne modellen hostes i Kina. Hvis du vil bruke denne modellen, aktiver den i innstillingene dine: {{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 9568132637..48c292100d 100644 --- a/packages/console/app/src/i18n/pl.ts +++ b/packages/console/app/src/i18n/pl.ts @@ -375,6 +375,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Osiągnąłeś swój miesięczny limit wydatków w wysokości ${{amount}}. Zarządzaj swoimi limitami tutaj: {{membersUrl}}", "zen.api.error.modelDisabled": "Model jest wyłączony", + "zen.api.error.regionNotAllowed": + "Ten model jest hostowany w Chinach. Jeśli chcesz korzystać z tego modelu, włącz go w swoich ustawieniach: {{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 a394b1eef0..6d77d17ee9 100644 --- a/packages/console/app/src/i18n/ru.ts +++ b/packages/console/app/src/i18n/ru.ts @@ -379,6 +379,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Вы достигли ежемесячного лимита расходов в ${{amount}}. Управляйте лимитами здесь: {{membersUrl}}", "zen.api.error.modelDisabled": "Модель отключена", + "zen.api.error.regionNotAllowed": + "Эта модель размещена в Китае. Если вы хотите использовать эту модель, включите её в настройках: {{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 ab654b41d7..eebe020948 100644 --- a/packages/console/app/src/i18n/th.ts +++ b/packages/console/app/src/i18n/th.ts @@ -370,6 +370,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "คุณถึงขีดจำกัดการใช้จ่ายรายเดือนที่ ${{amount}} แล้ว จัดการขีดจำกัดของคุณที่นี่: {{membersUrl}}", "zen.api.error.modelDisabled": "โมเดลถูกปิดใช้งาน", + "zen.api.error.regionNotAllowed": + "โมเดลนี้โฮสต์อยู่ในประเทศจีน หากคุณต้องการใช้โมเดลนี้ ให้เปิดใช้งานในการตั้งค่าของคุณ: {{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 041fb43157..866f3adc9a 100644 --- a/packages/console/app/src/i18n/tr.ts +++ b/packages/console/app/src/i18n/tr.ts @@ -377,6 +377,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Aylık ${{amount}} harcama limitinize ulaştınız. Limitlerinizi buradan yönetin: {{membersUrl}}", "zen.api.error.modelDisabled": "Model devre dışı", + "zen.api.error.regionNotAllowed": + "Bu model Çin'de barındırılıyor. Bu modeli kullanmak istiyorsanız ayarlarınızdan etkinleştirin: {{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 26feefb99b..91c7510148 100644 --- a/packages/console/app/src/i18n/uk.ts +++ b/packages/console/app/src/i18n/uk.ts @@ -374,6 +374,8 @@ export const dict = { "zen.api.error.userMonthlyLimitReached": "Ви досягли місячного ліміту витрат ${{amount}}. Керуйте лімітами: {{membersUrl}}", "zen.api.error.modelDisabled": "Модель вимкнено", + "zen.api.error.regionNotAllowed": + "Ця модель розміщена в Китаї. Якщо ви хочете використовувати цю модель, увімкніть її в налаштуваннях: {{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 cebe72f338..ebb0f47e7d 100644 --- a/packages/console/app/src/i18n/zh.ts +++ b/packages/console/app/src/i18n/zh.ts @@ -356,6 +356,7 @@ export const dict = { "您的工作区已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{billingUrl}}", "zen.api.error.userMonthlyLimitReached": "您已达到每月支出限额 ${{amount}}。请在此处管理您的限额:{{membersUrl}}", "zen.api.error.modelDisabled": "模型已禁用", + "zen.api.error.regionNotAllowed": "该模型部署在中国。如果你想使用该模型,请在设置中启用它:{{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 1d982d0611..8170edf646 100644 --- a/packages/console/app/src/i18n/zht.ts +++ b/packages/console/app/src/i18n/zht.ts @@ -356,6 +356,7 @@ export const dict = { "你的工作區已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{billingUrl}}", "zen.api.error.userMonthlyLimitReached": "你已達到每月支出限額 ${{amount}}。請在此處管理你的限額:{{membersUrl}}", "zen.api.error.modelDisabled": "模型已停用", + "zen.api.error.regionNotAllowed": "此模型部署於中國。如果你想使用此模型,請在設定中啟用它:{{consoleGoUrl}}", "zen.api.error.trialEnded": "{{model}} 的限免活动已結束。您可以訂閱 OpenCode Go 繼續使用該模型 - {{link}}", "black.meta.title": "OpenCode Black | 存取全球最佳編碼模型", diff --git a/packages/console/app/src/routes/zen/util/error.ts b/packages/console/app/src/routes/zen/util/error.ts index d17741ff70..5117815d27 100644 --- a/packages/console/app/src/routes/zen/util/error.ts +++ b/packages/console/app/src/routes/zen/util/error.ts @@ -3,6 +3,7 @@ export class CreditsError extends Error {} export class MonthlyLimitError extends Error {} export class UserLimitError extends Error {} export class ModelError extends Error {} +export class RegionError extends Error {} class LimitError extends Error { retryAfter?: number diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts index 9492a1addc..9be1dde330 100644 --- a/packages/console/app/src/routes/zen/util/handler.ts +++ b/packages/console/app/src/routes/zen/util/handler.ts @@ -21,6 +21,7 @@ import { MonthlyLimitError, UserLimitError, ModelError, + RegionError, RateLimitError, FreeUsageLimitError, GoUsageLimitError, @@ -127,11 +128,24 @@ export async function handler( : createKeyRateLimiter(modelInfo.id, modelInfo.rateLimit, zenApiKey, input.request) await rateLimiter?.check() const authInfo = await authenticate(modelInfo, zenApiKey) - if (authInfo && !authInfo.region) { - await Actor.provide("system", { workspaceID: authInfo.workspaceID }, () => - Workspace.setDefaultRegion({ country: countryFromRequest(input.request) }), - ) + const allowedRegions = authInfo?.region + ? authInfo.region + : await (async () => { + if (!authInfo) return + return Actor.provide("system", { workspaceID: authInfo.workspaceID }, () => + Workspace.setDefaultRegion({ country: countryFromRequest(input.request) }), + ) + })() + /* + if (true) { + if (!allowedRegions?.includes("unavailable")) + throw new RegionError( + t("zen.api.error.regionNotAllowed", { + consoleGoUrl: `https://opencode.ai/workspace/${authInfo.workspaceID}/go`, + }), + ) } + */ const stickyId = sessionId ? sessionId : (authInfo?.workspaceID ?? ip) const stickyTracker = createStickyTracker(modelInfo.id, modelInfo.stickyProvider, stickyId) const stickyProvider = await stickyTracker?.get() @@ -444,6 +458,15 @@ export async function handler( } catch {} } + if (error instanceof RegionError) + return new Response( + JSON.stringify({ + type: "error", + error: { type: error.constructor.name, message: error.message }, + }), + { status: 403 }, + ) + // Note: both top level "type" and "error.type" fields are used by the @ai-sdk/anthropic client to render the error message. if ( error instanceof AuthError ||