@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/gateway/bin.js +820 -816
- package/dist/index.d.ts +1 -1
- package/dist/index.js +21 -21
- package/package.json +1 -1
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.
|
|
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.
|
|
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,
|
|
726
|
-
thinkingLevel;if(
|
|
727
|
-
set(e,d),Ce(this,`google-nivel:${this.base}:${e}:${
|
|
728
|
-
(the rejected request was not billed; the model is noted and the following requests go straight there).")
|
|
729
|
-
return
|
|
730
|
-
|
|
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),
|
|
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.
|
|
733
|
-
description??"",...c.parameters!=null?{parametersJsonSchema:c.parameters}:{}}))}]:void 0;return {contents:o,...r?{systemInstruction:r}:{},...a?{tools:a}:{},...this.
|
|
734
|
-
opts.safetySettings}:{},...Object.keys(i).length>0?{generationConfig:i}:{},...n.deferrable===true?{serviceTier:We}:{}}}pensamiento(e,n){let r=this.opts.thinkingConfig?
|
|
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}
|
|
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
|
|
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
|
|
738
|
-
|
|
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===
|
|
740
|
-
false)throw new Error(`provider returned incomplete usage (promptTokenCount=${e.uso?.promptTokenCount??"absent"}, candidatesTokenCount=${e.uso?.candidatesTokenCount??"absent"}); cannot
|
|
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&&
|
|
742
|
-
|
|
743
|
-
{},...n.deferrable===true?{requestedServiceTier:We}:{},...s.reproducible?{}:{replayable:false},...e.idDeRespuesta?{providerMessageId:e.idDeRespuesta}:{},usage:i,structuredNatively:n.
|
|
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.
|
|
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",
|