Refactor from monolithic proxy to multi-backend architecture (Backend interface: OpenCode Zen + Kilo gateway). - Add auto rate-limit jailing: models returning HTTP 429 are hidden from /v1/models immediately and re-probed every 30 min - Backend interface supports model aliases, custom headers, and per-backend routing - Full Anthropic Messages API support with OpenAI format conversion - 9 free models across two backends with Claude name aliases
92 lines
3.0 KiB
Go
92 lines
3.0 KiB
Go
package proxy
|
|
|
|
// KiloGatewayBase is the Kilo Code public gateway base URL.
|
|
// Confirmed working without auth for free models (HTTP 200 on both
|
|
// GET /api/gateway/models and POST /api/gateway/chat/completions).
|
|
const KiloGatewayBase = "https://api.kilo.ai/api/gateway"
|
|
|
|
// KiloBackend forwards to Kilo Code's free gateway models.
|
|
//
|
|
// Kilo is an opencode-based CLI whose gateway exposes a handful of free models
|
|
// (suffixed ":free") reachable without authentication, in standard OpenAI
|
|
// Chat Completions format.
|
|
type KiloBackend struct{}
|
|
|
|
// kiloFreeModels are the free models advertised by the Kilo gateway.
|
|
// Sourced from GET /api/gateway/models filtering isFree:true.
|
|
var kiloFreeModels = []ModelInfo{
|
|
{
|
|
ID: "stepfun/step-3.7-flash:free",
|
|
Name: "StepFun Step 3.7 Flash (Free)",
|
|
OwnedBy: "stepfun",
|
|
ContextWindow: 256_000,
|
|
MaxOutputTokens: 32_000,
|
|
Description: "StepFun. Flash rápido, tareas generales.",
|
|
},
|
|
{
|
|
ID: "poolside/laguna-m.1:free",
|
|
Name: "Poolside Laguna M.1 (Free)",
|
|
OwnedBy: "poolside",
|
|
ContextWindow: 256_000,
|
|
MaxOutputTokens: 32_000,
|
|
Description: "Poolside. Modelo orientado a código.",
|
|
},
|
|
{
|
|
ID: "nvidia/nemotron-3-ultra-550b-a55b:free",
|
|
Name: "Nemotron 3 Ultra 550B (Free)",
|
|
OwnedBy: "nvidia",
|
|
ContextWindow: 1_000_000,
|
|
MaxOutputTokens: 16_384,
|
|
Description: "NVIDIA Nemotron 3 Ultra (550B/55B MoE). 1M contexto, razonamiento.",
|
|
},
|
|
{
|
|
ID: "openrouter/free",
|
|
Name: "OpenRouter Best Free (Free)",
|
|
OwnedBy: "openrouter",
|
|
ContextWindow: 256_000,
|
|
MaxOutputTokens: 32_000,
|
|
Description: "OpenRouter selecciona automáticamente el mejor modelo free disponible.",
|
|
},
|
|
}
|
|
|
|
// kiloAliases lets clients use shorter names for Kilo free models.
|
|
var kiloAliases = map[string]string{
|
|
"stepfun": "stepfun/step-3.7-flash:free",
|
|
"stepfun-free": "stepfun/step-3.7-flash:free",
|
|
"poolside": "poolside/laguna-m.1:free",
|
|
"poolside-free": "poolside/laguna-m.1:free",
|
|
"laguna": "poolside/laguna-m.1:free",
|
|
"openrouter": "openrouter/free",
|
|
}
|
|
|
|
// Name returns the backend identifier.
|
|
func (KiloBackend) Name() string { return "kilo" }
|
|
|
|
// Models returns the Kilo free models.
|
|
func (KiloBackend) Models() []ModelInfo { return kiloFreeModels }
|
|
|
|
// Resolve maps a requested name to a Kilo free model ID.
|
|
func (KiloBackend) Resolve(model string) (string, bool) {
|
|
if mapped, ok := kiloAliases[model]; ok {
|
|
return mapped, true
|
|
}
|
|
for _, m := range kiloFreeModels {
|
|
if m.ID == model {
|
|
return model, true
|
|
}
|
|
}
|
|
return "", false
|
|
}
|
|
|
|
// ChatURL is the Kilo gateway chat completions endpoint.
|
|
func (KiloBackend) ChatURL() string { return KiloGatewayBase + "/chat/completions" }
|
|
|
|
// Headers returns minimal headers for the Kilo gateway (no auth needed for free).
|
|
func (KiloBackend) Headers(_, _ string) map[string]string {
|
|
return map[string]string{
|
|
"Content-Type": "application/json",
|
|
"Accept": "text/event-stream, application/json",
|
|
"User-Agent": "kilo/7.3.54",
|
|
}
|
|
}
|