Skip to content

🧩 Custom OpenAI / Custom Anthropic

Context Code soporta dos proveedores genéricos que apuntan a endpoints OpenAI-compatible o Anthropic-compatible arbitrarios: tu propio gateway, un servidor on-premise, un proxy LLM, LiteLLM, vLLM, LM Studio, DeepInfra, Together, Fireworks, etc.

Se identifican con los IDs:

IDCliente que usaCaso típico
custom-openaiCliente HTTP responses OpenAI-compatibleLiteLLM, vLLM, LM Studio, DeepInfra, Together, Fireworks, gateways propios
custom-anthropic(Adapter Anthropic — ver "Limitaciones")Instalaciones on-premise Anthropic-compatible

A diferencia de openai, claude, openrouter, etc., estos dos no traen endpoint ni catálogo de modelos predefinido: tú los configuras durante /login y el CLI los persiste en tu perfil.


🪄 Wizard de configuración (/login)

Cuando seleccionas Custom OpenAI o Custom Anthropic en /login, se abre un asistente de 3 pasos:

text
Paso 1/3 · Endpoint
  URL del servidor API (ej: http://localhost:8001/v1)
  > _

Paso 2/3 · API key
  Ingresa tu API key.
  > ********

Paso 3/3 · Modelo
  Selecciona un modelo de la lista (el CLI hace GET {endpoint}/models).
  Si la lista no se puede cargar, podras escribirlo a mano.

Lo que persiste el wizard al terminar:

  1. API key → almacenamiento seguro del sistema (providerApiKeys[<provider>], y bajo el perfil activo si aplica).
  2. Endpoint → SQLite del provider (provider-state.sqlite3, tabla provider_base_url).
  3. Modelo elegido → como lastModel del perfil activo, vía setProviderProfileLastModel + setStoredLastModelForProvider.
  4. Lista completa de modelos descubiertos → caché en ~/.context/config.json bajo customProviderModelsCache[<provider>]. La consume /model para mostrarte tu catálogo real en vez del de OpenAI.

El fetch al endpoint /models tiene un timeout de 15 s. Si el servidor no responde, el wizard cae al modo "ingresar modelo a mano" sin colgarse.


🔌 /provider con custom

text
/provider list                                  # incluye CUSTOM OPENAI y CUSTOM ANTHROPIC
/provider current                               # muestra el activo (ej: Custom OpenAI / main)
/provider custom-openai                         # cambia el provider activo
/provider custom-openai perfil <nombre>        # cambia al perfil <nombre> dentro de custom-openai
/provider custom-openai <baseURL>               # cambia solo el endpoint del activo
/provider custom-openai clear                   # restaura el endpoint por defecto (api.openai.com)

El autocompletar (Tab tras /provider ) lista los dos custom junto al resto.

Estado mostrado en /provider list:

  • ● Conectado → hay API key guardada para ese perfil.
  • ○ Desconectado → falta API key (corre /login).
  • ACTUAL → es el perfil activo.
  • La línea +- → <url> muestra el endpoint configurado.

🤖 /model con custom

Cuando el provider activo es custom-openai (o cualquier OpenAI-compatible: openrouter, ollama, gemini-api, zai, nvidia, deepseek), al abrir /model el CLI hace fetch dinámico en background a <baseUrl>/models con tu API key y mergea los resultados con el catálogo base.

Cómo se construye la lista

  1. Default del usuario (modelo guardado como activo del perfil).
  2. Catálogo offline (lo que cacheó el wizard de /login paso 3, si lo corriste).
  3. Fetch dinámico del endpoint en background al abrir /model. Esos modelos se cachean en memoria durante la sesión.

Los tres se mergean sin duplicados. Cada vez que abres /model se vuelve a disparar el fetch para mantener la lista al día, con dedupe automático.

Si el endpoint no responde

/model no se bloquea. Muestra inmediatamente el catálogo offline (paso 2) y, si el fetch eventualmente termina, agrega los modelos nuevos. Si el fetch falla, te quedas con lo offline.

TIP

Si tu endpoint NO devuelve la ruta /models (algunos gateways minimalistas no la implementan), /model solo mostrará el catálogo offline. Si tampoco corriste el wizard de /login, verás solo el default. En cualquier caso puedes escribir el nombre del modelo directamente: /model <nombre>.

custom-anthropic no hace fetch

Anthropic-compatible no expone /models estándar; custom-anthropic solo muestra el catálogo offline del último /login.


📂 Perfiles para múltiples custom

El sistema de perfiles está habilitado para custom-openai y custom-anthropic, igual que para openai o claude. La intención es que cada perfil represente un endpoint distinto:

custom-openai / main         → http://localhost:8001/v1            (vLLM local)
custom-openai / deepinfra    → https://api.deepinfra.com/v1        (DeepInfra)
custom-openai / together     → https://api.together.xyz/v1         (Together)

Comandos para gestionarlos:

text
/login --profile deepinfra                     # wizard crea/activa el perfil 'deepinfra' y guarda todo ahi
/perfil create custom-openai together          # alternativa: crear primero
/perfil use custom-openai together             # activar
/login                                         # wizard cae en el perfil activo
/provider custom-openai perfil main           # alternar entre perfiles

Qué hace /login --profile <nombre> para custom-*:

  1. Antes de saveProviderApiKey y setProviderBaseUrl, el wizard llama ensureProviderProfile(provider, <nombre>) y setActiveProviderProfile(profile.id). Si el perfil no existe se crea; si existe se reutiliza.
  2. La API key, el endpoint, el modelo elegido y la lista de modelos descubiertos se persisten bajo ese perfil.
  3. Al terminar, el perfil queda activo.

Caché de modelos por perfil: customProviderModelsCache se indexa por profileId. Cada perfil tiene su propio catálogo, así /model muestra siempre la lista del perfil activo, no la del último /login. Si por alguna razón no hay caché para el perfil activo (perfil legacy creado antes de este cambio), cae al cache "por-provider" como fallback.


🧠 ¿Cómo se enruta una request?

Cuando el provider activo es custom-openai:

  1. getAPIProvider() retorna 'custom-openai'.
  2. isOpenAICompatibleProvider('custom-openai')true.
  3. getOpenAIBaseUrl('custom-openai') lee getConfiguredProviderBaseUrl('custom-openai') (tu endpoint del wizard), no cae al default api.openai.com.
  4. getOpenAICompatibleAccessToken('custom-openai') lee la API key vía getStoredProviderApiKey('custom-openai'), no OPENAI_API_KEY.
  5. La request va a <tu-endpoint>/responses (o /chat/completions según el modo) con tu Bearer token.

Esto significa que tu endpoint debe implementar al menos las rutas OpenAI-compatible que el CLI invoca (/responses o equivalente, /models para el wizard).


⚠️ Limitaciones honestas

  • custom-anthropic no tiene adapter completo todavía. Está registrado como provider de primera clase (aparece en /provider list, /login, /model, etc.) y su perfil persiste igual que cualquier otro. Pero el adapter Anthropic (services/api/anthropic.ts y similares) no enruta custom-anthropic a tu endpoint custom: las requests reales seguirán yendo al endpoint Anthropic configurado globalmente. Para producción úsalo solo si tu setup ya redirige api.anthropic.com a tu host (proxy reverso, DNS override, ANTHROPIC_BASE_URL env, etc.).

  • Sin auto-refresh de modelos. La lista solo se actualiza al re-correr /login con el mismo perfil. Si tu endpoint añade modelos nuevos, hasta el siguiente login /model seguirá mostrando la lista anterior. (Una mejora futura: /provider custom-openai refresh-models que haga refetch sin re-loguear).

  • No persistimos el "label" del endpoint. En /provider list siempre verás CUSTOM OPENAI; no hay un nombre amigable como "DeepInfra" o "vLLM local" para diferenciar perfiles. El nombre del perfil (main, deepinfra, etc.) cumple esa función.


🧪 Receta rápida — un único endpoint local

bash
context                                         # abre la sesión interactiva
/login                                          # selecciona "Custom OpenAI"
# Paso 1: http://localhost:8001/v1
# Paso 2: tu API key (o cualquier string si el server no la valida)
# Paso 3: elige el modelo de la lista que descubre el wizard
/provider list                                  # confirma "Custom OpenAI / main · Conectado · ACTUAL"
/model                                          # cambia al modelo que quieras del catálogo

🧪 Receta rápida — varios endpoints

bash
# Primero: el local (default, queda en perfil 'main')
context
/login                                          # "Custom OpenAI", endpoint local, key, modelo

# Segundo: DeepInfra (perfil 'deepinfra')
/login --profile deepinfra                      # mismo wizard, endpoint DeepInfra, key, modelo
                                                # el wizard crea el perfil 'deepinfra' y lo activa

# Tercero: Together (perfil 'together')
/login --profile together                       # idem

# Alternar (cada uno con su key, endpoint, modelo activo y catalogo)
/provider custom-openai perfil main
/provider custom-openai perfil deepinfra
/provider custom-openai perfil together

/model mostrará en cada caso el catálogo del endpoint correspondiente al perfil activo, gracias a que la caché se indexa por profileId.

Desarrollado con pasión e Inteligencia Artificial.