Ir al contenido

Diseño de Integración del Proveedor Kilo Gateway

Diseño de Integración del Proveedor Kilo Gateway

Sección titulada «Diseño de Integración del Proveedor Kilo Gateway»

Este documento describe el diseño para integrar “Kilo Gateway” como un proveedor de primera clase en OpenClaw, modelado según la implementación existente de OpenRouter. Kilo Gateway utiliza una API de completado compatible con OpenAI con una URL base diferente.

Recomendación: kilocode

Justificación:

  • Coincide con el ejemplo de configuración de usuario proporcionado (clave de proveedor kilocode)
  • Coherente con los patrones de nomenclatura de proveedores existentes (por ejemplo, openrouter, opencode, moonshot)
  • Corto y memorable
  • Evita la confusión con los términos genéricos “kilo” o “gateway”

Alternativa considerada: kilo-gateway - rechazada porque los nombres con guiones son menos comunes en la base de código y kilocode es más conciso.

Recomendación: kilocode/anthropic/claude-opus-4.6

Justificación:

  • Basado en el ejemplo de configuración de usuario
  • Claude Opus 4.5 es un modelo predeterminado capaz
  • La selección explícita del modelo evita la dependencia del enrutamiento automático

Recomendación: Predeterminado codificado con anulación de configuración

  • URL Base Predeterminada: https://api.kilo.ai/api/gateway/
  • Configurable: Sí, a través de models.providers.kilocode.baseUrl

Esto coincide con el patrón utilizado por otros proveedores como Moonshot, Venice y Synthetic.

Recomendación: Sin punto final dedicado para el escaneo de modelos inicialmente

Justificación:

  • Kilo Gateway actúa como proxy para OpenRouter, por lo que los modelos son dinámicos
  • Los usuarios pueden configurar manualmente los modelos en su configuración
  • Si Kilo Gateway expone un punto final /models en el futuro, se puede añadir el escaneo

Recomendación: Heredar el comportamiento de OpenRouter para los modelos de Anthropic

Dado que Kilo Gateway actúa como proxy para OpenRouter, se debe aplicar el mismo manejo especial:

  • Elegibilidad para TTL de caché para modelos anthropic/*
  • Parámetros adicionales (cacheControlTtl) para modelos anthropic/*
  • La política de transcripciones sigue los patrones de OpenRouter

Añadir:

export const KILOCODE_DEFAULT_MODEL_REF = "kilocode/anthropic/claude-opus-4.6";
export async function setKilocodeApiKey(key: string, agentDir?: string) {
upsertAuthProfile({
profileId: "kilocode:default",
credential: {
type: "api_key",
provider: "kilocode",
key,
},
agentDir: resolveAuthAgentDir(agentDir),
});
}

Añadir a envMap en resolveEnvApiKey():

const envMap: Record<string, string> = {
// ... existing entries
kilocode: "KILOCODE_API_KEY",
};

Añadir a SHELL_ENV_EXPECTED_KEYS:

const SHELL_ENV_EXPECTED_KEYS = [
// ... existing entries
"KILOCODE_API_KEY",
];

Añadir nuevas funciones:

export const KILOCODE_BASE_URL = "https://api.kilo.ai/api/gateway/";
export function applyKilocodeProviderConfig(cfg: OpenClawConfig): OpenClawConfig {
const models = { ...cfg.agents?.defaults?.models };
models[KILOCODE_DEFAULT_MODEL_REF] = {
...models[KILOCODE_DEFAULT_MODEL_REF],
alias: models[KILOCODE_DEFAULT_MODEL_REF]?.alias ?? "Kilo Gateway",
};
const providers = { ...cfg.models?.providers };
const existingProvider = providers.kilocode;
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record<string, unknown> as { apiKey?: string };
const resolvedApiKey = typeof existingApiKey === "string" ? existingApiKey : undefined;
const normalizedApiKey = resolvedApiKey?.trim();
providers.kilocode = {
...existingProviderRest,
baseUrl: KILOCODE_BASE_URL,
api: "openai-completions",
...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}),
};
return {
...cfg,
agents: {
...cfg.agents,
defaults: {
...cfg.agents?.defaults,
models,
},
},
models: {
mode: cfg.models?.mode ?? "merge",
providers,
},
};
}
export function applyKilocodeConfig(cfg: OpenClawConfig): OpenClawConfig {
const next = applyKilocodeProviderConfig(cfg);
const existingModel = next.agents?.defaults?.model;
return {
...next,
agents: {
...next.agents,
defaults: {
...next.agents?.defaults,
model: {
...(existingModel && "fallbacks" in (existingModel as Record<string, unknown>)
? {
fallbacks: (existingModel as { fallbacks?: string[] }).fallbacks,
}
: undefined),
primary: KILOCODE_DEFAULT_MODEL_REF,
},
},
},
};
}

Añadir al tipo AuthChoice:

export type AuthChoice =
// ... existing choices
"kilocode-api-key";
// ...

Añadir a OnboardOptions:

export type OnboardOptions = {
// ... existing options
kilocodeApiKey?: string;
// ...
};

Añadir a AuthChoiceGroupId:

export type AuthChoiceGroupId =
// ... existing groups
"kilocode";
// ...

Añadir a AUTH_CHOICE_GROUP_DEFS:

{
value: "kilocode",
label: "Kilo Gateway",
hint: "API key (OpenRouter-compatible)",
choices: ["kilocode-api-key"],
},

Añadir a buildAuthChoiceOptions():

options.push({
value: "kilocode-api-key",
label: "Kilo Gateway API key",
hint: "OpenRouter-compatible gateway",
});

7. src/commands/auth-choice.preferred-provider.ts

Sección titulada «7. src/commands/auth-choice.preferred-provider.ts»

Añadir mapeo:

const PREFERRED_PROVIDER_BY_AUTH_CHOICE: Partial<Record<AuthChoice, string>> = {
// ... existing mappings
"kilocode-api-key": "kilocode",
};

8. src/commands/auth-choice.apply.api-providers.ts

Sección titulada «8. src/commands/auth-choice.apply.api-providers.ts»

Añadir importación:

import {
// ... existing imports
applyKilocodeConfig,
applyKilocodeProviderConfig,
KILOCODE_DEFAULT_MODEL_REF,
setKilocodeApiKey,
} from "./onboard-auth.js";

Añadir manejo para kilocode-api-key:

if (authChoice === "kilocode-api-key") {
const store = ensureAuthProfileStore(params.agentDir, {
allowKeychainPrompt: false,
});
const profileOrder = resolveAuthProfileOrder({
cfg: nextConfig,
store,
provider: "kilocode",
});
const existingProfileId = profileOrder.find((profileId) => Boolean(store.profiles[profileId]));
const existingCred = existingProfileId ? store.profiles[existingProfileId] : undefined;
let profileId = "kilocode:default";
let mode: "api_key" | "oauth" | "token" = "api_key";
let hasCredential = false;
if (existingProfileId && existingCred?.type) {
profileId = existingProfileId;
mode = existingCred.type === "oauth" ? "oauth" : existingCred.type === "token" ? "token" : "api_key";
hasCredential = true;
}
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "kilocode") {
await setKilocodeApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
if (!hasCredential) {
const envKey = resolveEnvApiKey("kilocode");
if (envKey) {
const useExisting = await params.prompter.confirm({
message: `Use existing KILOCODE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true,
});
if (useExisting) {
await setKilocodeApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Kilo Gateway API key",
validate: validateApiKeyInput,
});
await setKilocodeApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
hasCredential = true;
}
if (hasCredential) {
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId,
provider: "kilocode",
mode,
});
}
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: KILOCODE_DEFAULT_MODEL_REF,
applyDefaultConfig: applyKilocodeConfig,
applyProviderConfig: applyKilocodeProviderConfig,
noteDefault: KILOCODE_DEFAULT_MODEL_REF,
noteAgentModel,
prompter: params.prompter,
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return { config: nextConfig, agentModelOverride };
}

También añadir el mapeo tokenProvider en la parte superior de la función:

if (params.opts.tokenProvider === "kilocode") {
authChoice = "kilocode-api-key";
}

Añadir opción CLI:

.option("--kilocode-api-key <key>", "Kilo Gateway API key")

Añadir al controlador de acciones:

kilocodeApiKey: opts.kilocodeApiKey as string | undefined,

Actualizar texto de ayuda de auth-choice:

.option(
"--auth-choice <choice>",
"Auth: setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|kilocode-api-key|ai-gateway-api-key|...",
)

10. src/commands/onboard-non-interactive/local/auth-choice.ts

Sección titulada «10. src/commands/onboard-non-interactive/local/auth-choice.ts»

Añadir manejo para kilocode-api-key:

if (authChoice === "kilocode-api-key") {
const resolved = await resolveNonInteractiveApiKey({
provider: "kilocode",
cfg: baseConfig,
flagValue: opts.kilocodeApiKey,
flagName: "--kilocode-api-key",
envVar: "KILOCODE_API_KEY",
});
await setKilocodeApiKey(resolved.apiKey, agentDir);
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "kilocode:default",
provider: "kilocode",
mode: "api_key",
});
// ... apply default model
}

Añadir exportaciones:

export {
// ... existing exports
applyKilocodeConfig,
applyKilocodeProviderConfig,
KILOCODE_BASE_URL,
} from "./onboard-auth.config-core.js";
export {
// ... existing exports
KILOCODE_DEFAULT_MODEL_REF,
setKilocodeApiKey,
} from "./onboard-auth.credentials.js";

12. src/agents/pi-embedded-runner/cache-ttl.ts

Sección titulada «12. src/agents/pi-embedded-runner/cache-ttl.ts»

Añadir soporte de Kilo Gateway para modelos de Anthropic:

export function isCacheTtlEligibleProvider(provider: string, modelId: string): boolean {
const normalizedProvider = provider.toLowerCase();
const normalizedModelId = modelId.toLowerCase();
if (normalizedProvider === "anthropic") return true;
if (normalizedProvider === "openrouter" && normalizedModelId.startsWith("anthropic/")) return true;
if (normalizedProvider === "kilocode" && normalizedModelId.startsWith("anthropic/")) return true;
return false;
}

Añadir manejo de Kilo Gateway (similar a OpenRouter):

const isKilocodeGemini = provider === "kilocode" && modelId.toLowerCase().includes("gemini");
// Include in needsNonImageSanitize check
const needsNonImageSanitize = isGoogle || isAnthropic || isMistral || isOpenRouterGemini || isKilocodeGemini;
{
"models": {
"mode": "merge",
"providers": {
"kilocode": {
"baseUrl": "https://api.kilo.ai/api/gateway/",
"apiKey": "xxxxx",
"api": "openai-completions",
"models": [
{
"id": "anthropic/claude-opus-4.6",
"name": "Anthropic: Claude Opus 4.6"
},
{ "id": "minimax/minimax-m2.5:free", "name": "Minimax: Minimax M2.5" }
]
}
}
}
}
{
"profiles": {
"kilocode:default": {
"type": "api_key",
"provider": "kilocode",
"key": "xxxxx"
}
}
}
  1. Pruebas Unitarias:

    • Probar que setKilocodeApiKey() escribe el perfil correcto
    • Probar que applyKilocodeConfig() establece los valores predeterminados correctos
    • Probar que resolveEnvApiKey("kilocode") devuelve la variable de entorno correcta
  2. Pruebas de Integración:

    • Probar el flujo de configuración con --auth-choice kilocode-api-key
    • Probar la configuración no interactiva con --kilocode-api-key
    • Probar la selección de modelo con el prefijo kilocode/
  3. Pruebas E2E:

    • Probar llamadas reales a la API a través de Kilo Gateway (pruebas en vivo)
  • No se necesita migración para los usuarios existentes
  • Los usuarios nuevos pueden usar inmediatamente la elección de autenticación kilocode-api-key
  • La configuración manual existente con el proveedor kilocode continuará funcionando
  1. Catálogo de Modelos: Si Kilo Gateway expone un endpoint /models, añada soporte de escaneo similar a scanOpenRouterModels()

  2. Soporte OAuth: Si Kilo Gateway añade OAuth, extienda el sistema de autenticación en consecuencia

  3. Limitación de Tasa: Considere añadir manejo de límites de tasa específico para Kilo Gateway si es necesario

  4. Documentación: Añada documentación en docs/providers/kilocode.md explicando la configuración y el uso

ArchivoTipo de CambioDescripción
src/commands/onboard-auth.credentials.tsAñadirKILOCODE_DEFAULT_MODEL_REF, setKilocodeApiKey()
src/agents/model-auth.tsModificarAñadir kilocode a envMap
src/config/io.tsModificarAñadir KILOCODE_API_KEY a las claves de entorno del shell
src/commands/onboard-auth.config-core.tsAñadirapplyKilocodeProviderConfig(), applyKilocodeConfig()
src/commands/onboard-types.tsModificarAñadir kilocode-api-key a AuthChoice, añadir kilocodeApiKey a las opciones
src/commands/auth-choice-options.tsModificarAñadir grupo y opción kilocode
src/commands/auth-choice.preferred-provider.tsModificarAñadir mapeo kilocode-api-key
src/commands/auth-choice.apply.api-providers.tsModificarAñadir manejo kilocode-api-key
src/cli/program/register.onboard.tsModificarAñadir opción --kilocode-api-key
src/commands/onboard-non-interactive/local/auth-choice.tsModificarAñadir manejo no interactivo
src/commands/onboard-auth.tsModificarExportar nuevas funciones
src/agents/pi-embedded-runner/cache-ttl.tsModificarAñadir soporte para kilocode
src/agents/transcript-policy.tsModificarAñadir manejo de Gemini para kilocode