@bivelio/savings-layer 0.4.35 → 0.4.36

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/dist/index.d.ts CHANGED
@@ -339,7 +339,7 @@ declare function precioDeLista$1(model: string, at?: Date | number): CostModel |
339
339
  * on the customer's machine. `test/version-declarada.test.ts` ties this
340
340
  * constant to package.json so the two can never drift.
341
341
  */
342
- declare const BV_SALA_VERSION = "0.4.35";
342
+ declare const BV_SALA_VERSION = "0.4.36";
343
343
 
344
344
  /**
345
345
  * Environment-agnostic UUID generation.
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ for(let n of ef[t]??[])if(!(n.vigenteDesde!==void 0&&e<n.vigenteDesde)&&!(n.vige
28
28
  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"],si={...Rt,...Object.
29
29
  fromEntries(nf.map(t=>[t,null]))},rf=ci(si);function Xt(t,e){let n=Qt(t);return n===void 0?void 0:ec(n,Qa(e))}var of=Object.fromEntries(Object.keys(si).map(t=>[t,si[t]===null?null:t]));function Qt(t){
30
30
  return ai(of,rf,t)??void 0}var sf=/^\d{4}-?\d{2}-?\d{2}$/;function st(t,e){let n=Qt(t);if(n===void 0)return;let r=t.lastIndexOf("/"),o=r>=0?t.slice(r+1):t;if(!(n!==t&&n!==o&&!sf.test(o.slice(n.length+
31
- 1))))return ec(n,Qa(e))}var Ve="0.4.35",wr="x-bvsala-version";var af=0;function Pt(){let t=globalThis.crypto;if(t?.randomUUID)return t.randomUUID();let e=new Uint8Array(16);if(t?.getRandomValues)t.getRandomValues(e);else {let r=++af,o=Date.now?Date.now():0;for(let i=0;i<
31
+ 1))))return ec(n,Qa(e))}var Ve="0.4.36",wr="x-bvsala-version";var af=0;function Pt(){let t=globalThis.crypto;if(t?.randomUUID)return t.randomUUID();let e=new Uint8Array(16);if(t?.getRandomValues)t.getRandomValues(e);else {let r=++af,o=Date.now?Date.now():0;for(let i=0;i<
32
32
  16;i++)e[i]=(i<6?r>>>i*8:o>>>(i-6)*8)&255;}e[6]=e[6]&15|64,e[8]=e[8]&63|128;let n=[];for(let r=0;r<16;r++)n.push(e[r].toString(16).padStart(2,"0"));return `${n[0]}${n[1]}${n[2]}${n[3]}-${n[4]}${n[5]}-${n[6]}${n[7]}\
33
33
  -${n[8]}${n[9]}-${n[10]}${n[11]}${n[12]}${n[13]}${n[14]}${n[15]}`}var ek=["exact","task_equivalent","not_verified","bounded_degradation","rejected"];function nk(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 li=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
34
  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,
@@ -722,26 +722,26 @@ done",response:c};return}let r=cs(e.model),o=await this.enviarConCorrecciones(r,
722
722
  isArray(c)?c:[c])i.sumar(l);if(!i.terminado())throw new Error("provider stream ended before completion (no finishReason)");i.texto!==""&&(yield {type:"text",delta:i.texto}),yield {type:"done",response:this.
723
723
  cerrar(i,e,o,c)};return}let s=o.body,a=s&&typeof s.getReader=="function"?s:await o.text();for await(let c of un(a)){let l;try{l=JSON.parse(c.data);}catch{continue}if(l===null||typeof l!="object")continue;
724
724
  let u=i.sumar(l);u!==""&&(yield {type:"text",delta:u});}if(!i.terminado())throw new Error("provider stream ended before completion (no finishReason)");yield {type:"done",response:this.cerrar(i,e,o,i.uso??
725
- null)};}async enviarConCorrecciones(e,n,r,o){let i=await this.enviar(e,n,r,o);for(let s=0;s<3&&!i.ok&&i.status===400;s++){let a=await ls(i),c=Fl(a),l=this.cuerpo(e,n).generationConfig?.thinkingConfig?.
726
- thinkingLevel;if(c===null||l===void 0||c!==String(l).toUpperCase())throw new Error(`provider ${i.status}: ${a}`);let u=c==="MINIMAL"?"LOW":null,d=this.nivelAprendido.get(e)??new Map;d.set(c,u),this.nivelAprendido.
727
- set(e,d),Ce(this,`google-nivel:${this.base}:${e}:${c}`,`[bvsala] Model "${e}" rejects thinkingLevel ${c} with a 400, so `+(u?`${u} is sent instead`:"no thinking level is sent (the model's default)")+"\
728
- (the rejected request was not billed; the model is noted and the following requests go straight there)."),i=await this.enviar(e,n,r,o);}if(!i.ok)throw new Error(`provider ${i.status}: ${await ls(i)}`);
729
- return i}async enviar(e,n,r,o){let i=r?"streamGenerateContent?alt=sse":"generateContent";return await this.fetchImpl(`${this.base}/models/${encodeURIComponent(e)}:${i}`,{method:"POST",headers:{"conten\
730
- t-type":"application/json",...this.opts.apiKey?{"x-goog-api-key":this.opts.apiKey}:{},...this.opts.headers},body:JSON.stringify(this.cuerpo(e,n)),...o?{signal:o}:{}})}cuerpo(e,n){let{systemInstruction:r,
731
- contents:o}=ql(n.messages),i={};n.maxOutputTokens!=null&&(i.maxOutputTokens=n.maxOutputTokens),n.temperature!=null&&(i.temperature=n.temperature),n.seed!=null&&(i.seed=n.seed),n.schema!=null&&(i.responseMimeType=
732
- "application/json",i.responseJsonSchema=n.schema);let s=this.pensamiento(e,n);s!==void 0&&(i.thinkingConfig=s);let a=n.tools&&n.tools.length>0?[{functionDeclarations:n.tools.map(c=>({name:c.id,description:c.
733
- description??"",...c.parameters!=null?{parametersJsonSchema:c.parameters}:{}}))}]:void 0;return {contents:o,...r?{systemInstruction:r}:{},...a?{tools:a}:{},...this.opts.safetySettings?{safetySettings:this.
734
- opts.safetySettings}:{},...Object.keys(i).length>0?{generationConfig:i}:{},...n.deferrable===true?{serviceTier:We}:{}}}pensamiento(e,n){let r=this.opts.thinkingConfig?{...this.opts.thinkingConfig}:void 0;
735
- if(n.reasoningEffort!=null){let i=zl(e,n.reasoningEffort);if(i===null)Ce(this,`google-esfuerzo:${e}:${n.reasoningEffort}`,`[bvsala] reasoningEffort "${n.reasoningEffort}" has no equivalent on "${e}" (\
736
- thinking cannot be turned off on Gemini 2.5 Pro), so no thinking config is sent for it.`);else {i.noSeApaga&&Ce(this,`google-no-se-apaga:${e}`,`[bvsala] Thinking cannot be turned off on "${e}" (Google:\
737
- \xABReasoning cannot be turned off for Gemini 2.5 Pro or 3 models\xBB), so reasoningEffort "none" is sent as the lowest level, ${String(i.config.thinkingLevel)}. Its thinking tokens are billed as out\
738
- put.`);let{thinkingLevel:s,thinkingBudget:a,...c}=r??{};r={...c,...i.config};}}let o=r?.thinkingLevel;if(r&&typeof o=="string"){let i=this.nivelAprendido.get(e),s=o.toUpperCase();if(i?.has(s)){let a=i.
739
- get(s),{thinkingLevel:c,...l}=r;r=a?{...l,thinkingLevel:a}:l;}}return r&&Object.keys(r).length>0?r:void 0}cerrar(e,n,r,o){let i=Ul(e.uso,e.huboPensamiento);if(this.opts.requireUsage===true&&i.complete===
740
- false)throw new Error(`provider returned incomplete usage (promptTokenCount=${e.uso?.promptTokenCount??"absent"}, candidatesTokenCount=${e.uso?.candidatesTokenCount??"absent"}); cannot measure cost.`);let s=Bl(
741
- e.paradaNativa,e.bloqueo,e.llamadas.length>0),a=typeof e.uso?.serviceTier=="string"&&e.uso.serviceTier!==""?e.uso.serviceTier:void 0,c=a?"cuerpo":void 0;return !a&&this.oficial&&(a=Vl(r,jl),a&&(c="cabe\
742
- cera")),dt({text:e.texto,...e.llamadas.length>0?{toolCalls:e.llamadas}:{},...s.parada!==void 0?{finishReason:s.parada}:{},...s.detalle!==void 0?{finishReasonDetail:s.detalle}:{},...a?{servedServiceTier:a}:
743
- {},...n.deferrable===true?{requestedServiceTier:We}:{},...s.reproducible?{}:{replayable:false},...e.idDeRespuesta?{providerMessageId:e.idDeRespuesta}:{},usage:i,structuredNatively:n.schema!=null,raw:o},{...Mt(
744
- 0),esquemaEnFormatoNativo:n.schema!=null,origen:this.oficial?"google":null,...c?{tierLeidoDe:c}:{}})}};var pt=class{events=[];start;now;constructor(e=()=>Date.now()){this.now=e,this.start=e();}record(e,n,r){this.events.push({stage:e,outcome:n,...r?{detail:r}:{},atMs:this.now()-this.start});}elapsed(){return this.
725
+ null)};}async enviarConCorrecciones(e,n,r,o){let i=this.cuerpo(e,n),s=await this.enviar(e,i,r,o);for(let a=0;a<3&&!s.ok&&s.status===400;a++){let c=await ls(s),l=Fl(c),u=i.generationConfig?.thinkingConfig?.
726
+ thinkingLevel;if(l===null||u===void 0||l!==String(u).toUpperCase())throw new Error(`provider ${s.status}: ${c}`);let d=this.nivelAprendido.get(e)??new Map;if(!d.has(l)){let p=l==="MINIMAL"?"LOW":null;
727
+ d.set(l,p),this.nivelAprendido.set(e,d),Ce(this,`google-nivel:${this.base}:${e}:${l}`,`[bvsala] Model "${e}" rejects thinkingLevel ${l} with a 400, so `+(p?`${p} is sent instead`:"no thinking level is\
728
+ sent (the model's default)")+" (the rejected request was not billed; the model is noted and the following requests go straight there).");}i=this.cuerpo(e,n),s=await this.enviar(e,i,r,o);}if(!s.ok)throw new Error(
729
+ `provider ${s.status}: ${await ls(s)}`);return s}async enviar(e,n,r,o){let i=r?"streamGenerateContent?alt=sse":"generateContent";return await this.fetchImpl(`${this.base}/models/${encodeURIComponent(e)}\
730
+ :${i}`,{method:"POST",headers:{"content-type":"application/json",...this.opts.apiKey?{"x-goog-api-key":this.opts.apiKey}:{},...this.opts.headers},body:JSON.stringify(n),...o?{signal:o}:{}})}cuerpo(e,n){
731
+ let{systemInstruction:r,contents:o}=ql(n.messages),i={};n.maxOutputTokens!=null&&(i.maxOutputTokens=n.maxOutputTokens),n.temperature!=null&&(i.temperature=n.temperature),n.seed!=null&&(i.seed=n.seed),
732
+ n.schema!=null&&(i.responseMimeType="application/json",i.responseJsonSchema=n.schema);let s=this.pensamiento(e,n);s!==void 0&&(i.thinkingConfig=s);let a=n.tools&&n.tools.length>0?[{functionDeclarations:n.
733
+ tools.map(c=>({name:c.id,description:c.description??"",...c.parameters!=null?{parametersJsonSchema:c.parameters}:{}}))}]:void 0;return {contents:o,...r?{systemInstruction:r}:{},...a?{tools:a}:{},...this.
734
+ opts.safetySettings?{safetySettings:this.opts.safetySettings}:{},...Object.keys(i).length>0?{generationConfig:i}:{},...n.deferrable===true?{serviceTier:We}:{}}}pensamiento(e,n){let r=this.opts.thinkingConfig?
735
+ {...this.opts.thinkingConfig}:void 0;if(n.reasoningEffort!=null){let i=zl(e,n.reasoningEffort);if(i===null)Ce(this,`google-esfuerzo:${e}:${n.reasoningEffort}`,`[bvsala] reasoningEffort "${n.reasoningEffort}\
736
+ " has no equivalent on "${e}" (thinking cannot be turned off on Gemini 2.5 Pro), so no thinking config is sent for it.`);else {i.noSeApaga&&Ce(this,`google-no-se-apaga:${e}`,`[bvsala] Thinking cannot b\
737
+ e turned off on "${e}" (Google: \xABReasoning cannot be turned off for Gemini 2.5 Pro or 3 models\xBB), so reasoningEffort "none" is sent as the lowest level, ${String(i.config.thinkingLevel)}. Its th\
738
+ inking tokens are billed as output.`);let{thinkingLevel:s,thinkingBudget:a,...c}=r??{};r={...c,...i.config};}}let o=r?.thinkingLevel;if(r&&typeof o=="string"){let i=this.nivelAprendido.get(e),s=o.toUpperCase();
739
+ if(i?.has(s)){let a=i.get(s),{thinkingLevel:c,...l}=r;r=a?{...l,thinkingLevel:a}:l;}}return r&&Object.keys(r).length>0?r:void 0}cerrar(e,n,r,o){let i=Ul(e.uso,e.huboPensamiento);if(this.opts.requireUsage===
740
+ true&&i.complete===false)throw new Error(`provider returned incomplete usage (promptTokenCount=${e.uso?.promptTokenCount??"absent"}, candidatesTokenCount=${e.uso?.candidatesTokenCount??"absent"}); cannot m\
741
+ easure cost.`);let s=Bl(e.paradaNativa,e.bloqueo,e.llamadas.length>0),a=typeof e.uso?.serviceTier=="string"&&e.uso.serviceTier!==""?e.uso.serviceTier:void 0,c=a?"cuerpo":void 0;return !a&&this.oficial&&
742
+ (a=Vl(r,jl),a&&(c="cabecera")),dt({text:e.texto,...e.llamadas.length>0?{toolCalls:e.llamadas}:{},...s.parada!==void 0?{finishReason:s.parada}:{},...s.detalle!==void 0?{finishReasonDetail:s.detalle}:{},
743
+ ...a?{servedServiceTier:a}:{},...n.deferrable===true?{requestedServiceTier:We}:{},...s.reproducible?{}:{replayable:false},...e.idDeRespuesta?{providerMessageId:e.idDeRespuesta}:{},usage:i,structuredNatively:n.
744
+ schema!=null,raw:o},{...Mt(0),esquemaEnFormatoNativo:n.schema!=null,origen:this.oficial?"google":null,...c?{tierLeidoDe:c}:{}})}};var pt=class{events=[];start;now;constructor(e=()=>Date.now()){this.now=e,this.start=e();}record(e,n,r){this.events.push({stage:e,outcome:n,...r?{detail:r}:{},atMs:this.now()-this.start});}elapsed(){return this.
745
745
  now()-this.start}all(){return this.events}};var Ke=class extends Error{status;constructor(e,n){super(e),this.name="LicenseError",n&&(this.status=n);}};function us(t){return t instanceof Uint8Array||ArrayBuffer.isView(t)&&t.constructor.name==="Uint8Array"&&"BYTES_PER_ELEMENT"in t&&t.BYTES_PER_ELEMENT===1}function io(t,e=""){if(typeof t!="number"){let n=e&&
746
746
  `"${e}" `;throw new TypeError(`${n}expected number, got ${typeof t}`)}if(!Number.isSafeInteger(t)||t<0){let n=e&&`"${e}" `;throw new RangeError(`${n}expected integer >= 0, got ${t}`)}}function De(t,e,n=""){
747
747
  let r=us(t),o=t?.length,i=e!==void 0;if(!r||i&&o!==e){let s=n&&`"${n}" `,a=i?` of length ${e}`:"",c=r?`length=${o}`:`type=${typeof t}`,l=s+"expected Uint8Array"+a+", got "+c;throw r?new RangeError(l):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bivelio/savings-layer",
3
- "version": "0.4.35",
3
+ "version": "0.4.36",
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",