@bivelio/savings-layer 1.1.0 → 1.1.1

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.1 — corrected packaging text
4
+
5
+ - The Python client's README and module docstring no longer say "Commercial
6
+ software … paid to run": they state the Apache-2.0 open-core license, matching
7
+ the package and the gateway it talks to.
8
+ - The npm README no longer says "the repository is private" (it is public) and
9
+ links the paper as v2.2.
10
+
3
11
  ## 1.1.0 — savings levers reach the batch surface, cache audit, cascade 2026
4
12
 
5
13
  ### Added
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://savings.bivelio.com/brand/savings-logo.png" alt="Savings. by BiVelio" width="360">
2
+ <img src="https://savings.bivelio.com/brand/og-image.png" alt="BiVelio Savings Layer" width="720">
3
3
  </p>
4
4
 
5
5
  <h1 align="center">The savings layer for your LLM bill</h1>
@@ -98,7 +98,7 @@ installed coding agent. The published benchmark, trial by trial, with the raw CS
98
98
  is at **[savings.bivelio.com/en/how-it-works](https://savings.bivelio.com/en/how-it-works)**.
99
99
 
100
100
  📄 **The paper:** [Verifiable Measurement of Cost Savings in LLM Applications
101
- (open-core edition, v2)](./docs/PAPER.md) — live double-runs, percentile cluster
101
+ (open-core edition, v2.2)](./docs/PAPER.md) — live double-runs, percentile cluster
102
102
  bootstrap, four ledgers, and every limitation stated. Also at
103
103
  **[savings.bivelio.com/paper](https://savings.bivelio.com/paper)**.
104
104
 
@@ -172,8 +172,8 @@ the limits): `cache_control` and its 1-hour TTL, tool search and
172
172
  `tool_reference` blocks, the advisor, every `anthropic-beta` value. An armed lever
173
173
  changes only what it declares, and a request it cannot rewrite exactly travels
174
174
  untouched. A test suite checks this against a fake upstream on every change
175
- (`test/gateway-no-empeora.test.ts`; the repository is private, so the linked
176
- section lists exactly what it checks). The gateway also logs, once per session,
175
+ (`test/gateway-no-empeora.test.ts`; the section below lists exactly what it
176
+ checks). The gateway also logs, once per session,
177
177
  requests that come out worse than your client asked for: cache markers the
178
178
  provider ignored, a 1-hour TTL written at 5 minutes upstream, and tool search off
179
179
  (Claude Code turns it off by default behind any proxy, this one included;
@@ -1462,7 +1462,9 @@ BVSALA_SEAT_ID=worker-03 # stable per replica; [A-Za-z0-9._:/-], max 128 chars
1462
1462
 
1463
1463
  ## Licensing & privacy
1464
1464
 
1465
- BV‑SALA is commercial software. The plans are **Measure** (free), **Pro** (per seat),
1465
+ BV‑SALA is open core: the npm package is **Apache-2.0** and free — install it with no keys
1466
+ (COMMUNITY mode runs every local lever, zero telemetry, nothing sent to BiVelio). The
1467
+ optional **cloud** is commercial. Its plans are **Measure** (free), **Pro** (per seat),
1466
1468
  **Team** (a number of seats included, plus each extra seat) and **Enterprise** (by
1467
1469
  contract); Pro and Team are paid whether or not you save and carry **no commission** on
1468
1470
  your savings. The prices are at the top of this page, in [LICENSE-CLOUD.md](./LICENSE-CLOUD.md) §6 and in
@@ -168,7 +168,7 @@ bp.test(n.betas))return null;let o=gt(e,t);if(o===null||vp(o))return null;let r=
168
168
  let o=Object.entries(ka).map(([r,i])=>`${r}\u2192${i}`).join(", ");return e!=="1"?{linea:"sibling model routing: OFF (BVSALA_GATEWAY_SIBLING_MODEL=1 turns it on)",aviso:false}:n?{linea:`sibling model r\
169
169
  outing: ARMED (${o}; ON if your licence includes sibling_model_routing; fail-closed). Changes the model you see in the response; cache reads cost 0.025\xD7 instead of 0.1\xD7 (list price). Turning it on mid\
170
170
  -conversation pays one cold prefix write, once. If the provider rejects the rewritten request (400), it is re-sent unchanged once`,aviso:false}:{linea:"sibling model routing: NOT ARMED - BVSALA_GATEWAY_E\
171
- LISION=0 turns off the levers",aviso:true}}var xa=new Set;function Z(e,t){xa.has(e)||(xa.add(e),console.warn(t));}var ye="1.1.0",Ur="x-bvsala-version";var Xt=class{options;now;flushIntervalMs;maxBatch;maxBuffer;buffer=[];seatId;ci;timer;inflight=null;fallosSeguidos=0;contadores={sent:0,requeued:0,discarded:0,dropped:0};constructor(t){this.options=t,
171
+ LISION=0 turns off the levers",aviso:true}}var xa=new Set;function Z(e,t){xa.has(e)||(xa.add(e),console.warn(t));}var ye="1.1.1",Ur="x-bvsala-version";var Xt=class{options;now;flushIntervalMs;maxBatch;maxBuffer;buffer=[];seatId;ci;timer;inflight=null;fallosSeguidos=0;contadores={sent:0,requeued:0,discarded:0,dropped:0};constructor(t){this.options=t,
172
172
  this.now=t.now??(()=>Date.now()),this.flushIntervalMs=t.flushIntervalMs??15e3,this.maxBatch=t.maxBatch??50,this.maxBuffer=t.maxBuffer??1e3,this.ci=t.ci??false;}setSeat(t,n){t&&(this.seatId=t),this.ci=n;}stats(){
173
173
  return {...this.contadores}}record(t){let n=this.now();this.buffer.push({report:t,at:n});let o=yp(t);if(o&&this.buffer.push({report:o,at:n}),this.buffer.length>this.maxBuffer){let r=this.buffer.length-
174
174
  this.maxBuffer;this.contadores.dropped+=r,this.buffer.splice(0,r);}this.buffer.length>=this.maxBatch&&this.flush();}start(){this.timer||(this.timer=setInterval(()=>{this.flush();},this.flushIntervalMs),this.
package/dist/index.d.ts CHANGED
@@ -1799,7 +1799,7 @@ declare function precioDeLista(model: string, at?: Date | number): CostModel | u
1799
1799
  * on the customer's machine. `test/version-declarada.test.ts` ties this
1800
1800
  * constant to package.json so the two can never drift.
1801
1801
  */
1802
- declare const BV_SALA_VERSION = "1.1.0";
1802
+ declare const BV_SALA_VERSION = "1.1.1";
1803
1803
 
1804
1804
  /**
1805
1805
  * Typed intermediate representation for LLM -> LLM handoffs.
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ for(let n of Df[t]??[])if(!(n.vigenteDesde!==void 0&&e<n.vigenteDesde)&&!(n.vige
31
31
  p-research","o4-mini-deep-research","gpt-5.5-pro","gpt-5.4-pro","gpt-5.2-pro","gpt-5-pro","gpt-5.5-cyber","gemini-3.8-flash-tts","gemini-3.8-flash-lite-tts","gemini-3.1-flash-lite-image"],li={...qt,...Object.
32
32
  fromEntries(If.map(t=>[t,null]))},Af=di(li);function yn(t,e){let n=Ut(t);return n===void 0?void 0:Tc(n,Ec(e))}var Of=Object.fromEntries(Object.keys(li).map(t=>[t,li[t]===null?null:t]));function Ut(t){
33
33
  return ui(Of,Af,t)??void 0}var Mf=/^\d{4}-?\d{2}-?\d{2}$/;function st(t,e){let n=Ut(t);if(n===void 0)return;let r=t.lastIndexOf("/"),o=r>=0?t.slice(r+1):t;if(!(n!==t&&n!==o&&!Mf.test(o.slice(n.length+
34
- 1))))return Tc(n,Ec(e))}var We="1.1.0",vr="x-bvsala-version";var Lf=["exact","task_equivalent","not_verified","bounded_degradation","rejected"];function $f(t){return {v:1,task:t.task,goal:t.goal,rules:t.rules??[],facts:t.facts??[],refs:t.refs??[],...t.delta?{delta:t.delta}:{},outputContract:t.outputContract}}var yr=class{id;exact=false;constructor(e="heuristic"){this.id=e;}count(e){if(e.length===0)return 0;let n=e.match(/[A-Za-z]+|\d+|\s+|[^\sA-Za-z\d]/g)??[],r=0;for(let o of n){let i=o[0];if(/\s/.test(i)){let s=(o.
34
+ 1))))return Tc(n,Ec(e))}var We="1.1.1",vr="x-bvsala-version";var Lf=["exact","task_equivalent","not_verified","bounded_degradation","rejected"];function $f(t){return {v:1,task:t.task,goal:t.goal,rules:t.rules??[],facts:t.facts??[],refs:t.refs??[],...t.delta?{delta:t.delta}:{},outputContract:t.outputContract}}var yr=class{id;exact=false;constructor(e="heuristic"){this.id=e;}count(e){if(e.length===0)return 0;let n=e.match(/[A-Za-z]+|\d+|\s+|[^\sA-Za-z\d]/g)??[],r=0;for(let o of n){let i=o[0];if(/\s/.test(i)){let s=(o.
35
35
  match(/\n/g)??[]).length;r+=s+Math.floor(Math.max(0,o.length-1)/2);}else /[A-Za-z]/.test(i)?r+=Math.max(1,Math.ceil(o.length/4)):/\d/.test(i)?r+=Math.max(1,Math.ceil(o.length/2)):r+=1;}return Math.max(r,
36
36
  Math.ceil(e.length/4))}},$e=new yr;var kr=class{estimators=new Map;modelToTokenizer=new Map;fallbackId;constructor(e=$e){this.fallbackId=e.id,this.estimators.set(e.id,e);}register(e){return this.estimators.set(e.id,e),this}mapModel(e,n){
37
37
  return this.modelToTokenizer.set(e,n),this}resolve(e){let n=e.tokenizer?this.estimators.get(e.tokenizer):void 0;if(n)return n;if(e.model){let r=this.modelToTokenizer.get(e.model);if(r){let o=this.estimators.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivelio/savings-layer",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "The savings layer for your LLM bill: a zero-dependency open-core layer inside your code — and a local gateway for coding agents — that lets through only what has to be paid for, and returns a SavingsReport per call measured with your provider's own meter. Apache-2.0, zero telemetry by default; the optional cloud adds team dashboard and shared caches.",
5
5
  "keywords": [
6
6
  "llm",