@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.
- package/CHANGELOG.md +115 -0
- package/LICENSE +183 -163
- package/LICENSE-CLOUD.md +174 -0
- package/NOTICE +11 -0
- package/README.md +223 -122
- package/dist/adapters/ai-sdk.js +78 -78
- package/dist/adapters/anthropic-sdk.js +88 -88
- package/dist/adapters/langchain.js +58 -58
- package/dist/adapters/mastra.js +70 -70
- package/dist/gateway/bin.js +1291 -1082
- package/dist/index.d.ts +364 -191
- package/dist/index.js +1717 -1642
- package/docs/terminales/README.md +39 -33
- package/docs/terminales/aider.md +1 -1
- package/docs/terminales/claude-code.md +2 -2
- package/docs/terminales/cline.md +1 -1
- package/docs/terminales/codex.md +3 -3
- package/docs/terminales/copilot.md +1 -1
- package/docs/terminales/crush.md +1 -1
- package/docs/terminales/cursor.md +32 -0
- package/docs/terminales/deepseek.md +28 -0
- package/docs/terminales/droid.md +1 -1
- package/docs/terminales/gemini.md +38 -0
- package/docs/terminales/goose.md +2 -2
- package/docs/terminales/kilo.md +2 -2
- package/docs/terminales/no-soportados.md +16 -27
- package/docs/terminales/ollama.md +19 -0
- package/docs/terminales/opencode.md +2 -2
- package/docs/terminales/qwen-code.md +2 -2
- package/package.json +48 -20
|
@@ -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 (
|
|
13
|
-
|
|
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.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
|
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
|
|
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](
|
|
55
|
-
| [Cursor](
|
|
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)
|
|
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
|
-
|
|
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.
|
|
100
|
-
[bvsala gateway]
|
|
101
|
-
[bvsala gateway] metering:
|
|
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
|
-
|
|
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` |
|
|
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
|
|
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
|
|
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
|
|
169
|
-
|
|
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
|
|
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
|
|
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`,
|
|
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
|
|
package/docs/terminales/aider.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
package/docs/terminales/cline.md
CHANGED
|
@@ -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` (
|
|
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
|
|
package/docs/terminales/codex.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
package/docs/terminales/crush.md
CHANGED
|
@@ -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
|
|
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.
|
package/docs/terminales/droid.md
CHANGED
|
@@ -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
|
|
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.
|
package/docs/terminales/goose.md
CHANGED
|
@@ -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
|
|
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
|
|
package/docs/terminales/kilo.md
CHANGED
|
@@ -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
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
|
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
|
|
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
|
|