feat: anon kilo gateway

This commit is contained in:
Catriel Müller
2026-01-28 10:22:54 +01:00
parent 579ad5819e
commit 537289326b
25 changed files with 202 additions and 137 deletions
+1 -5
View File
@@ -4,11 +4,7 @@
// "enterprise": {
// "url": "https://enterprise.dev.opencode.ai",
// },
"provider": {
"opencode": {
"options": {},
},
},
"provider": {},
"mcp": {
"context7": {
"type": "remote",
@@ -244,23 +244,25 @@ export function DialogConnectProvider(props: { provider: string }) {
return (
<div class="flex flex-col gap-6">
<Switch>
<Match when={provider().id === "opencode"}>
{/* kilocode_change start */}
<Match when={provider().id === "kilo"}>
<div class="flex flex-col gap-4">
<div class="text-14-regular text-text-base">
{language.t("provider.connect.opencodeZen.line1")}
{language.t("provider.connect.kiloGateway.line1")}
</div>
<div class="text-14-regular text-text-base">
{language.t("provider.connect.opencodeZen.line2")}
{language.t("provider.connect.kiloGateway.line2")}
</div>
<div class="text-14-regular text-text-base">
{language.t("provider.connect.opencodeZen.visit.prefix")}
<Link href="https://opencode.ai/zen" tabIndex={-1}>
{language.t("provider.connect.opencodeZen.visit.link")}
{language.t("provider.connect.kiloGateway.visit.prefix")}
<Link href="https://kilo.ai" tabIndex={-1}>
{language.t("provider.connect.kiloGateway.visit.link")}
</Link>
{language.t("provider.connect.opencodeZen.visit.suffix")}
{language.t("provider.connect.kiloGateway.visit.suffix")}
</div>
</div>
</Match>
{/* kilocode_change end */}
<Match when={true}>
<div class="text-14-regular text-text-base">
{language.t("provider.connect.apiKey.description", { provider: provider().name })}
+6 -6
View File
@@ -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":
+6 -6
View File
@@ -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":
+6 -5
View File
@@ -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":
+6 -5
View File
@@ -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":
+6 -6
View File
@@ -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":
+6 -5
View File
@@ -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":
+6 -5
View File
@@ -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":
+6 -5
View File
@@ -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":
+6 -5
View File
@@ -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":
+6 -6
View File
@@ -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":
+6 -6
View File
@@ -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":
+6 -6
View File
@@ -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":
+5 -4
View File
@@ -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}} 模型。",
+5 -5
View File
@@ -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}} 模型。",
+4 -1
View File
@@ -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
+28 -1
View File
@@ -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<string> {
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
*/
+3
View File
@@ -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,
+11 -7
View File
@@ -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(
+6 -4
View File
@@ -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)
@@ -17,11 +17,11 @@ import { KiloAutoMethod } from "@kilocode/kilo-gateway/tui" // kilocode_change
const PROVIDER_PRIORITY: Record<string, number> = {
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],
+19 -27
View File
@@ -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
}
+30 -2
View File
@@ -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,
})
},
),
+4 -2
View File
@@ -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 =