Files
free-ide-proxy/KIMCHI_ANALISIS.md
renato97 46127431a3 feat(proxy): auto-discovery de modelos + backend Kimchi
- Nueva interfaz Discoverer con Refresh() por backend
- Kilo: full auto (isFree + metadata completa del upstream)
- OpenCode: heurística -free para descubrir nuevos free
- Kimchi: agrega todos los IDs no-curados del upstream
- discoveryLoop cada 10 min en el Proxy
- Backends stateful (mutex + catálogo dinámico)
- CREDENCIALES.md y KIMCHI_ANALISIS.md documentan el setup
2026-07-12 19:58:30 -03:00

276 lines
8.8 KiB
Markdown

# Kimchi Dev — Análisis Completo para Integración en Free IDE Proxy
## 1. Instalación
```bash
which kimchi
# /home/ren/.local/bin/kimchi
```
## 2. Configuración Local
### Archivos relevantes
| Archivo | Propósito |
|---------|-----------|
| `~/.config/kimchi/config.json` | Config principal: apiKey, skillPaths, deviceId, onboarding |
| `~/.config/kimchi/harness/models.json` | Definiciones de proveedores y modelos |
| `~/.config/kimchi/harness/settings.json` | Settings: defaultProvider, defaultModel, multiModel, etc. |
| `~/.config/kimchi/harness/auth.json` | Auth por proveedor (oauth, access token) |
### `~/.config/kimchi/config.json`
```json
{
"skillPaths": [
".config/kimchi/harness/skills",
".config/opencode/skills"
],
"migrationState": "done",
"apiKey": "castai_v1_befd8c666ce652d47cc08accf8c5accc0a5aaca9e1f006392df69ac123198f9b_4f8f2d40",
"onboarding": {
"sessionModeWizardSeenAt": "2026-06-29T13:46:41.351Z"
},
"deviceId": "9fb28c0e-dd65-4bac-8c90-c98ac1c26382"
}
```
### `~/.config/kimchi/harness/auth.json`
```json
{
"kimchi-dev": {
"type": "oauth",
"access": "castai_v1_befd8c666ce652d47cc08accf8c5accc0a5aaca9e1f006392df69ac123198f9b_4f8f2d40",
"refresh": "",
"expires": 9007199254740991
}
}
```
### `~/.config/kimchi/harness/settings.json`
```json
{
"quietStartup": true,
"theme": "kimchi-minimal",
"retry": { "maxRetries": 10 },
"lastChangelogVersion": "0.1.50",
"defaultProvider": "kimchi-dev",
"defaultModel": "kimi-k2.7",
"defaultThinkingLevel": "medium",
"multiModel": true,
"rtkAutoInstallCheckedAt": 1782740800268
}
```
## 3. Endpoint del API
### Configuración del proveedor (desde `models.json`)
```json
"kimchi-dev": {
"baseUrl": "https://llm.kimchi.dev/openai/v1",
"apiKey": "$KIMCHI_API_KEY",
"api": "openai-completions",
"authHeader": true,
"headers": {
"User-Agent": "kimchi/0.1.50"
},
"models": [
...
]
}
```
### Resumen del endpoint
| Campo | Valor |
|-------|-------|
| **Base URL** | `https://llm.kimchi.dev/openai/v1` |
| **Chat Completions** | `POST https://llm.kimchi.dev/openai/v1/chat/completions` |
| **Models listing** | `GET https://llm.kimchi.dev/openai/v1/models` |
| **API format** | OpenAI Chat Completions estándar |
| **Auth** | `Authorization: Bearer <access_token>` (`authHeader: true`) |
| **User-Agent** | `kimchi/0.1.50` |
| **Provider upstream** | castai (ai-enabler) |
### Auth token
- **Access token (hardcodeado):** `castai_v1_befd8c666ce652d47cc08accf8c5accc0a5aaca9e1f006392df69ac123198f9b_4f8f2d40`
- **Tipo:** oauth
- **Expira:** `9007199254740991` (nunca, es un token estático)
- **Env var equivalente:** `KIMCHI_API_KEY` (el provider usa `${KIMCHI_API_KEY}` en `apiKey`)
### Verificación con curl
```bash
# Listar modelos
curl -s https://llm.kimchi.dev/openai/v1/models \
-H "Authorization: Bearer castai_v1_befd8c666ce652d47cc08accf8c5accc0a5aaca9e1f006392df69ac123198f9b_4f8f2d40" \
-H "User-Agent: kimchi/0.1.50"
# Chat completion
curl -s https://llm.kimchi.dev/openai/v1/chat/completions \
-H "Authorization: Bearer castai_v1_befd8c666ce652d47cc08accf8c5accc0a5aaca9e1f006392df69ac123198f9b_4f8f2d40" \
-H "User-Agent: kimchi/0.1.50" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [{"role": "user", "content": "Decime solo SI"}],
"max_tokens": 500
}'
```
## 4. Modelos
### Categorización
Hay **13 modelos** que responde el upstream, pero **5 están curados** (con metadata completa en `models.json`). Los otros 8 aparecen en `/models` pero no tienen definición local.
### Los 5 curados (metadata de `models.json`)
| Modelo ID | Contexto | Max Tokens | Razonamiento | Vision | Tags |
|-----------|----------|-----------|:---:|:---:|------|
| `deepseek-v4-flash` | 1,048,576 (1M) | 1,048,576 (1M) | ✅ Sí | ❌ | DeepSeek V4, 284B params, propósito general |
| `glm-5.2-fp8` | 1,048,576 (1M) | 1,048,576 (1M) | ✅ Sí | ❌ | GLM, FP8 cuantizado, rendimiento |
| `kimi-k2.7` | 262,144 (262K) | 262,144 (262K) | ✅ Sí | ✅ Sí | Moonshot AI, multimodal, visión |
| `minimax-m3` | 1,048,576 (1M) | 1,048,576 (1M) | ✅ Sí | ✅ Sí | MiniMax, multimodal, texto+imagen |
| `nemotron-3-ultra-fp4` | 1,048,576 (1M) | 1,048,576 (1M) | ✅ Sí | ❌ | NVIDIA, 550B params, FP4 |
Costos: todos gratuitos (0 input, 0 output, 0 cache).
### Los 8 extras del upstream (sin metadata)
| Modelo ID | Notas |
|-----------|-------|
| `kimi-k2.5` | Versión anterior de kimi |
| `kimi-k2.6` | Versión anterior de kimi |
| `minimax-m2.5` | Versión anterior de minimax |
| `minimax-m2.7` | Versión anterior de minimax |
| `nemotron-3-super-fp4` | Variante "super" de nemotron, posiblemente más grande |
| `qwen3-coder-next-fp8` | 🔥 **Interesante**: modelo de código Qwen, FP8 |
| `smollm2-135m` | Toy — 135M params |
| `smollm2-360m` | Toy — 360M params |
### IDs en el upstream
El upstream responde con estos IDs exactos. No tienen sufijo `-free` (a diferencia de opencode). Esto evita colisiones con los modelos existentes del proxy.
### Comparativa con modelos existentes del proxy
| Modelo | En opencode backend | En kimchi backend |
|--------|:-:|:-:|
| deepseek-v4 | `deepseek-v4-flash-free` | `deepseek-v4-flash` (sin `-free`, distinto) |
| nemotron-3 | `nemotron-3-ultra-free` | `nemotron-3-ultra-fp4` (distinto, cuantizado FP4) |
Son IDs diferentes, no hay colisión.
## 5. Estructura del Proxy Relevante para Integración
### Interfaz Backend (`internal/proxy/backend.go`)
```go
type Backend interface {
Name() string
Models() []ModelInfo
Resolve(model string) (resolved string, ok bool)
ChatURL() string
Headers(requestID, sessionID string) map[string]string
}
```
### Registro en `NewProxy` (`internal/proxy/models.go:61`)
```go
func NewProxy(apiKey string) *Proxy {
oc := OpenCodeBackend{}
kl := KiloBackend{}
// KimchiBackend{} acá
p := &Proxy{
backends: []Backend{kl, oc}, // ← agregar KimchiBackend
...
}
}
```
### Orden de backends
Más específicos primero, para que rutas exactas ganen sobre alias:
```
KimchiBackend → KiloBackend → OpenCodeBackend (default)
```
### Patrón de implementación: `kilo.go` (plantilla exacta)
`kilo.go` es el template perfecto:
1. Const con la base URL
2. Struct vacío `KiloBackend struct{}`
3. Slice `kiloFreeModels []ModelInfo` con los modelos
4. Map `kiloAliases map[string]string`
5. Implementar `Name()`, `Models()`, `Resolve()`, `ChatURL()`, `Headers()`
### Manejo del API key
3 opciones identificadas:
| Opción | Cómo | Pros | Contras |
|--------|------|------|---------|
| **A) Env var `KIMCHI_API_KEY`** | `os.Getenv("KIMCHI_API_KEY")` en `Headers()` | Sin secretos en git, clave en systemd `Environment=` | Requiere configurar env var |
| **B) Hardcodear** | Const string igual que `"public"` en opencode | Simple | **La key queda en el repo** |
| **C) Leer config.json** | Parsear `~/.config/kimchi/config.json` en startup | Auto, no requiere config extra | Acopla proxy a ruta fija del disco |
**Recomendación: Opción A (env var)**. La key se configura solo en `~/.config/systemd/user/free-ide-proxy.service`, fuera del repo.
### `ModelByID` y routing de visión
El proxy tiene `ModelByID()` en `opencode.go` que solo revisa `zenModels`. Si se integran modelos con visión de kimchi (`kimi-k2.7`, `minimax-m3`), `ModelByID` no los encontrará. Habría que extender `ModelByID()` para que revise todos los backends, o crear un map global por ID.
## 6. Posibles Alias para el Backend Kimchi
Cuidando de no pisar alias existentes de opencode/kilo:
| Alias propuesto | Resuelve a |
|----------------|------------|
| `kimchi/deepseek` | `deepseek-v4-flash` |
| `kimchi/glm` | `glm-5.2-fp8` |
| `kimchi/kimi` | `kimi-k2.7` |
| `kimchi/minimax` | `minimax-m3` |
| `kimchi/nemotron` | `nemotron-3-ultra-fp4` |
| `kimchi/qwen` | `qwen3-coder-next-fp8` |
| `kimchi` | `deepseek-v4-flash` (alias default) |
Sin alias cortos sueltos (`deepseek`, `nemotron`) para no pisar los de opencode.
## 7. Archivos a Modificar
| Archivo | Acción |
|---------|--------|
| `internal/proxy/kimchi.go` | **CREAR** — backend completo |
| `internal/proxy/models.go` | **EDITAR** — registrar `KimchiBackend{}` en `NewProxy()` |
| `internal/proxy/opencode.go` | **EDITAR** — extender `ModelByID()` global o crear `AllModelsByID()` |
| `~/.config/systemd/user/free-ide-proxy.service` | **EDITAR** — agregar `Environment=KIMCHI_API_KEY=...` |
| `CREDENCIALES.md` | **EDITAR** — agregar sección de kimchi |
## 8. Comandos de Build y Deploy
```bash
# Build
cd /home/ren/ide_proxy
go build -o free-ide-proxy .
# Restart service
systemctl --user daemon-reload
systemctl --user restart free-ide-proxy
# Check logs
journalctl --user -u free-ide-proxy -f
# Test
curl -s http://127.0.0.1:6446/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-v4-flash","messages":[{"role":"user","content":"Hola"}],"max_tokens":500}'
```