From 537289326be2d81c7f1748ef0e69455b3b97124c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Wed, 28 Jan 2026 10:22:54 +0100 Subject: [PATCH 1/2] feat: anon kilo gateway --- .opencode/opencode.jsonc | 6 +-- .../components/dialog-connect-provider.tsx | 16 ++++--- packages/app/src/i18n/ar.ts | 12 ++--- packages/app/src/i18n/br.ts | 12 ++--- packages/app/src/i18n/da.ts | 11 +++-- packages/app/src/i18n/de.ts | 11 +++-- packages/app/src/i18n/en.ts | 12 ++--- packages/app/src/i18n/es.ts | 11 +++-- packages/app/src/i18n/fr.ts | 11 +++-- packages/app/src/i18n/ja.ts | 11 +++-- packages/app/src/i18n/ko.ts | 11 +++-- packages/app/src/i18n/no.ts | 12 ++--- packages/app/src/i18n/pl.ts | 12 ++--- packages/app/src/i18n/ru.ts | 12 ++--- packages/app/src/i18n/zh.ts | 9 ++-- packages/app/src/i18n/zht.ts | 10 ++-- packages/kilo-gateway/src/api/constants.ts | 5 +- packages/kilo-gateway/src/api/profile.ts | 29 +++++++++++- packages/kilo-gateway/src/index.ts | 3 ++ packages/opencode/src/acp/agent.ts | 18 +++++--- packages/opencode/src/cli/cmd/models.ts | 10 ++-- .../cli/cmd/tui/component/dialog-provider.tsx | 11 ++--- packages/opencode/src/provider/provider.ts | 46 ++++++++----------- packages/opencode/src/server/routes/config.ts | 32 ++++++++++++- packages/opencode/src/tool/registry.ts | 6 ++- 25 files changed, 202 insertions(+), 137 deletions(-) diff --git a/.opencode/opencode.jsonc b/.opencode/opencode.jsonc index c3f0b7070d..b9fa6e939d 100644 --- a/.opencode/opencode.jsonc +++ b/.opencode/opencode.jsonc @@ -4,11 +4,7 @@ // "enterprise": { // "url": "https://enterprise.dev.opencode.ai", // }, - "provider": { - "opencode": { - "options": {}, - }, - }, + "provider": {}, "mcp": { "context7": { "type": "remote", diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index 5c762ee9de..e5c2227b7b 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -244,23 +244,25 @@ export function DialogConnectProvider(props: { provider: string }) { return (
- + {/* kilocode_change start */} +
- {language.t("provider.connect.opencodeZen.line1")} + {language.t("provider.connect.kiloGateway.line1")}
- {language.t("provider.connect.opencodeZen.line2")} + {language.t("provider.connect.kiloGateway.line2")}
- {language.t("provider.connect.opencodeZen.visit.prefix")} - - {language.t("provider.connect.opencodeZen.visit.link")} + {language.t("provider.connect.kiloGateway.visit.prefix")} + + {language.t("provider.connect.kiloGateway.visit.link")} - {language.t("provider.connect.opencodeZen.visit.suffix")} + {language.t("provider.connect.kiloGateway.visit.suffix")}
+ {/* kilocode_change end */}
{language.t("provider.connect.apiKey.description", { provider: provider().name })} diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts index 1dee0115b3..593307e0fb 100644 --- a/packages/app/src/i18n/ar.ts +++ b/packages/app/src/i18n/ar.ts @@ -116,13 +116,13 @@ export const dict = { "provider.connect.apiKey.label": "مفتاح واجهة برمجة تطبيقات {{provider}}", "provider.connect.apiKey.placeholder": "مفتاح API", "provider.connect.apiKey.required": "مفتاح API مطلوب", - "provider.connect.opencodeZen.line1": - "يمنحك Kilo CLI Zen الوصول إلى مجموعة مختارة من النماذج الموثوقة والمحسنة لوكلاء البرمجة.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "يمنحك Kilo Gateway الوصول إلى مجموعة مختارة من النماذج الموثوقة والمحسنة لوكلاء البرمجة.", + "provider.connect.kiloGateway.line2": "باستخدام مفتاح API واحد، ستحصل على إمكانية الوصول إلى نماذج مثل Claude و GPT و Gemini و GLM والمزيد.", - "provider.connect.opencodeZen.visit.prefix": "قم بزيارة ", - "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", - "provider.connect.opencodeZen.visit.suffix": " للحصول على مفتاح API الخاص بك.", + "provider.connect.kiloGateway.visit.prefix": "قم بزيارة ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " للحصول على مفتاح API الخاص بك.", "provider.connect.oauth.code.visit.prefix": "قم بزيارة ", "provider.connect.oauth.code.visit.link": "هذا الرابط", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/br.ts b/packages/app/src/i18n/br.ts index 6442bd8a4d..09dad7236c 100644 --- a/packages/app/src/i18n/br.ts +++ b/packages/app/src/i18n/br.ts @@ -116,13 +116,13 @@ export const dict = { "provider.connect.apiKey.label": "Chave de API do {{provider}}", "provider.connect.apiKey.placeholder": "Chave de API", "provider.connect.apiKey.required": "A chave de API é obrigatória", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen oferece acesso a um conjunto selecionado de modelos confiáveis otimizados para agentes de código.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway oferece acesso a um conjunto selecionado de modelos confiáveis otimizados para agentes de código.", + "provider.connect.kiloGateway.line2": "Com uma única chave de API você terá acesso a modelos como Claude, GPT, Gemini, GLM e mais.", - "provider.connect.opencodeZen.visit.prefix": "Visite ", - "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", - "provider.connect.opencodeZen.visit.suffix": " para obter sua chave de API.", + "provider.connect.kiloGateway.visit.prefix": "Visite ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " para obter sua chave de API.", "provider.connect.oauth.code.visit.prefix": "Visite ", "provider.connect.oauth.code.visit.link": "este link", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts index 85da3935a2..5f10112b81 100644 --- a/packages/app/src/i18n/da.ts +++ b/packages/app/src/i18n/da.ts @@ -114,12 +114,13 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} API-nøgle", "provider.connect.apiKey.placeholder": "API-nøgle", "provider.connect.apiKey.required": "API-nøgle er påkrævet", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen giver dig adgang til et udvalg af pålidelige optimerede modeller til kodningsagenter.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway giver dig adgang til et udvalg af pålidelige optimerede modeller til kodningsagenter.", + "provider.connect.kiloGateway.line2": "Med en enkelt API-nøgle får du adgang til modeller som Claude, GPT, Gemini, GLM og flere.", - "provider.connect.opencodeZen.visit.prefix": "Besøg ", - "provider.connect.opencodeZen.visit.suffix": " for at hente din API-nøgle.", + "provider.connect.kiloGateway.visit.prefix": "Besøg ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " for at hente din API-nøgle.", "provider.connect.oauth.code.visit.prefix": "Besøg ", "provider.connect.oauth.code.visit.link": "dette link", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts index ac66e67950..e6ac6fb202 100644 --- a/packages/app/src/i18n/de.ts +++ b/packages/app/src/i18n/de.ts @@ -118,12 +118,13 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} API-Schlüssel", "provider.connect.apiKey.placeholder": "API-Schlüssel", "provider.connect.apiKey.required": "API-Schlüssel ist erforderlich", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen bietet Ihnen Zugriff auf eine kuratierte Auswahl zuverlässiger, optimierter Modelle für Coding-Agenten.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway bietet Ihnen Zugriff auf eine kuratierte Auswahl zuverlässiger, optimierter Modelle für Coding-Agenten.", + "provider.connect.kiloGateway.line2": "Mit einem einzigen API-Schlüssel erhalten Sie Zugriff auf Modelle wie Claude, GPT, Gemini, GLM und mehr.", - "provider.connect.opencodeZen.visit.prefix": "Besuchen Sie ", - "provider.connect.opencodeZen.visit.suffix": ", um Ihren API-Schlüssel zu erhalten.", + "provider.connect.kiloGateway.visit.prefix": "Besuchen Sie ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": ", um Ihren API-Schlüssel zu erhalten.", "provider.connect.oauth.code.visit.prefix": "Besuchen Sie ", "provider.connect.oauth.code.visit.link": "diesen Link", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index 9dcf640be1..c4f6adbe51 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -116,13 +116,13 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} API key", "provider.connect.apiKey.placeholder": "API key", "provider.connect.apiKey.required": "API key is required", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen gives you access to a curated set of reliable optimized models for coding agents.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway gives you access to a curated set of reliable optimized models for coding agents.", + "provider.connect.kiloGateway.line2": "With a single API key you'll get access to models such as Claude, GPT, Gemini, GLM and more.", - "provider.connect.opencodeZen.visit.prefix": "Visit ", - "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", - "provider.connect.opencodeZen.visit.suffix": " to collect your API key.", + "provider.connect.kiloGateway.visit.prefix": "Visit ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " to collect your API key.", "provider.connect.oauth.code.visit.prefix": "Visit ", "provider.connect.oauth.code.visit.link": "this link", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts index 398d6986b3..6ca5a10099 100644 --- a/packages/app/src/i18n/es.ts +++ b/packages/app/src/i18n/es.ts @@ -114,12 +114,13 @@ export const dict = { "provider.connect.apiKey.label": "Clave API de {{provider}}", "provider.connect.apiKey.placeholder": "Clave API", "provider.connect.apiKey.required": "La clave API es obligatoria", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen te da acceso a un conjunto curado de modelos fiables optimizados para agentes de programación.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway te da acceso a un conjunto curado de modelos fiables optimizados para agentes de programación.", + "provider.connect.kiloGateway.line2": "Con una sola clave API obtendrás acceso a modelos como Claude, GPT, Gemini, GLM y más.", - "provider.connect.opencodeZen.visit.prefix": "Visita ", - "provider.connect.opencodeZen.visit.suffix": " para obtener tu clave API.", + "provider.connect.kiloGateway.visit.prefix": "Visita ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " para obtener tu clave API.", "provider.connect.oauth.code.visit.prefix": "Visita ", "provider.connect.oauth.code.visit.link": "este enlace", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts index 9f3fa5b4e2..f8d1846ad4 100644 --- a/packages/app/src/i18n/fr.ts +++ b/packages/app/src/i18n/fr.ts @@ -114,12 +114,13 @@ export const dict = { "provider.connect.apiKey.label": "Clé API {{provider}}", "provider.connect.apiKey.placeholder": "Clé API", "provider.connect.apiKey.required": "La clé API est requise", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen vous donne accès à un ensemble sélectionné de modèles fiables et optimisés pour les agents de codage.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway vous donne accès à un ensemble sélectionné de modèles fiables et optimisés pour les agents de codage.", + "provider.connect.kiloGateway.line2": "Avec une seule clé API, vous aurez accès à des modèles tels que Claude, GPT, Gemini, GLM et plus encore.", - "provider.connect.opencodeZen.visit.prefix": "Visitez ", - "provider.connect.opencodeZen.visit.suffix": " pour récupérer votre clé API.", + "provider.connect.kiloGateway.visit.prefix": "Visitez ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " pour récupérer votre clé API.", "provider.connect.oauth.code.visit.prefix": "Visitez ", "provider.connect.oauth.code.visit.link": "ce lien", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts index 8ea3cd0639..be77cf7f58 100644 --- a/packages/app/src/i18n/ja.ts +++ b/packages/app/src/i18n/ja.ts @@ -114,11 +114,12 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} APIキー", "provider.connect.apiKey.placeholder": "APIキー", "provider.connect.apiKey.required": "APIキーが必要です", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zenは、コーディングエージェント向けに最適化された信頼性の高いモデルへのアクセスを提供します。", - "provider.connect.opencodeZen.line2": "1つのAPIキーで、Claude、GPT、Gemini、GLMなどのモデルにアクセスできます。", - "provider.connect.opencodeZen.visit.prefix": " ", - "provider.connect.opencodeZen.visit.suffix": " にアクセスしてAPIキーを取得してください。", + "provider.connect.kiloGateway.line1": + "Kilo Gatewayは、コーディングエージェント向けに最適化された信頼性の高いモデルへのアクセスを提供します。", + "provider.connect.kiloGateway.line2": "1つのAPIキーで、Claude、GPT、Gemini、GLMなどのモデルにアクセスできます。", + "provider.connect.kiloGateway.visit.prefix": " ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " にアクセスしてAPIキーを取得してください。", "provider.connect.oauth.code.visit.prefix": " ", "provider.connect.oauth.code.visit.link": "このリンク", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts index 7cdce05ccc..7067ce4728 100644 --- a/packages/app/src/i18n/ko.ts +++ b/packages/app/src/i18n/ko.ts @@ -118,11 +118,12 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} API 키", "provider.connect.apiKey.placeholder": "API 키", "provider.connect.apiKey.required": "API 키가 필요합니다", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen은 코딩 에이전트를 위해 최적화된 신뢰할 수 있는 엄선된 모델에 대한 액세스를 제공합니다.", - "provider.connect.opencodeZen.line2": "단일 API 키로 Claude, GPT, Gemini, GLM 등 다양한 모델에 액세스할 수 있습니다.", - "provider.connect.opencodeZen.visit.prefix": "", - "provider.connect.opencodeZen.visit.suffix": "를 방문하여 API 키를 받으세요.", + "provider.connect.kiloGateway.line1": + "Kilo Gateway은 코딩 에이전트를 위해 최적화된 신뢰할 수 있는 엄선된 모델에 대한 액세스를 제공합니다.", + "provider.connect.kiloGateway.line2": "단일 API 키로 Claude, GPT, Gemini, GLM 등 다양한 모델에 액세스할 수 있습니다.", + "provider.connect.kiloGateway.visit.prefix": "", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": "를 방문하여 API 키를 받으세요.", "provider.connect.oauth.code.visit.prefix": "", "provider.connect.oauth.code.visit.link": "이 링크", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/no.ts b/packages/app/src/i18n/no.ts index f0f391d187..ab247fa250 100644 --- a/packages/app/src/i18n/no.ts +++ b/packages/app/src/i18n/no.ts @@ -119,13 +119,13 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} API-nøkkel", "provider.connect.apiKey.placeholder": "API-nøkkel", "provider.connect.apiKey.required": "API-nøkkel er påkrevd", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen gir deg tilgang til et utvalg av pålitelige optimaliserte modeller for kodeagenter.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway gir deg tilgang til et utvalg av pålitelige optimaliserte modeller for kodeagenter.", + "provider.connect.kiloGateway.line2": "Med én enkelt API-nøkkel får du tilgang til modeller som Claude, GPT, Gemini, GLM og flere.", - "provider.connect.opencodeZen.visit.prefix": "Besøk ", - "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", - "provider.connect.opencodeZen.visit.suffix": " for å hente API-nøkkelen din.", + "provider.connect.kiloGateway.visit.prefix": "Besøk ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " for å hente API-nøkkelen din.", "provider.connect.oauth.code.visit.prefix": "Besøk ", "provider.connect.oauth.code.visit.link": "denne lenken", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/pl.ts b/packages/app/src/i18n/pl.ts index 1713896c6b..500b4bb6ed 100644 --- a/packages/app/src/i18n/pl.ts +++ b/packages/app/src/i18n/pl.ts @@ -116,13 +116,13 @@ export const dict = { "provider.connect.apiKey.label": "Klucz API {{provider}}", "provider.connect.apiKey.placeholder": "Klucz API", "provider.connect.apiKey.required": "Klucz API jest wymagany", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen daje dostęp do wybranego zestawu niezawodnych, zoptymalizowanych modeli dla agentów kodujących.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway daje dostęp do wybranego zestawu niezawodnych, zoptymalizowanych modeli dla agentów kodujących.", + "provider.connect.kiloGateway.line2": "Z jednym kluczem API uzyskasz dostęp do modeli takich jak Claude, GPT, Gemini, GLM i więcej.", - "provider.connect.opencodeZen.visit.prefix": "Odwiedź ", - "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", - "provider.connect.opencodeZen.visit.suffix": ", aby odebrać swój klucz API.", + "provider.connect.kiloGateway.visit.prefix": "Odwiedź ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": ", aby odebrać swój klucz API.", "provider.connect.oauth.code.visit.prefix": "Odwiedź ", "provider.connect.oauth.code.visit.link": "ten link", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts index ca7c49264e..0675889ea1 100644 --- a/packages/app/src/i18n/ru.ts +++ b/packages/app/src/i18n/ru.ts @@ -116,13 +116,13 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} API ключ", "provider.connect.apiKey.placeholder": "API ключ", "provider.connect.apiKey.required": "API ключ обязателен", - "provider.connect.opencodeZen.line1": - "Kilo CLI Zen даёт вам доступ к отобранным надёжным оптимизированным моделям для агентов программирования.", - "provider.connect.opencodeZen.line2": + "provider.connect.kiloGateway.line1": + "Kilo Gateway даёт вам доступ к отобранным надёжным оптимизированным моделям для агентов программирования.", + "provider.connect.kiloGateway.line2": "С одним API ключом вы получите доступ к таким моделям как Claude, GPT, Gemini, GLM и другим.", - "provider.connect.opencodeZen.visit.prefix": "Посетите ", - "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", - "provider.connect.opencodeZen.visit.suffix": " чтобы получить ваш API ключ.", + "provider.connect.kiloGateway.visit.prefix": "Посетите ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " чтобы получить ваш API ключ.", "provider.connect.oauth.code.visit.prefix": "Посетите ", "provider.connect.oauth.code.visit.link": "эту ссылку", "provider.connect.oauth.code.visit.suffix": diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts index 9f04d87ea9..3208edcf45 100644 --- a/packages/app/src/i18n/zh.ts +++ b/packages/app/src/i18n/zh.ts @@ -118,10 +118,11 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} API 密钥", "provider.connect.apiKey.placeholder": "API 密钥", "provider.connect.apiKey.required": "API 密钥为必填项", - "provider.connect.opencodeZen.line1": "Kilo CLI Zen 为你提供一组精选的可靠优化模型,用于代码智能体。", - "provider.connect.opencodeZen.line2": "只需一个 API 密钥,你就能使用 Claude、GPT、Gemini、GLM 等模型。", - "provider.connect.opencodeZen.visit.prefix": "访问 ", - "provider.connect.opencodeZen.visit.suffix": " 获取你的 API 密钥。", + "provider.connect.kiloGateway.line1": "Kilo Gateway 为你提供一组精选的可靠优化模型,用于代码智能体。", + "provider.connect.kiloGateway.line2": "只需一个 API 密钥,你就能使用 Claude、GPT、Gemini、GLM 等模型。", + "provider.connect.kiloGateway.visit.prefix": "访问 ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " 获取你的 API 密钥。", "provider.connect.oauth.code.visit.prefix": "访问 ", "provider.connect.oauth.code.visit.link": "此链接", "provider.connect.oauth.code.visit.suffix": " 获取授权码,以连接你的帐户并在 Kilo CLI 中使用 {{provider}} 模型。", diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts index 824087f28c..bd6bac4979 100644 --- a/packages/app/src/i18n/zht.ts +++ b/packages/app/src/i18n/zht.ts @@ -118,11 +118,11 @@ export const dict = { "provider.connect.apiKey.label": "{{provider}} API 金鑰", "provider.connect.apiKey.placeholder": "API 金鑰", "provider.connect.apiKey.required": "API 金鑰為必填", - "provider.connect.opencodeZen.line1": "Kilo CLI Zen 為你提供一組精選的可靠最佳化模型,用於程式碼代理程式。", - "provider.connect.opencodeZen.line2": "只需一個 API 金鑰,你就能使用 Claude、GPT、Gemini、GLM 等模型。", - "provider.connect.opencodeZen.visit.prefix": "造訪 ", - "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", - "provider.connect.opencodeZen.visit.suffix": " 取得你的 API 金鑰。", + "provider.connect.kiloGateway.line1": "Kilo Gateway 為你提供一組精選的可靠最佳化模型,用於程式碼代理程式。", + "provider.connect.kiloGateway.line2": "只需一個 API 金鑰,你就能使用 Claude、GPT、Gemini、GLM 等模型。", + "provider.connect.kiloGateway.visit.prefix": "造訪 ", + "provider.connect.kiloGateway.visit.link": "kilo.ai", + "provider.connect.kiloGateway.visit.suffix": " 取得你的 API 金鑰。", "provider.connect.oauth.code.visit.prefix": "造訪 ", "provider.connect.oauth.code.visit.link": "此連結", "provider.connect.oauth.code.visit.suffix": " 取得授權碼,以連線你的帳戶並在 Kilo CLI 中使用 {{provider}} 模型。", diff --git a/packages/kilo-gateway/src/api/constants.ts b/packages/kilo-gateway/src/api/constants.ts index a2e3c9f208..cb6900ef19 100644 --- a/packages/kilo-gateway/src/api/constants.ts +++ b/packages/kilo-gateway/src/api/constants.ts @@ -12,9 +12,12 @@ export const KILO_OPENROUTER_BASE = "https://api.kilo.ai/api/openrouter" /** Device auth polling interval in milliseconds */ export const POLL_INTERVAL_MS = 3000 -/** Default model to use as fallback */ +/** Default model for authenticated users */ export const DEFAULT_MODEL = "anthropic/claude-sonnet-4" +/** Default model for anonymous/free usage */ +export const DEFAULT_FREE_MODEL = "minimax/minimax-m2.1:free" + /** Token expiration duration in milliseconds (1 year) */ export const TOKEN_EXPIRATION_MS = 365 * 24 * 60 * 60 * 1000 diff --git a/packages/kilo-gateway/src/api/profile.ts b/packages/kilo-gateway/src/api/profile.ts index 343c2e9048..506ac119de 100644 --- a/packages/kilo-gateway/src/api/profile.ts +++ b/packages/kilo-gateway/src/api/profile.ts @@ -1,6 +1,6 @@ import { select } from "@clack/prompts" import type { KilocodeProfile, Organization, KilocodeBalance } from "../types.js" -import { KILO_API_BASE, DEFAULT_MODEL } from "./constants.js" +import { KILO_API_BASE, DEFAULT_MODEL, DEFAULT_FREE_MODEL } from "./constants.js" /** * Fetch user profile from Kilo API @@ -106,6 +106,33 @@ export async function fetchDefaultModel(token: string, organizationId?: string): */ export const getKiloDefaultModel = fetchDefaultModel +/** + * Fetch default free model for anonymous usage (no authentication required) + */ +export async function fetchDefaultFreeModel(): Promise { + try { + const response = await fetch(`${KILO_API_BASE}/api/defaults`, { + headers: { + "Content-Type": "application/json", + }, + }) + + if (!response.ok) { + return DEFAULT_FREE_MODEL + } + + const data = (await response.json()) as { defaultFreeModel?: string } + return data.defaultFreeModel || DEFAULT_FREE_MODEL + } catch { + return DEFAULT_FREE_MODEL + } +} + +/** + * Alias for compatibility + */ +export const getKiloDefaultFreeModel = fetchDefaultFreeModel + /** * Fetch both profile and balance in parallel */ diff --git a/packages/kilo-gateway/src/index.ts b/packages/kilo-gateway/src/index.ts index b23171f10d..4534d1f257 100644 --- a/packages/kilo-gateway/src/index.ts +++ b/packages/kilo-gateway/src/index.ts @@ -27,9 +27,11 @@ export { fetchBalance, fetchProfileWithBalance, fetchDefaultModel, + fetchDefaultFreeModel, getKiloProfile, getKiloBalance, getKiloDefaultModel, + getKiloDefaultFreeModel, promptOrganizationSelection, } from "./api/profile.js" export { fetchKiloModels } from "./api/models.js" @@ -74,6 +76,7 @@ export { KILO_OPENROUTER_BASE, POLL_INTERVAL_MS, DEFAULT_MODEL, + DEFAULT_FREE_MODEL, TOKEN_EXPIRATION_MS, USER_AGENT, CONTENT_TYPE, diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index d4d556485d..c45a9cb56b 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -37,6 +37,7 @@ import { Config } from "@/config/config" import { Todo } from "@/session/todo" import { z } from "zod" import { LoadAPIKeyError } from "ai" +import { fetchDefaultFreeModel } from "@kilocode/kilo-gateway" // kilocode_change import type { Event, OpencodeClient, SessionMessageResponse } from "@opencode-ai/sdk/v2" import { applyPatch } from "diff" @@ -1359,12 +1360,10 @@ export namespace ACP { if (specified && !providers.length) return specified - const opencodeProvider = providers.find((p) => p.id === "opencode") - if (opencodeProvider) { - if (opencodeProvider.models["big-pickle"]) { - return { providerID: "opencode", modelID: "big-pickle" } - } - const [best] = Provider.sort(Object.values(opencodeProvider.models)) + // kilocode_change start + const kiloProvider = providers.find((p) => p.id === "kilo") + if (kiloProvider) { + const [best] = Provider.sort(Object.values(kiloProvider.models)) if (best) { return { providerID: best.providerID, @@ -1372,6 +1371,7 @@ export namespace ACP { } } } + // kilocode_change end const models = providers.flatMap((p) => Object.values(p.models)) const [best] = Provider.sort(models) @@ -1384,7 +1384,11 @@ export namespace ACP { if (specified) return specified - return { providerID: "opencode", modelID: "big-pickle" } + // kilocode_change start + const freeModel = await fetchDefaultFreeModel() + const parsed = Provider.parseModel(freeModel) + return { providerID: "kilo", modelID: parsed.modelID } + // kilocode_change end } function parseUri( diff --git a/packages/opencode/src/cli/cmd/models.ts b/packages/opencode/src/cli/cmd/models.ts index 156dae91c6..7a650cd79b 100644 --- a/packages/opencode/src/cli/cmd/models.ts +++ b/packages/opencode/src/cli/cmd/models.ts @@ -60,13 +60,15 @@ export const ModelsCommand = cmd({ return } + // kilocode_change start const providerIDs = Object.keys(providers).sort((a, b) => { - const aIsOpencode = a.startsWith("opencode") - const bIsOpencode = b.startsWith("opencode") - if (aIsOpencode && !bIsOpencode) return -1 - if (!aIsOpencode && bIsOpencode) return 1 + const aIsKilo = a === "kilo" || a.startsWith("opencode") + const bIsKilo = b === "kilo" || b.startsWith("opencode") + if (aIsKilo && !bIsKilo) return -1 + if (!aIsKilo && bIsKilo) return 1 return a.localeCompare(b) }) + // kilocode_change end for (const providerID of providerIDs) { printModels(providerID, args.verbose) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx index 88ecbff90f..956a19fc94 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx @@ -17,11 +17,11 @@ import { KiloAutoMethod } from "@kilocode/kilo-gateway/tui" // kilocode_change const PROVIDER_PRIORITY: Record = { kilo: -1, // kilocode_change - Kilo Gateway at top - opencode: 0, - anthropic: 1, - "github-copilot": 2, - openai: 3, - google: 4, + // kilocode_change - removed opencode from popular providers + anthropic: 0, + "github-copilot": 1, + openai: 2, + google: 3, } export function createDialogProviderOptions() { @@ -40,7 +40,6 @@ export function createDialogProviderOptions() { value: provider.id, description: { kilo: "(Recommended)", // kilocode_change - opencode: "(Recommended)", anthropic: "(Claude Max or API key)", openai: "(ChatGPT Plus/Pro or API key)", }[provider.id], diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index 8fd0d6204e..f06bf150ca 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -101,28 +101,6 @@ export namespace Provider { }, } }, - async opencode(input) { - const hasKey = await (async () => { - const env = Env.all() - if (input.env.some((item) => env[item])) return true - if (await Auth.get(input.id)) return true - const config = await Config.get() - if (config.provider?.["opencode"]?.options?.apiKey) return true - return false - })() - - if (!hasKey) { - for (const [key, value] of Object.entries(input.models)) { - if (value.cost.input === 0) continue - delete input.models[key] - } - } - - return { - autoload: Object.keys(input.models).length > 0, - options: hasKey ? {} : { apiKey: "public" }, - } - }, openai: async () => { return { autoload: false, @@ -400,6 +378,16 @@ export namespace Provider { }, } }, + // kilocode_change start - prevent opencode zen from auto-connecting without credentials + opencode: async () => { + return { + autoload: false, + options: { + headers: DEFAULT_HEADERS, + }, + } + }, + // kilocode_change end gitlab: async (input) => { const instanceUrl = Env.get("GITLAB_INSTANCE_URL") || "https://gitlab.com" @@ -1163,9 +1151,11 @@ export namespace Provider { "gemini-2.5-flash", "gpt-5-nano", ] - if (providerID.startsWith("opencode")) { + // kilocode_change start + if (providerID.startsWith("kilo")) { priority = ["gpt-5-nano"] } + // kilocode_change end if (providerID.startsWith("github-copilot")) { // prioritize free models for github copilot priority = ["gpt-5-mini", "claude-haiku-4.5", ...priority] @@ -1177,11 +1167,13 @@ export namespace Provider { } } - // Check if opencode provider is available before using it - const opencodeProvider = await state().then((state) => state.providers["opencode"]) - if (opencodeProvider && opencodeProvider.models["gpt-5-nano"]) { - return getModel("opencode", "gpt-5-nano") + // kilocode_change start + // Check if kilo provider is available before using it + const kiloProvider = await state().then((state) => state.providers["kilo"]) + if (kiloProvider && kiloProvider.models["gpt-5-nano"]) { + return getModel("kilo", "gpt-5-nano") } + // kilocode_change end return undefined } diff --git a/packages/opencode/src/server/routes/config.ts b/packages/opencode/src/server/routes/config.ts index 85d28f6aa6..9f2fa3d4be 100644 --- a/packages/opencode/src/server/routes/config.ts +++ b/packages/opencode/src/server/routes/config.ts @@ -7,6 +7,10 @@ import { mapValues } from "remeda" import { errors } from "../error" import { Log } from "../../util/log" import { lazy } from "../../util/lazy" +// kilocode_change start +import { fetchDefaultModel, fetchDefaultFreeModel } from "@kilocode/kilo-gateway" +import { Auth } from "../../auth" +// kilocode_change end const log = Log.create({ service: "server" }) @@ -82,10 +86,34 @@ export const ConfigRoutes = lazy(() => }), async (c) => { using _ = log.time("providers") - const providers = await Provider.list().then((x) => mapValues(x, (item) => item)) + const providers = await Provider.list() + + // kilocode_change start - Fetch default model from Kilo API + let kiloApiDefault: string | undefined + try { + const kiloAuth = await Auth.get("kilo") + if (kiloAuth) { + const token = kiloAuth.type === "oauth" ? kiloAuth.access : kiloAuth.key + const organizationId = kiloAuth.type === "oauth" ? kiloAuth.accountId : undefined + kiloApiDefault = await fetchDefaultModel(token, organizationId) + } else { + kiloApiDefault = await fetchDefaultFreeModel() + } + } catch { + // Fall back to Provider.sort() on API failure + } + // kilocode_change end + + // kilocode_change start - Use API default for Kilo provider if valid + const defaults = mapValues(providers, (item) => Provider.sort(Object.values(item.models))[0].id) + if (kiloApiDefault && providers["kilo"]?.models[kiloApiDefault]) { + defaults["kilo"] = kiloApiDefault + } + // kilocode_change end + return c.json({ providers: Object.values(providers), - default: mapValues(providers, (item) => Provider.sort(Object.values(item.models))[0].id), + default: defaults, }) }, ), diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts index faa5f72bcc..95e440f124 100644 --- a/packages/opencode/src/tool/registry.ts +++ b/packages/opencode/src/tool/registry.ts @@ -132,10 +132,12 @@ export namespace ToolRegistry { const result = await Promise.all( tools .filter((t) => { - // Enable websearch/codesearch for zen users OR via enable flag + // Enable websearch/codesearch for zen/kilo users OR via enable flag + // kilocode_change start if (t.id === "codesearch" || t.id === "websearch") { - return model.providerID === "opencode" || Flag.OPENCODE_ENABLE_EXA + return model.providerID === "opencode" || model.providerID === "kilo" || Flag.OPENCODE_ENABLE_EXA } + // kilocode_change end // use apply tool in same format as codex const usePatch = From f2c17920b8bdd3ce15d31cc98261b8d0eb5b3493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Wed, 28 Jan 2026 11:34:43 +0100 Subject: [PATCH 2/2] refactor: unify default model function --- packages/kilo-gateway/src/api/profile.ts | 62 +++++++------------ packages/kilo-gateway/src/index.ts | 2 - packages/opencode/src/acp/agent.ts | 4 +- packages/opencode/src/server/routes/config.ts | 19 ++---- 4 files changed, 28 insertions(+), 59 deletions(-) diff --git a/packages/kilo-gateway/src/api/profile.ts b/packages/kilo-gateway/src/api/profile.ts index 506ac119de..aa717a64c4 100644 --- a/packages/kilo-gateway/src/api/profile.ts +++ b/packages/kilo-gateway/src/api/profile.ts @@ -77,27 +77,34 @@ export const getKiloBalance = fetchBalance /** * Fetch default model for a given organization context + * When token is provided, returns the authenticated user's default model + * When no token is provided, returns the default free model for anonymous usage */ -export async function fetchDefaultModel(token: string, organizationId?: string): Promise { +export async function fetchDefaultModel(token?: string, organizationId?: string): Promise { const path = organizationId ? `/api/organizations/${organizationId}/defaults` : `/api/defaults` const url = `${KILO_API_BASE}${path}` try { - const response = await fetch(url, { - headers: { - Authorization: `Bearer ${token}`, - "Content-Type": "application/json", - }, - }) - - if (!response.ok) { - return DEFAULT_MODEL + const headers: Record = { + "Content-Type": "application/json", + } + if (token) { + headers.Authorization = `Bearer ${token}` } - const data = (await response.json()) as { defaultModel?: string } - return data.defaultModel || DEFAULT_MODEL - } catch (error) { - return DEFAULT_MODEL + const response = await fetch(url, { headers }) + + if (!response.ok) { + return token ? DEFAULT_MODEL : DEFAULT_FREE_MODEL + } + + const data = (await response.json()) as { defaultModel?: string; defaultFreeModel?: string } + if (token) { + return data.defaultModel || DEFAULT_MODEL + } + return data.defaultFreeModel || DEFAULT_FREE_MODEL + } catch { + return token ? DEFAULT_MODEL : DEFAULT_FREE_MODEL } } @@ -106,33 +113,6 @@ export async function fetchDefaultModel(token: string, organizationId?: string): */ export const getKiloDefaultModel = fetchDefaultModel -/** - * Fetch default free model for anonymous usage (no authentication required) - */ -export async function fetchDefaultFreeModel(): Promise { - try { - const response = await fetch(`${KILO_API_BASE}/api/defaults`, { - headers: { - "Content-Type": "application/json", - }, - }) - - if (!response.ok) { - return DEFAULT_FREE_MODEL - } - - const data = (await response.json()) as { defaultFreeModel?: string } - return data.defaultFreeModel || DEFAULT_FREE_MODEL - } catch { - return DEFAULT_FREE_MODEL - } -} - -/** - * Alias for compatibility - */ -export const getKiloDefaultFreeModel = fetchDefaultFreeModel - /** * Fetch both profile and balance in parallel */ diff --git a/packages/kilo-gateway/src/index.ts b/packages/kilo-gateway/src/index.ts index 4534d1f257..c1ce3e7c6d 100644 --- a/packages/kilo-gateway/src/index.ts +++ b/packages/kilo-gateway/src/index.ts @@ -27,11 +27,9 @@ export { fetchBalance, fetchProfileWithBalance, fetchDefaultModel, - fetchDefaultFreeModel, getKiloProfile, getKiloBalance, getKiloDefaultModel, - getKiloDefaultFreeModel, promptOrganizationSelection, } from "./api/profile.js" export { fetchKiloModels } from "./api/models.js" diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index c45a9cb56b..db3f7ae4e3 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -37,7 +37,7 @@ import { Config } from "@/config/config" import { Todo } from "@/session/todo" import { z } from "zod" import { LoadAPIKeyError } from "ai" -import { fetchDefaultFreeModel } from "@kilocode/kilo-gateway" // kilocode_change +import { fetchDefaultModel } from "@kilocode/kilo-gateway" // kilocode_change import type { Event, OpencodeClient, SessionMessageResponse } from "@opencode-ai/sdk/v2" import { applyPatch } from "diff" @@ -1385,7 +1385,7 @@ export namespace ACP { if (specified) return specified // kilocode_change start - const freeModel = await fetchDefaultFreeModel() + const freeModel = await fetchDefaultModel() const parsed = Provider.parseModel(freeModel) return { providerID: "kilo", modelID: parsed.modelID } // kilocode_change end diff --git a/packages/opencode/src/server/routes/config.ts b/packages/opencode/src/server/routes/config.ts index 9f2fa3d4be..e6ac26bb0d 100644 --- a/packages/opencode/src/server/routes/config.ts +++ b/packages/opencode/src/server/routes/config.ts @@ -8,7 +8,7 @@ import { errors } from "../error" import { Log } from "../../util/log" import { lazy } from "../../util/lazy" // kilocode_change start -import { fetchDefaultModel, fetchDefaultFreeModel } from "@kilocode/kilo-gateway" +import { fetchDefaultModel } from "@kilocode/kilo-gateway" import { Auth } from "../../auth" // kilocode_change end @@ -89,19 +89,10 @@ export const ConfigRoutes = lazy(() => const providers = await Provider.list() // kilocode_change start - Fetch default model from Kilo API - let kiloApiDefault: string | undefined - try { - const kiloAuth = await Auth.get("kilo") - if (kiloAuth) { - const token = kiloAuth.type === "oauth" ? kiloAuth.access : kiloAuth.key - const organizationId = kiloAuth.type === "oauth" ? kiloAuth.accountId : undefined - kiloApiDefault = await fetchDefaultModel(token, organizationId) - } else { - kiloApiDefault = await fetchDefaultFreeModel() - } - } catch { - // Fall back to Provider.sort() on API failure - } + const kiloAuth = await Auth.get("kilo") + const token = kiloAuth?.type === "oauth" ? kiloAuth.access : kiloAuth?.key + const organizationId = kiloAuth?.type === "oauth" ? kiloAuth.accountId : undefined + const kiloApiDefault = await fetchDefaultModel(token, organizationId) // kilocode_change end // kilocode_change start - Use API default for Kilo provider if valid