@bivelio/savings-layer 0.5.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,20 +9,21 @@ terminal). Cada afirmación va marcada **[V]** (verificada en fuente) o **[I]**
9
9
 
10
10
  `bvsala gateway` es un proxy local medidor: escucha en `127.0.0.1`, reenvía
11
11
  cada petición al proveedor (`https://api.anthropic.com` por defecto) —**byte a
12
- byte**, salvo las palancas que se explican abajo (con licencia PRO, la de tarifa
13
- va encendida por defecto)— y, una vez servida la respuesta, lee el `usage` del
12
+ byte**, salvo las palancas que se explican abajo (la de tarifa va armada por
13
+ defecto)— y, una vez servida la respuesta, lee el `usage` del
14
14
  stream y lo convierte en coste. Ni tus prompts, ni las respuestas, ni la clave de
15
15
  tu proveedor salen de tu máquina hacia BiVelio: solo viaja el uso de cada
16
16
  petición —cuentas de tokens, coste, el id del modelo, un id de petición y los ids
17
17
  opacos de asiento y de sesión—, y la lista exacta de campos está en la
18
- LICENSE §5. Es fail-closed como el SDK: arranca solo con tu clave de servicio
19
- (`BIVELIO_SERVICE_KEY`) y una licencia BiVelio activa, que recoge con esa clave y
20
- cuya firma verifica en tu máquina. Una vez arrancado, jamás corta una petición en
21
- curso: si la licencia caduca o se revoca, solo las peticiones NUEVAS reciben un
22
- HTTP 402 hasta renovarla. La medición es best-effort: con la ingesta caída,
18
+ LICENSE-CLOUD.md §5. **Open core**: arranca sin ninguna clave, en modo Community —todas
19
+ las palancas locales armadas, cero telemetría, y el metering se queda en las
20
+ rutas locales `/_bvsala`—. `BIVELIO_SERVICE_KEY` (opcional) añade el panel, los
21
+ entitlements de la org y la recogida de licencia; una licencia PRESENTE pero
22
+ caducada o revocada solo corta las peticiones NUEVAS con un HTTP 402 hasta
23
+ renovarla, jamás una en curso. La medición es best-effort: con la ingesta caída,
23
24
  reenvía y avisa.
24
25
 
25
- Mide cada petición. Con licencia PRO aplica por defecto **una sola palanca**:
26
+ Mide cada petición con contador de proveedor. La **palanca por defecto**:
26
27
  rebaja el TTL de escritura de caché mientras la sesión sigue caliente — cambia la
27
28
  tarifa, nunca el contenido que lee el modelo. Las demás (modelo hermano, esfuerzo
28
29
  por turno) van apagadas hasta que las enciendes. Y mide **todo el tráfico de inferencia**
@@ -31,8 +32,7 @@ lo que su terminal manda por fuera.
31
32
 
32
33
  En suscripción (login de claude.ai en Claude Code, cuenta ChatGPT en Codex) no
33
34
  hay factura por tokens: ese tráfico se mide a precio de lista equivalente y
34
- nunca se le acredita ahorro ni comisión; la licencia por asiento hace falta
35
- igual.
35
+ nunca se le acredita ahorro ni comisión.
36
36
 
37
37
  ## Índice
38
38
 
@@ -51,8 +51,10 @@ igual.
51
51
  | [Crush](crush.md) | `http://127.0.0.1:8402/v1` | **con**, sin barra final | `~/.config/crush/crushrc` | — (config de usuario) | [V] |
52
52
  | [Droid](droid.md) | `http://127.0.0.1:8402` | sin **[I]** | `~/.factory/settings.json` | — (config de usuario) | validar en mano |
53
53
  | [Cline](cline.md) | `http://127.0.0.1:8402/v1` | **con** | UI | — | [V] |
54
- | [Gemini CLI](no-soportados.md#gemini-cli--no-se-mide-todavía) | — | — | env `GOOGLE_GEMINI_BASE_URL` | — | **no se mide**: el gateway no lee el dialecto de Gemini |
55
- | [Cursor](no-soportados.md#cursor--no-se-puede) | — | — | sus servidores, no tu máquina | — | **no se puede**: Cursor no alcanza `127.0.0.1` |
54
+ | [Gemini CLI](gemini.md) | `http://127.0.0.1:8402` | n/a (protocolo Gemini) | env `GOOGLE_GEMINI_BASE_URL` | `bvsala gemini` ✅ | [V] en test (upstream falso): `:generateContent` y `:streamGenerateContent` |
55
+ | [Cursor](cursor.md) (BYOK) | `http://127.0.0.1:8402/v1` | **con** | UI → Settings → Models → OpenAI API Base URL | — (config de la UI) | [I]: solo el tráfico con TU clave pasa por el gateway |
56
+ | [Claude Code con DeepSeek](deepseek.md) | `http://127.0.0.1:8402` | **sin** | env `ANTHROPIC_BASE_URL` | `bvsala gateway --upstream deepseek` | [V] en test: `/v1/messages` → `/anthropic` |
57
+ | [Ollama / vLLM / LM Studio](ollama.md) (locales) | `http://127.0.0.1:8402/v1` | **con** | `base_url` del SDK | `bvsala gateway --upstream ollama|vllm|lmstudio` | [V] en test; sin precio de lista → reenviado, no metido en dólares |
56
58
  | [Python y cualquier SDK](../../README.md#python-and-any-other-language-the-local-gateway) (OpenAI · Anthropic) | OpenAI: `http://127.0.0.1:8403/v1` · Anthropic: `http://127.0.0.1:8402` | OpenAI **con**, Anthropic **sin** | `base_url` del SDK | `bvsala gateway --upstream openai` | [V] en test (upstream falso) |
57
59
 
58
60
  Reglas de la columna «Base URL»: **nunca barra final**, **nunca redirecciones**
@@ -60,9 +62,9 @@ Reglas de la columna «Base URL»: **nunca barra final**, **nunca redirecciones*
60
62
  en vez de seguirlo). Y nunca copies el URL de un terminal a otro: cada SDK añade
61
63
  su propio tramo de ruta y el error es silencioso (§ «Comprobar que mide»).
62
64
 
63
- Claude Code, Codex, Goose, Qwen Code, opencode, Kilo, Copilot CLI (BYOK) y Aider
64
- tienen **envoltorio propio** (`bvsala
65
- claude|codex|goose|qwen|opencode|kilo|copilot|aider`): arrancan un gateway en
65
+ Claude Code, Codex, Goose, Qwen Code, opencode, Kilo, Copilot CLI (BYOK), Aider
66
+ y Gemini CLI tienen **envoltorio propio** (`bvsala
67
+ claude|codex|goose|qwen|opencode|kilo|copilot|aider|gemini`): arrancan un gateway en
66
68
  puerto efímero, lanzan el terminal apuntándole y lo apagan al salir. Cero
67
69
  configuración persistente: opencode y Kilo reciben la suya por variable
68
70
  (`OPENCODE_CONFIG_CONTENT`, `KILO_CONFIG_CONTENT`), fusionada con la tuya. La
@@ -88,24 +90,26 @@ tráfico degradado: no viaja a BiVelio.
88
90
 
89
91
  ```bash
90
92
  npm i -g @bivelio/savings-layer # trae el binario `bvsala`
91
- export BIVELIO_SERVICE_KEY=bvk_… # clave de servicio, desde tu panel. Obligatoria: sin ella el gateway no arranca
92
- bvsala gateway # escucha en http://127.0.0.1:8402
93
+ bvsala gateway # escucha en http://127.0.0.1:8402 — sin claves: modo Community
93
94
  bvsala gateway --port 8500 # otro puerto si el 8402 está ocupado
95
+ bvsala gateway --upstream deepseek # Claude Code con DeepSeek; qwen|glm|moonshot|minimax|gemini|ollama|vllm|lmstudio también
96
+ export BIVELIO_SERVICE_KEY=bvk_… # OPCIONAL: panel + entitlements de org (sin ella: modo Community)
94
97
  ```
95
98
 
96
99
  Al arrancar imprime, entre otras, estas líneas:
97
100
 
98
101
  ```
99
- [bvsala gateway] v0.4.x listening on http://127.0.0.1:8402 → https://api.anthropic.com
100
- [bvsala gateway] license: PRO, active until 2026-10-24 (+14 days grace), collected with your service key and verified on this machine
101
- [bvsala gateway] metering: ON (service key present)
102
+ [bvsala gateway] v0.6.x listening on http://127.0.0.1:8402 → https://api.anthropic.com
103
+ [bvsala gateway] COMMUNITY MODE (open core): every local saving lever on, zero telemetry - no BiVelio keys set
104
+ [bvsala gateway] metering: OFF (community mode - no BiVelio service key; local reports stay available with x-bvsala-report)
102
105
  ```
103
106
 
104
- Si no arranca (sale con código 1), el mensaje dice exactamente qué falta:
107
+ Con `BIVELIO_SERVICE_KEY` la licencia se recoge sola (línea `license: PRO, active
108
+ until …`) y el metering queda ON. Si algo no arranca (sale con código 1), el
109
+ mensaje dice exactamente qué falta:
105
110
 
106
111
  | Mensaje | Qué pasa | Arreglo |
107
112
  |---|---|---|
108
- | `BIVELIO_SERVICE_KEY is not set` | falta la clave de servicio | créala en el panel (Instalar, paso 2), expórtala y relanza |
109
113
  | `BIVELIO_SERVICE_KEY is not recognised` | clave borrada, rotada o copiada a medias | crea otra |
110
114
  | `your organization has no active BiVelio license` | no hay suscripción | suscríbete en Cuenta y relanza |
111
115
  | `your BiVelio license expired on …` | licencia caducada y sin gracia | renueva en Cuenta |
@@ -151,22 +155,24 @@ como salen hoy:
151
155
 
152
156
  | `· not metered: …` | Qué pasa | Arreglo |
153
157
  |---|---|---|
154
- | `no BIVELIO_SERVICE_KEY` | un gateway arrancado desde código sin clave de servicio: reenvía, no mide (el CLI `bvsala` ni arranca sin ella) | exporta `BIVELIO_SERVICE_KEY` |
158
+ | `no BIVELIO_SERVICE_KEY` | modo Community: sin clave no hay ingesta a la que medir — el tráfico se reenvía y los informes locales (`/_bvsala`) siguen funcionando | exporta `BIVELIO_SERVICE_KEY` si quieres el panel |
155
159
  | `model "…" has no list price in the catalog` | modelo fuera del catálogo de precios, a propósito: un precio presente y equivocado es peor que ninguno (la consola lo avisa una vez por modelo) | nada; se reenvía sin medir |
156
160
  | `could not read the model from the request body (content-encoding: …)` | el cuerpo no se pudo leer: JSON ilegible o una compresión que este Node no abre (zstd, el de Codex, necesita Node ≥ 22.15) | actualiza Node |
157
161
  | `the request did not ask for usage (stream_options.include_usage)` | Chat Completions en stream sin `include_usage`: el proveedor no manda contador | añade `stream_options={"include_usage": True}` a la llamada, o arranca con `BVSALA_GATEWAY_USAGE_INJECT=1` |
158
162
  | `…; usage injection skips compressed request bodies` | la inyección está puesta, pero solo añade la opción a cuerpos sin comprimir | pídelo en la llamada |
159
163
  | `…, and the upstream rejects that option` | el upstream rechazó `stream_options` y la inyección quedó apagada para el resto del proceso | en stream no hay arreglo desde el gateway; con `stream: false` sí se mide |
160
- | `the stream ended without the provider's final usage event` | el stream se cortó antes de su evento final (`message_delta`, `response.completed`/`incomplete`/`failed`, el chunk de uso o `[DONE]`): sin él no hay contador | nada |
164
+ | `the stream ended without the provider's final usage event` | el stream se cortó antes de completarse (`message_delta` y `message_stop` en Anthropic, `response.completed`/`incomplete`/`failed`, el chunk de uso o `[DONE]`): sin contador y cierre terminal no hay medida | nada |
161
165
  | `the response ended as response.failed without usage` | la Responses API cerró con `response.failed` sin `usage`. Si lo trae, sí se mide | nada |
162
166
  | `the response ended as response.incomplete without usage` | la Responses API cerró con `response.incomplete` sin `usage`. Si lo trae, sí se mide: un `response.incomplete` por `max_output_tokens` o por el filtro de contenido lo factura el proveedor | nada |
163
167
  | `the response carried no usage` | respuesta JSON (`stream: false`) sin `usage` | nada |
164
168
  | `the response was too large to read its usage` | respuesta JSON de más de 5 MB: el gateway no la guarda entera para leerla | nada |
165
169
  | `the response is neither JSON nor an event stream (content-type: …)` | el upstream contestó con otro tipo de contenido en una ruta que sí sabe medir | revisa el upstream |
166
- | `no usage dialect for this route` | ruta sin contador que el gateway sepa leer (embeddings, imágenes, audio…): solo mide `/v1/messages`, `…/chat/completions` y `…/responses` | nada |
170
+ | `no usage dialect for this route` | ruta sin contador que el gateway sepa leer (embeddings, imágenes, audio…): solo mide `/v1/messages`, `…/chat/completions`, `…/responses` y el protocolo Gemini (`:generateContent` / `:streamGenerateContent`) | nada |
167
171
 
168
- Con `BVSALA_GATEWAY_COALESCE=1` (apagada por defecto), una petición idéntica a
169
- otra que sigue en vuelo no viaja: recibe la réplica y su línea lleva
172
+ Con `BVSALA_GATEWAY_COALESCE=1` (apagada por defecto), una petición idéntica de
173
+ inferencia de lectura (`messages`, `chat/completions`, `responses` o `embeddings`)
174
+ a otra que sigue en vuelo no viaja: recibe la réplica. Batches, administración y
175
+ rutas desconocidas siempre se ejecutan por separado. La línea lleva
170
176
  `· COALESCED (call avoided)`. Detrás va `· by reference: floor $… (cache read
171
177
  price, …)` cuando se valora con el contador de la petición que sí viajó —a
172
178
  precio de lectura de caché, sin primas y con la salida solo si el cuerpo trae
@@ -180,7 +186,7 @@ razonamiento que declara el proveedor y la regla `reference-v2` los exige.
180
186
  |---|---|
181
187
  | `no-primary-record` | la petición que viajó no dejó su contador final (ni evento final del stream ni `usage` en el JSON) |
182
188
  | `subscription` | tráfico de suscripción (Claude o ChatGPT): no hay factura por token |
183
- | `unofficial-upstream` | el gateway no habla con `api.anthropic.com` ni `api.openai.com` (un mock, un proxy, Azure, un revendedor): el precio de lista no está en ninguna factura |
189
+ | `unofficial-upstream` | el gateway no habla con el origen oficial de un proveedor (un mock, un proxy, Azure, un revendedor — Ollama/vLLM/LM Studio y OpenRouter incluidos): el precio de lista no está en ninguna factura |
184
190
  | `layer-changed-request` | una palanca cambió lo que viajó (modelo, cuerpo, cabeceras; también la rebaja de TTL de la caché): ya no es la petición del cliente byte a byte |
185
191
  | `primary-failed` | la petición que viajó cerró con `response.failed` |
186
192
  | `client-disconnected` | el cliente de esta petición se fue antes de recibir la réplica entera |
@@ -202,7 +208,7 @@ sistemas. Lo que cambia es cómo se fija la clave en la sesión — el `export`
202
208
  estas guías es POSIX; en PowerShell:
203
209
 
204
210
  ```powershell
205
- $env:BIVELIO_SERVICE_KEY = "bvk_…"
211
+ $env:BIVELIO_SERVICE_KEY = "bvk_…" # OPCIONAL: panel + entitlements de org (sin ella: modo Community)
206
212
  bvsala claude
207
213
  ```
208
214
 
@@ -283,8 +289,8 @@ license state. These routes are answered by the gateway and never forwarded;
283
289
  the gateway listens on 127.0.0.1 only, they send no CORS headers, they answer
284
290
  403 to a `Host` other than 127.0.0.1 or localhost (so a web page cannot reach
285
291
  them by rebinding its own name to 127.0.0.1), no route lists reports (you need
286
- the id), and like every other route they answer 402 when the license does not
287
- serve. The gateway
292
+ the id), and like every other route they answer 402 when a live license does not
293
+ serve (in COMMUNITY mode there is no license: they answer as usual). The gateway
288
294
  keeps the last 1,000 reports for one hour at most, in memory; nothing is
289
295
  written to disk and nothing more is sent to BiVelio.
290
296
 
@@ -301,7 +307,7 @@ would fail it.
301
307
 
302
308
  | Lever | Applies to | What changes | What does not |
303
309
  |---|---|---|---|
304
- | Cache TTL (`cache_ttl_tuning`, on by default with PRO) | `/v1/messages` requests where a large part of the prompt is new (session start, compaction); a chained turn travels untouched | every `cache_control` with `ttl: "1h"` becomes `"5m"`, the top-level one included (a 1-hour top-level marker behind 5-minute block markers would be a 400) | a key named `cache_control` inside a tool call's `input` or a tool's `input_schema` is content and stays as it is; so does the advisor's `caching`; headers are untouched |
310
+ | Cache TTL (`cache_ttl_tuning`, armed by default in community and PRO) | `/v1/messages` requests where a large part of the prompt is new (session start, compaction); a chained turn travels untouched | every `cache_control` with `ttl: "1h"` becomes `"5m"`, the top-level one included (a 1-hour top-level marker behind 5-minute block markers would be a 400) | a key named `cache_control` inside a tool call's `input` or a tool's `input_schema` is content and stays as it is; so does the advisor's `caching`; headers are untouched |
305
311
  | Per-turn effort (`BVSALA_GATEWAY_EFFORT=low` or `medium`) | `/v1/messages` for `claude-fable-5-1`, `claude-mythos-5-1`, `claude-opus-5-5` and `claude-opus-5`, when the level is below the model's default effort (`high`; `medium` on `claude-opus-5-5`) and the request carries no `output_config` of its own (top level or in a message); a level at or above the default leaves the request untouched | one message appended at the end of `messages`, `{"role":"system","content":[],"output_config":{"effort":…}}`, and `mid-conversation-output-config-2026-07-01` appended after your `anthropic-beta` value | your `anthropic-beta` value is kept verbatim in front; nothing earlier in `messages` moves |
306
312
  | Sibling model (`BVSALA_GATEWAY_SIBLING_MODEL=1`) | `/v1/messages` and `/v1/messages/count_tokens` for `claude-fable-5`, except with a forced `tool_choice` or the 1M-context beta | `model` becomes `claude-fable-5-1` | headers are untouched |
307
313
  | Context-editing dials (`BVSALA_GATEWAY_DIALES_ELISION=1`; measured as a net loss, off) | `/v1/messages` | your `clear_tool_uses_20250919` edit in `context_management` is replaced by ours | your other edits are kept, `clear_thinking_20251015` first; your `anthropic-beta` value is kept verbatim, with `context-management-2025-06-27` appended if it was not there |
@@ -330,7 +336,7 @@ Each kind is logged once per session (Claude Code's session id; once per gateway
330
336
  process for clients that send none) and every case is counted. `bvsala` prints
331
337
  the totals when it exits, because the per-request log is silent inside `bvsala
332
338
  claude|codex|goose|qwen` (unless `BVSALA_GATEWAY_LOG=1`). None of this is sent to BiVelio: the usage record has
333
- no field for it (LICENSE §5), so it stays on your machine.
339
+ no field for it (LICENSE-CLOUD.md §5), so it stays on your machine.
334
340
 
335
341
  **Limits.**
336
342
 
@@ -9,7 +9,7 @@ variables que mandan son las de litellm [V].
9
9
  ## Qué necesitas
10
10
 
11
11
  - `aider` en el PATH y tu **API key** (`ANTHROPIC_API_KEY` o `OPENAI_API_KEY`).
12
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (ver [README](README.md)).
12
+ - `bvsala` instalado. Open core: sin claves arranca en modo Community; `BIVELIO_SERVICE_KEY` (opcional) añade el panel y los entitlements (ver [README](README.md)).
13
13
 
14
14
  ## Envoltorio: `bvsala aider [args…]`
15
15
 
@@ -15,12 +15,12 @@ construcción, con test.
15
15
  pero ahí no hay factura por token: el gateway lo mide a precio de lista
16
16
  equivalente y nunca le acredita ahorro ni comisión (la licencia por asiento
17
17
  hace falta igual).
18
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
18
+ - `bvsala` instalado. Open core: sin claves el gateway arranca en modo Community (todo el ahorro local, cero telemetría); `BIVELIO_SERVICE_KEY` añade el panel y los entitlements de la org (ver [README](README.md)).
19
19
 
20
20
  ## Envoltorio: `bvsala claude` (recomendado)
21
21
 
22
22
  ```bash
23
- export BIVELIO_SERVICE_KEY=bvk_…
23
+ export BIVELIO_SERVICE_KEY=bvk_… # OPCIONAL: panel + entitlements de org (sin ella: modo Community)
24
24
  bvsala claude # cualquier argumento pasa tal cual: bvsala claude -p "hola"
25
25
  ```
26
26
 
@@ -14,7 +14,7 @@ que se usa.
14
14
 
15
15
  - Cline instalado en VS Code.
16
16
  - Tu **API key** de Anthropic.
17
- - `bvsala gateway` corriendo en `http://127.0.0.1:8402` (necesita `BIVELIO_SERVICE_KEY` y una licencia BiVelio activa; ver [README](README.md)).
17
+ - `bvsala gateway` corriendo en `http://127.0.0.1:8402` (sin claves: modo Community; `BIVELIO_SERVICE_KEY` opcional; ver [README](README.md)).
18
18
 
19
19
  ## Pasos en la UI
20
20
 
@@ -14,12 +14,12 @@ cifras.
14
14
  suscripción ChatGPT (se enruta y se mide a precio de lista equivalente, **sin
15
15
  comisión**: no hay factura por tokens; la licencia por asiento hace falta
16
16
  igual; ver más abajo).
17
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
17
+ - `bvsala` instalado. Open core: sin claves el gateway arranca en modo Community (todo el ahorro local, cero telemetría); `BIVELIO_SERVICE_KEY` añade el panel y los entitlements de la org (ver [README](README.md)).
18
18
 
19
19
  ## Envoltorio: `bvsala codex [args…]`
20
20
 
21
21
  ```bash
22
- export BIVELIO_SERVICE_KEY=bvk_…
22
+ export BIVELIO_SERVICE_KEY=bvk_… # OPCIONAL: panel + entitlements de org (sin ella: modo Community)
23
23
  bvsala codex # cualquier argumento pasa tal cual a codex
24
24
  ```
25
25
 
@@ -107,7 +107,7 @@ del staff, a diferencia de Anthropic, que lo documenta). Postura idéntica a
107
107
  Claude Code: cero persistencia de `Authorization` / `ChatGPT-Account-ID`,
108
108
  binario sin modificar, y no se promociona como modo de ahorro.
109
109
 
110
- **Comisión 0 por diseño (desde la versión en que el gateway exige licencia):**
110
+ **Comisión 0 por diseño:**
111
111
  el gateway clasifica como suscripción el tráfico de `/backend-api/…` o con
112
112
  upstream chatgpt.com (y el de Claude Code con `anthropic-beta: oauth-*`) y no le
113
113
  acredita ahorro: `baseline == actual`. Laguna que queda: el registro no lleva
@@ -26,7 +26,7 @@ tokens por modelo). Con BYOK, la CLI funciona **sin cuenta de GitHub** [V].
26
26
  ```
27
27
 
28
28
  (Con OpenAI, el tipo por defecto, el base URL es `https://api.openai.com/v1`: ver «El tipo `openai`» abajo.)
29
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (ver [README](README.md)).
29
+ - `bvsala` instalado. Open core: sin claves arranca en modo Community; `BIVELIO_SERVICE_KEY` (opcional) añade el panel y los entitlements (ver [README](README.md)).
30
30
 
31
31
  ### Envoltorio: `bvsala copilot [args…]`
32
32
 
@@ -10,7 +10,7 @@ relativa, y eso dicta la forma del URL: **con `/v1`, sin barra final**.
10
10
  - `crush` instalado.
11
11
  - `ANTHROPIC_API_KEY` exportada (Crush retiró su OAuth de Claude en ene-2026:
12
12
  solo API key).
13
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
13
+ - `bvsala` instalado. Open core: sin claves el gateway arranca en modo Community (todo el ahorro local, cero telemetría); `BIVELIO_SERVICE_KEY` añade el panel y los entitlements de la org (ver [README](README.md)).
14
14
 
15
15
  ## Config de usuario: `~/.config/crush/crushrc`
16
16
 
@@ -0,0 +1,32 @@
1
+ # Cursor (BYOK: tu propia clave OpenAI-compatible)
2
+
3
+ Cursor solo pasa por un gateway local cuando la petición va con **tu** clave de
4
+ proveedor: sus modelos propios viajan por los servidores de Cursor y no alcanzan
5
+ `127.0.0.1` (su panel de uso mide esos).
6
+
7
+ **Mecanismo [I]:** Cursor → Settings → Models → **OpenAI API Base URL**. Las
8
+ peticiones OpenAI-compatibles con tu clave salen hacia esa URL.
9
+
10
+ ## Receta
11
+
12
+ 1. Arranca el gateway con el upstream que quieras:
13
+
14
+ ```bash
15
+ bvsala gateway --upstream openai --port 8402 # deepseek, qwen, glm, moonshot, ollama… también
16
+ ```
17
+
18
+ 2. En Cursor: Settings → Models → **OpenAI API Base URL** =
19
+ `http://127.0.0.1:8402/v1` (**con** `/v1`).
20
+
21
+ 3. Añade un modelo OpenAI-compatible con tu API key, como harías sin el gateway.
22
+
23
+ ## Qué se mide y qué no
24
+
25
+ - Se mide: lo que Cursor manda con TU clave a esa base URL, a precio de lista
26
+ para los modelos con fila en el catálogo.
27
+ - No se mide: los modelos propios de Cursor (su dashboard de uso es el medidor
28
+ ahí) y los streams sin `stream_options.include_usage`.
29
+
30
+ ## Comprobar que mide
31
+
32
+ El log del gateway tiene que mostrar `POST /v1/chat/completions …` con `$`.
@@ -0,0 +1,28 @@
1
+ # Claude Code con DeepSeek (endpoint en formato Anthropic)
2
+
3
+ DeepSeek publica un endpoint compatible con el protocolo Anthropic
4
+ (`https://api.deepseek.com/anthropic`): el gateway reescribe `/v1/messages` hacia
5
+ `/anthropic/v1/messages` automáticamente, así que Claude Code habla con DeepSeek
6
+ sin tocar su configuración **[V] en test** (`test/gateway-gemini.test.ts`).
7
+
8
+ Por qué merece la pena: las lecturas de caché de DeepSeek cuestan $0,003/1M y la
9
+ entrada off-peak $0,15/1M — el hermano barato más agresivo para tráfico Claude.
10
+
11
+ ## Receta
12
+
13
+ ```bash
14
+ bvsala gateway --upstream deepseek --port 8402
15
+ ANTHROPIC_BASE_URL=http://127.0.0.1:8402 \
16
+ ANTHROPIC_AUTH_TOKEN=<tu API key de DeepSeek> \
17
+ ANTHROPIC_MODEL=deepseek-flash \
18
+ claude
19
+ ```
20
+
21
+ ## Notas
22
+
23
+ - Se mide a precio de lista para `deepseek-flash` y `deepseek-v4-pro` (el
24
+ catálogo los tarifa a PEAK, el lado conservador: off-peak es la mitad).
25
+ - `deepseek-chat` (el alias clásico) no tiene fila propia: se reenvía y el log
26
+ dice «not metered». Usa `deepseek-flash`.
27
+ - La calidad del modelo es asunto tuyo: el gateway no enruta por calidad, solo
28
+ mide lo que le mandas.
@@ -9,7 +9,7 @@ lo dice tal cual; no hay validación hecha.
9
9
  ## Qué necesitas
10
10
 
11
11
  - `droid` instalado, en modo BYOK con tu **API key** de Anthropic.
12
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
12
+ - `bvsala` instalado. Open core: sin claves el gateway arranca en modo Community (todo el ahorro local, cero telemetría); `BIVELIO_SERVICE_KEY` añade el panel y los entitlements de la org (ver [README](README.md)).
13
13
 
14
14
  ## Config de usuario: `~/.factory/settings.json`
15
15
 
@@ -0,0 +1,38 @@
1
+ # Gemini CLI
2
+
3
+ `bvsala gemini` lanza la CLI de Gemini a través del gateway local, sin tocar su
4
+ configuración.
5
+
6
+ **Mecanismo [V]:** la CLI de Gemini solo habla el protocolo generativelanguage;
7
+ el gateway lo entiende desde la 0.6 (`:generateContent` y
8
+ `:streamGenerateContent`, con SSE `alt=sse` o JSON por líneas) y lee el
9
+ `usageMetadata` de cada respuesta. El `GOOGLE_GEMINI_BASE_URL` de la CLI apunta
10
+ al gateway, y tu `GEMINI_API_KEY` viaja en `x-goog-api-key`, intacta.
11
+
12
+ ## Requisitos
13
+
14
+ - `bvsala` instalado (`npm i -g @bivelio/savings-layer`). Sin claves arranca en
15
+ modo Community; `BIVELIO_SERVICE_KEY` (opcional) añade el panel.
16
+ - La CLI de Gemini instalada y tu `GEMINI_API_KEY` exportada.
17
+
18
+ ## Un comando
19
+
20
+ ```bash
21
+ bvsala gemini
22
+ ```
23
+
24
+ A la salida imprime cuántas peticiones midió y cuáles reenvió sin medir, y por
25
+ qué.
26
+
27
+ ## A mano
28
+
29
+ ```bash
30
+ bvsala gateway --upstream gemini --port 8402 # el gateway con el dialecto Gemini
31
+ GOOGLE_GEMINI_BASE_URL=http://127.0.0.1:8402 gemini
32
+ ```
33
+
34
+ ## Comprobar que mide
35
+
36
+ El log del gateway tiene que mostrar `POST /v1beta/models/…:streamGenerateContent`
37
+ con `$` y los tokens. Los modelos con precio de lista en el catálogo se meten a
38
+ precio de lista; uno sin fila se reenvía y la línea lo dice.
@@ -9,12 +9,12 @@ forma del URL.
9
9
 
10
10
  - `goose` en el PATH, con el proveedor Anthropic elegido.
11
11
  - `ANTHROPIC_API_KEY` exportada (Goose es solo BYOK).
12
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
12
+ - `bvsala` instalado. Open core: sin claves el gateway arranca en modo Community (todo el ahorro local, cero telemetría); `BIVELIO_SERVICE_KEY` añade el panel y los entitlements de la org (ver [README](README.md)).
13
13
 
14
14
  ## Envoltorio: `bvsala goose`
15
15
 
16
16
  ```bash
17
- export BIVELIO_SERVICE_KEY=bvk_…
17
+ export BIVELIO_SERVICE_KEY=bvk_… # OPCIONAL: panel + entitlements de org (sin ella: modo Community)
18
18
  bvsala goose # espejo exacto de `bvsala claude`
19
19
  ```
20
20
 
@@ -11,7 +11,7 @@ Esto sustituye a la receta anterior (proveedor custom por UI, forma inferida).
11
11
  ## Qué necesitas
12
12
 
13
13
  - Kilo (CLI `kilo`, o la extensión) con el proveedor **`anthropic`** y tu **API key** de Anthropic.
14
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
14
+ - `bvsala` instalado. Open core: sin claves el gateway arranca en modo Community (todo el ahorro local, cero telemetría); `BIVELIO_SERVICE_KEY` añade el panel y los entitlements de la org (ver [README](README.md)).
15
15
 
16
16
  **Lo que no pasa por aquí:** el proveedor por defecto de Kilo es su propia
17
17
  pasarela (Kilo Gateway, modelos alojados por Kilo con su cuenta). Ese tráfico va
@@ -20,7 +20,7 @@ a Kilo, no a un base URL tuyo, y no se mide. Tampoco los demás proveedores.
20
20
  ## Envoltorio (CLI): `bvsala kilo [args…]`
21
21
 
22
22
  ```bash
23
- export BIVELIO_SERVICE_KEY=bvk_…
23
+ export BIVELIO_SERVICE_KEY=bvk_… # OPCIONAL: panel + entitlements de org (sin ella: modo Community)
24
24
  bvsala kilo
25
25
  ```
26
26
 
@@ -2,33 +2,11 @@
2
2
 
3
3
  **Fuente:** `docs/investigacion/2026-09-27/agentes-de-codigo.md`. Decir que no es
4
4
  parte de la receta: un terminal apuntado al gateway que no se puede medir sería
5
- pagar una licencia por un proxy vacío.
6
-
7
- ## Gemini CLI — no se mide todavía
8
-
9
- Gemini CLI acepta un base URL propio: `GOOGLE_GEMINI_BASE_URL` (y
10
- `GOOGLE_VERTEX_BASE_URL` con Vertex), en HTTPS salvo que apunte a `localhost` o
11
- `127.0.0.1` [V: `docs/reference/configuration.md` de `google-gemini/gemini-cli`,
12
- 2026-09-27]. El problema no es enrutarlo: es que habla la **API de Gemini**
13
- (`…/models/<modelo>:streamGenerateContent`, contador en `usageMetadata`), y el
14
- gateway solo sabe leer el contador de Anthropic Messages y de OpenAI Chat
15
- Completions y Responses. Cada petición se reenviaría con la línea
16
- `not metered: no usage dialect for this route`, sin coste.
17
-
18
- Hasta que el gateway lea ese dialecto, el contador de Gemini CLI es su propio
19
- `/stats model` (tokens por modelo y cuota) [V]. Qué haría falta para medirlo, y
20
- por qué no se ha hecho hoy (los precios de contexto largo de los modelos Pro),
21
- está en el informe.
22
-
23
- ## Cursor — no se puede
24
-
25
- Cursor manda **todas** las peticiones, también las de tu propia clave, a través
26
- de sus servidores: «all requests are routed through Cursor's servers for final
27
- prompt building» [V: cursor.com/docs/settings/api-keys, 2026-09-27]. Un gateway
28
- en `127.0.0.1` es inalcanzable desde ahí, y exponerlo a Internet no es una
29
- opción (escucha solo en loopback a propósito). Las claves propias, además, solo
30
- cubren los modelos de chat; Tab sigue con los modelos de Cursor [V]. El contador
31
- de Cursor es su panel de uso.
5
+ pagar por un proxy vacío.
6
+
7
+ > Actualización 2026-11 (open core): Gemini CLI **ya se mide**
8
+ > ([gemini.md](gemini.md)) y Cursor **ya tiene receta** para su override de base
9
+ > URL BYOK ([cursor.md](cursor.md)). Quedan aquí los casos que siguen sin medirse.
32
10
 
33
11
  ## Copilot con modelos de GitHub — no pasa por un base URL
34
12
 
@@ -39,3 +17,14 @@ GitHub y no a un base URL tuyo. Con BYOK sí se mide: ver [copilot.md](copilot.m
39
17
 
40
18
  El proveedor por defecto de Kilo son sus modelos alojados; ese tráfico va a Kilo.
41
19
  Con el proveedor `anthropic` y tu clave sí se mide: ver [kilo.md](kilo.md).
20
+
21
+ ## Cursor con sus modelos propios — no pasa por un base URL tuyo
22
+
23
+ Con modelos de Cursor (sin BYOK) las peticiones van a los servidores de Cursor y
24
+ no alcanzan un gateway en `127.0.0.1`; su panel de uso es el medidor ahí. Con tu
25
+ propia clave OpenAI-compatible sí se mide: ver [cursor.md](cursor.md).
26
+
27
+ ## Modelos locales (Ollama, vLLM, LM Studio) — sin precio de lista
28
+
29
+ Se reenvían y el log lo dice; no hay precio de lista que meter en dólares. Ver
30
+ [ollama.md](ollama.md).
@@ -0,0 +1,19 @@
1
+ # Ollama, vLLM y LM Studio (modelos locales)
2
+
3
+ El gateway también se pone delante de un servidor local OpenAI-compatible: útil
4
+ para dar a un agente un tier local gratis mientras el gateway sigue midiendo las
5
+ llamadas de pago.
6
+
7
+ ```bash
8
+ bvsala gateway --upstream ollama --port 8402 # http://localhost:11434
9
+ bvsala gateway --upstream vllm --port 8402 # http://localhost:8000
10
+ bvsala gateway --upstream lmstudio --port 8402 # http://localhost:1234
11
+ ```
12
+
13
+ Luego apunta cualquier SDK OpenAI a `http://127.0.0.1:8402/v1` (**con** `/v1`).
14
+
15
+ **Honestidad de la medición:** los modelos locales no tienen precio de lista, así
16
+ que este tráfico se reenvía y el log lo dice (`not metered: model "…" has no
17
+ list price in the catalog`). En dólares no se acredita nada; el valor es
18
+ operativo: un solo base URL para todos los modelos, con el metering de los
19
+ providers de pago funcionando al lado.
@@ -9,12 +9,12 @@ defecto: por eso aquí el URL lleva `/v1` [V].
9
9
  ## Qué necesitas
10
10
 
11
11
  - `opencode` instalado, proveedor `anthropic` con tu **API key** de Anthropic.
12
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
12
+ - `bvsala` instalado. Open core: sin claves el gateway arranca en modo Community (todo el ahorro local, cero telemetría); `BIVELIO_SERVICE_KEY` añade el panel y los entitlements de la org (ver [README](README.md)).
13
13
 
14
14
  ## Envoltorio: `bvsala opencode [args…]`
15
15
 
16
16
  ```bash
17
- export BIVELIO_SERVICE_KEY=bvk_…
17
+ export BIVELIO_SERVICE_KEY=bvk_… # OPCIONAL: panel + entitlements de org (sin ella: modo Community)
18
18
  bvsala opencode
19
19
  ```
20
20
 
@@ -10,7 +10,7 @@ catálogo a propósito (más abajo).
10
10
  - `qwen` en el PATH.
11
11
  - **Una API key de Anthropic** (`ANTHROPIC_API_KEY`), con Qwen Code configurado
12
12
  para usar el proveedor Anthropic.
13
- - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
13
+ - `bvsala` instalado. Open core: sin claves el gateway arranca en modo Community (todo el ahorro local, cero telemetría); `BIVELIO_SERVICE_KEY` añade el panel y los entitlements de la org (ver [README](README.md)).
14
14
 
15
15
  ## Config de usuario: `~/.qwen/settings.json`
16
16
 
@@ -31,7 +31,7 @@ verá nada.
31
31
  ## Envoltorio: `bvsala qwen`
32
32
 
33
33
  ```bash
34
- export BIVELIO_SERVICE_KEY=bvk_…
34
+ export BIVELIO_SERVICE_KEY=bvk_… # OPCIONAL: panel + entitlements de org (sin ella: modo Community)
35
35
  bvsala qwen
36
36
  ```
37
37