@bivelio/savings-layer 0.4.24 → 0.4.26

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.
@@ -1,15 +1,40 @@
1
1
  # opencode a través del gateway
2
2
 
3
- **Fuente:** `docs/PASARELA-S3-TERMINALES.md` §3 [V]. opencode enruta por
4
- **archivo de configuración**, no por variable de entorno, y su capa
5
- `packages/llm` añade `/messages` al `baseURL`: por eso aquí el URL lleva `/v1`.
3
+ **Fuente:** `docs/PASARELA-S3-TERMINALES.md` §3 [V] y
4
+ `docs/investigacion/2026-09-27/agentes-de-codigo.md` (código de
5
+ `anomalyco/opencode` v1.18.32, 2026-09-27). opencode enruta por **configuración**,
6
+ y su capa de protocolo añade `/messages` a `https://api.anthropic.com/v1` por
7
+ defecto: por eso aquí el URL lleva `/v1` [V].
6
8
 
7
9
  ## Qué necesitas
8
10
 
9
11
  - `opencode` instalado, proveedor `anthropic` con tu **API key** de Anthropic.
10
12
  - `bvsala` instalado, `BIVELIO_SERVICE_KEY` exportada y una licencia BiVelio activa (la recoge el gateway con la clave; ver [README](README.md)).
11
13
 
12
- ## Config de usuario: `~/.config/opencode/opencode.json`
14
+ ## Envoltorio: `bvsala opencode [args…]`
15
+
16
+ ```bash
17
+ export BIVELIO_SERVICE_KEY=bvk_…
18
+ bvsala opencode
19
+ ```
20
+
21
+ opencode acepta la configuración entera en la variable `OPENCODE_CONFIG_CONTENT`
22
+ y la fusiona **por encima** de la global y de la de proyecto (`config.ts`: se
23
+ carga después de `opencode.json` global, del de proyecto y de `.opencode/`; solo
24
+ la config de cuenta remota y la gestionada por la empresa van después) [V]. El
25
+ envoltorio arranca un gateway efímero y lanza `opencode` con esa variable
26
+ apuntando `provider.anthropic.options.baseURL` a `http://127.0.0.1:<puerto>/v1`.
27
+ **No escribe nada en disco** y todo muere al salir.
28
+
29
+ - Si ya exportas tu propio `OPENCODE_CONFIG_CONTENT`, el envoltorio lo
30
+ **fusiona**: solo cambia `provider.anthropic.options.baseURL`; tu clave, tus
31
+ modelos y lo demás siguen igual. Si no es un objeto JSON (por ejemplo, JSONC
32
+ con comentarios), se niega antes de arrancar y no repite su valor.
33
+ - Solo pasa por el gateway el proveedor `anthropic`. Los demás proveedores
34
+ (OpenAI, OpenCode Zen, OpenRouter…) van directos y no se miden.
35
+ - Al salir imprime cuántas peticiones midió y cuáles reenvió sin medir, y por qué.
36
+
37
+ ## Manual: `~/.config/opencode/opencode.json`
13
38
 
14
39
  ```json
15
40
  {
@@ -27,11 +52,6 @@
27
52
  [V]. El `opencode.json` de proyecto pisa al global: si tienes uno en el repo,
28
53
  ahí es donde manda.
29
54
 
30
- No hay envoltorio `bvsala opencode`: el enrutado es config de usuario. El
31
- `bvsala doctor --write opencode` previsto en S3 hará un merge JSON conservador
32
- de este bloque (con copia `.bak`) en tu config de usuario, nunca en archivos
33
- del repo.
34
-
35
55
  ### Alternativa [V]: `baseURL` desde variable de entorno
36
56
 
37
57
  ```json
@@ -56,10 +76,12 @@ opencode
56
76
 
57
77
  - **Sin `/v1`** → opencode pide `http://127.0.0.1:8402/messages` → `[gateway] POST /messages → 404`.
58
78
  - **Barra final** (`…/v1/`) → no.
59
- - **Config de proyecto** con otro `baseURL` pisando al global sin que lo sepas.
79
+ - **Config de proyecto** con otro `baseURL` pisando al global sin que lo sepas
80
+ (con el envoltorio no pasa: su variable manda sobre los dos).
60
81
  - **Gateway apagado con la config escrita**: opencode falla hasta que arranques
61
82
  `bvsala gateway` de nuevo. La config es persistente; el gateway, no. (La
62
- variante `{env:…}` sin exportar la variable también falla, por vacío.)
83
+ variante `{env:…}` sin exportar la variable también falla, por vacío.) El
84
+ envoltorio no tiene esta trampa.
63
85
 
64
86
  ## Nota BYOK
65
87
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivelio/savings-layer",
3
- "version": "0.4.24",
3
+ "version": "0.4.26",
4
4
  "description": "The savings layer for your LLM bill: a library inside your code that lets through only what has to be paid for and returns a SavingsReport per call, measured with your provider's own meter and kept apart from estimates. Commercial license, paid per seat, commission only on measured savings. Your prompts never leave your infrastructure.",
5
5
  "keywords": [
6
6
  "llm",
@@ -15,6 +15,10 @@
15
15
  "email": "support@bivelio.com",
16
16
  "url": "https://savings.bivelio.com"
17
17
  },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/BiVelio/bivelio-savings-layer.git"
21
+ },
18
22
  "license": "SEE LICENSE IN LICENSE",
19
23
  "author": "BiVelio Inc.",
20
24
  "type": "module",
@@ -27,6 +31,26 @@
27
31
  "import": "./dist/index.js",
28
32
  "default": "./dist/index.js"
29
33
  },
34
+ "./ai-sdk": {
35
+ "types": "./dist/adapters/ai-sdk.d.ts",
36
+ "import": "./dist/adapters/ai-sdk.js",
37
+ "default": "./dist/adapters/ai-sdk.js"
38
+ },
39
+ "./mastra": {
40
+ "types": "./dist/adapters/mastra.d.ts",
41
+ "import": "./dist/adapters/mastra.js",
42
+ "default": "./dist/adapters/mastra.js"
43
+ },
44
+ "./langchain": {
45
+ "types": "./dist/adapters/langchain.d.ts",
46
+ "import": "./dist/adapters/langchain.js",
47
+ "default": "./dist/adapters/langchain.js"
48
+ },
49
+ "./anthropic-sdk": {
50
+ "types": "./dist/adapters/anthropic-sdk.d.ts",
51
+ "import": "./dist/adapters/anthropic-sdk.js",
52
+ "default": "./dist/adapters/anthropic-sdk.js"
53
+ },
30
54
  "./package.json": "./package.json"
31
55
  },
32
56
  "bin": {
@@ -52,13 +76,23 @@
52
76
  "build:all": "pnpm run build:packages && pnpm run build:services && pnpm run build",
53
77
  "typecheck": "tsc --noEmit",
54
78
  "typecheck:packages": "pnpm -r --filter=./packages/* --filter=./services/* typecheck",
55
- "typecheck:all": "pnpm run typecheck && pnpm run typecheck:packages",
79
+ "typecheck:all": "pnpm run typecheck && pnpm run typecheck:packages && pnpm run typecheck:ejemplos",
80
+ "typecheck:ejemplos": "tsc -p examples/stacks/tsconfig.json",
56
81
  "test": "vitest run",
57
82
  "test:watch": "vitest",
58
83
  "lint": "tsc --noEmit",
59
84
  "example:basic": "BVSALA_DEV_OPEN=1 tsx examples/basic/index.ts",
60
85
  "example:handoff": "BVSALA_DEV_OPEN=1 tsx examples/multi-agent/handoff.ts",
61
86
  "example:serialization": "BVSALA_DEV_OPEN=1 tsx examples/serialization/format-selector.ts",
87
+ "example:otel": "BVSALA_DEV_OPEN=1 tsx examples/exporters/otel.ts",
88
+ "example:focus": "BVSALA_DEV_OPEN=1 tsx examples/exporters/focus.ts",
89
+ "example:nextjs": "BVSALA_DEV_OPEN=1 tsx examples/stacks/nextjs/run.ts",
90
+ "example:express": "BVSALA_DEV_OPEN=1 tsx examples/stacks/express/server.ts",
91
+ "example:ai-sdk": "BVSALA_DEV_OPEN=1 tsx examples/stacks/ai-sdk/bivelio-check.ts",
92
+ "example:mastra": "BVSALA_DEV_OPEN=1 tsx examples/stacks/mastra/bivelio-check.ts",
93
+ "example:langchain": "BVSALA_DEV_OPEN=1 tsx examples/stacks/langchain/bivelio-check.ts",
94
+ "example:anthropic-sdk": "BVSALA_DEV_OPEN=1 tsx examples/stacks/anthropic-sdk/bivelio-check.ts",
95
+ "init:ejemplos": "tsx scripts/ejemplos-de-init.ts",
62
96
  "example:licensed": "tsx examples/licensing/licensed.ts",
63
97
  "license:demo": "tsx examples/licensing/demo.ts",
64
98
  "example:revocation": "tsx examples/licensing/revocation.ts",
@@ -72,10 +106,13 @@
72
106
  "web:dev": "node apps/web/serve.mjs",
73
107
  "prepublishOnly": "pnpm run build",
74
108
  "ab:publish": "tsx benchmarks/publish.ts",
109
+ "ab:sonda": "BVSALA_DEV_OPEN=1 tsx --env-file-if-exists=.env.bench benchmarks/sonda-del-banco.ts",
110
+ "medicion:reproducir": "node apps/web/public/measure/reproduce.mjs",
75
111
  "verja:calibrar": "tsx corpus/calibrar-la-verja.ts",
76
112
  "corpus:arnes": "tsx corpus/arnes/informe.ts",
77
113
  "corpus:auditar": "tsx corpus/auditoria/auditar.ts",
78
114
  "sombra:corpus": "tsx benchmarks/sombra-corpus.ts",
115
+ "compactacion:banco": "tsx benchmarks/compactacion-de-cola/banco.ts",
79
116
  "sombra:diales": "tsx --env-file-if-exists=.env.bench benchmarks/sombra-diales.ts",
80
117
  "anillo1": "tsx --env-file-if-exists=.env.bench benchmarks/anillo1/arnes.ts",
81
118
  "anillo2": "tsx benchmarks/anillo2/arnes.ts",
@@ -84,25 +121,72 @@
84
121
  "salida": "tsx --env-file-if-exists=.env.bench benchmarks/salida/arnes.ts",
85
122
  "salida:anatomia": "tsx benchmarks/salida/anatomia.ts",
86
123
  "salida:por-clase": "tsx benchmarks/salida/por-clase.ts",
124
+ "esfuerzo": "tsx --env-file-if-exists=.env.bench benchmarks/esfuerzo/banco.ts",
87
125
  "luz-verde": "bash scripts/luz-verde.sh",
88
- "sonda:sdk": "BVSALA_DEV_OPEN=1 tsx --env-file-if-exists=.env.bench benchmarks/sdk/sonda.ts"
126
+ "sonda:sdk": "BVSALA_DEV_OPEN=1 tsx --env-file-if-exists=.env.bench benchmarks/sdk/sonda.ts",
127
+ "sbom:tarball": "tsx scripts/sbom.ts",
128
+ "cache-semantica": "BVSALA_DEV_OPEN=1 tsx benchmarks/cache-semantica/arnes.ts",
129
+ "cache-semantica:publicar": "tsx benchmarks/cache-semantica/publicar.ts",
130
+ "latencia:gateways": "tsx benchmarks/latencia-gateways/arnes.ts",
131
+ "vigia:conexiones": "tsx benchmarks/latencia-gateways/vigia-conexiones.ts",
132
+ "cache-semantica:calibrada": "BVSALA_DEV_OPEN=1 tsx benchmarks/cache-semantica/calibrada.ts",
133
+ "cache-semantica:simulacion": "tsx benchmarks/cache-semantica/simulacion.ts"
89
134
  },
90
135
  "devDependencies": {
91
136
  "@noble/curves": "^2.2.0",
137
+ "@opentelemetry/api": "^1.9.1",
138
+ "@opentelemetry/sdk-trace-base": "^2.11.0",
92
139
  "@types/node": "^22.10.2",
93
140
  "gpt-tokenizer": "^3.4.0",
141
+ "hyparquet": "^1.31.2",
94
142
  "tsup": "^8.3.5",
95
143
  "tsx": "^4.19.2",
96
144
  "typescript": "^5.7.2",
97
- "vitest": "^2.1.8"
145
+ "vitest": "^2.1.8",
146
+ "@ai-sdk/anthropic": "4.0.65",
147
+ "@ai-sdk/openai": "4.0.78",
148
+ "@anthropic-ai/sdk": "0.128.0",
149
+ "@langchain/core": "1.2.13",
150
+ "@langchain/openai": "1.6.0",
151
+ "@mastra/core": "1.71.0",
152
+ "ai": "7.0.118",
153
+ "ai-v6": "npm:ai@6.0.293",
154
+ "@types/express": "5.0.6",
155
+ "express": "5.2.1",
156
+ "langchain": "1.5.14",
157
+ "zod": "4.6.5"
98
158
  },
99
159
  "packageManager": "pnpm@10.17.1",
100
160
  "peerDependencies": {
101
- "gpt-tokenizer": "^3"
161
+ "@opentelemetry/api": "^1.9.0",
162
+ "gpt-tokenizer": "^3",
163
+ "@anthropic-ai/sdk": ">=0.103.0 <1",
164
+ "@langchain/core": ">=1.1.0 <2",
165
+ "@mastra/core": ">=1.68.0 <2",
166
+ "ai": "^6.0.0 || ^7.0.0",
167
+ "langchain": ">=1.1.0 <2"
102
168
  },
103
169
  "peerDependenciesMeta": {
170
+ "@opentelemetry/api": {
171
+ "optional": true
172
+ },
104
173
  "gpt-tokenizer": {
105
174
  "optional": true
175
+ },
176
+ "@anthropic-ai/sdk": {
177
+ "optional": true
178
+ },
179
+ "@langchain/core": {
180
+ "optional": true
181
+ },
182
+ "@mastra/core": {
183
+ "optional": true
184
+ },
185
+ "ai": {
186
+ "optional": true
187
+ },
188
+ "langchain": {
189
+ "optional": true
106
190
  }
107
191
  }
108
192
  }