@bivelio/savings-layer 0.4.12 → 0.4.13
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 +76 -76
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/gateway/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {spawn}from'child_process';import {existsSync,readFileSync,mkdirSync,writeFileSync}from'fs';import {homedir}from'os';import {join,dirname,delimiter}from'path';import {fileURLToPath}from'url';import {createServer}from'http';import {randomUUID,createHash}from'crypto';import*as
|
|
2
|
+
import {spawn}from'child_process';import {existsSync,readFileSync,mkdirSync,writeFileSync}from'fs';import {homedir}from'os';import {join,dirname,delimiter}from'path';import {fileURLToPath}from'url';import {createServer}from'http';import {randomUUID,createHash}from'crypto';import*as A from'zlib';var $e=new Set;function E(e,t){$e.has(e)||($e.add(e),console.warn(t));}var z=class{options;now;flushIntervalMs;maxBatch;maxBuffer;buffer=[];seatId;ci;timer;inflight=null;fallosSeguidos=0;constructor(t){this.options=t,this.now=t.now??(()=>Date.now()),this.flushIntervalMs=
|
|
3
3
|
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;}record(t){this.buffer.push({report:t,at:this.now()}),this.
|
|
4
4
|
buffer.length>this.maxBuffer&&this.buffer.splice(0,this.buffer.length-this.maxBuffer),this.buffer.length>=this.maxBatch&&this.flush();}start(){this.timer||(this.timer=setInterval(()=>{this.flush();},this.
|
|
5
5
|
flushIntervalMs),this.timer.unref?.());}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0),this.flush();}async stopAndDrain(t){this.timer&&(clearInterval(this.timer),this.timer=void 0);let n=t??
|
|
@@ -24,7 +24,7 @@ if(e.KUBERNETES_SERVICE_HOST||_t(e))return;let n=e.HOSTNAME??e.COMPUTERNAME??awa
|
|
|
24
24
|
e.arch,e.execPath,n,t.USER??t.USERNAME??t.LOGNAME,t.HOME??t.USERPROFILE].filter(o=>typeof o=="string"&&o.length>0);return r.length?r.join("|"):void 0}var Ot=["CI","CONTINUOUS_INTEGRATION","GITHUB_ACTI\
|
|
25
25
|
ONS","GITLAB_CI","CIRCLECI","TRAVIS","JENKINS_URL","BUILDKITE","TF_BUILD","TEAMCITY_VERSION","BITBUCKET_BUILD_NUMBER","CODEBUILD_BUILD_ID","HEROKU_TEST_RUN_ID","DRONE"];function Z(){let e=X()?.env;if(!e)
|
|
26
26
|
return false;for(let t of Ot){let n=e[t];if(n&&n!=="false"&&n!=="0")return true}return false}async function Dt(e,t){let n=globalThis.crypto,r=new TextEncoder;if(n?.subtle)try{let i=await n.subtle.importKey("raw",
|
|
27
|
-
r.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),
|
|
27
|
+
r.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await n.subtle.sign("HMAC",i,r.encode(t));return [...new Uint8Array(a)].map(u=>u.toString(16).padStart(2,"0")).join("")}catch{}let o=2166136261,s=`${e}\
|
|
28
28
|
|${t}`;for(let i=0;i<s.length;i++)o^=s.charCodeAt(i),o=Math.imul(o,16777619);return (o>>>0).toString(16).padStart(8,"0")}async function ee(e){let n=X()?.env?.BVSALA_SEAT_ID;if(n&&Lt.test(n))return n;let r=await Pt();
|
|
29
29
|
if(!r)return;let o=await Dt(e,r);if(o)return `m-${o.slice(0,32)}`}var Lt=/^[A-Za-z0-9._:/-]{1,128}$/;var pe={"gpt-4.1":{inputPer1k:.002,outputPer1k:.008,cachedInputPer1k:5e-4},"gpt-4.1-mini":{inputPer1k:4e-4,outputPer1k:.0016,cachedInputPer1k:1e-4},"gpt-4.1-nano":{inputPer1k:1e-4,outputPer1k:4e-4,cachedInputPer1k:25e-6},
|
|
30
30
|
"gpt-4o":{inputPer1k:.0025,outputPer1k:.01,cachedInputPer1k:.00125},"gpt-4o-mini":{inputPer1k:15e-5,outputPer1k:6e-4,cachedInputPer1k:75e-6},"gpt-4-turbo":{inputPer1k:.01,outputPer1k:.03},"gpt-4":{inputPer1k:.03,
|
|
@@ -43,56 +43,56 @@ able-5":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:.001},"claude-sonnet-4"
|
|
|
43
43
|
cachedInputPer1k:.0015},"claude-3-haiku":{inputPer1k:25e-5,outputPer1k:.00125,cachedInputPer1k:3e-5},"gemini-3.7-flash":{inputPer1k:75e-5,outputPer1k:.00375,cachedInputPer1k:75e-6},"gemini-3.5-flash":{
|
|
44
44
|
inputPer1k:.0015,outputPer1k:.009,cachedInputPer1k:15e-5},"gemini-3.5-flash-lite":{inputPer1k:3e-4,outputPer1k:.0025,cachedInputPer1k:3e-5},"gemini-3.1-pro-preview":{inputPer1k:.002,outputPer1k:.012,cachedInputPer1k:2e-4},
|
|
45
45
|
"gemini-2.5-pro":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},"gemini-2.5-flash":{inputPer1k:3e-4,outputPer1k:.0025,cachedInputPer1k:3e-5}};function Ne(e,t,n){if(!n)return;let r=e[n];if(r)
|
|
46
|
-
return r;let o=n.lastIndexOf("/"),s=o>=0?n.slice(o+1):n,i=e[s];if(i)return i;for(let
|
|
47
|
-
slice(
|
|
46
|
+
return r;let o=n.lastIndexOf("/"),s=o>=0?n.slice(o+1):n,i=e[s];if(i)return i;for(let a of t){if(!s.startsWith(a))continue;let u=s.charAt(a.length);if(u!==""&&u!=="-"&&u!=="."&&u!=="_")continue;let p=s.
|
|
47
|
+
slice(a.length+1);if(!(/^\d/.test(p)&&!/^\d{4}/.test(p)))return e[a]}}function me(e){return Object.keys(e).sort((t,n)=>n.length-t.length)}var Mt=me(pe);function M(e){return Ne(pe,Mt,e)}var $=class{resto="";uso=null;elisionObservada=null;eventos={};observar(t){this.resto+=typeof t=="string"?t:t.toString("utf8");let n;for(;(n=this.resto.indexOf(`
|
|
48
48
|
|
|
49
49
|
`))>=0;){let r=this.resto.slice(0,n);this.resto=this.resto.slice(n+2);let o=/^event: (.+)$/m.exec(r)?.[1];if(o&&(this.eventos[o]=(this.eventos[o]??0)+1),o!=="message_start"&&o!=="message_delta")continue;
|
|
50
|
-
let s=/^data: (.+)$/m.exec(r)?.[1];if(s)try{let i=JSON.parse(s),
|
|
50
|
+
let s=/^data: (.+)$/m.exec(r)?.[1];if(s)try{let i=JSON.parse(s),a=ze(i.context_management);a&&(this.elisionObservada=a);let u=i.usage??i.message?.usage;if(u){let p=u.cache_creation||this.uso?.cache_creation?
|
|
51
51
|
{...this.uso?.cache_creation,...u.cache_creation}:void 0;this.uso={...this.uso,...u,...p?{cache_creation:p}:{}};}}catch{}}}usage(){return this.uso}usageFinal(){return (this.eventos.message_delta??0)>0?this.
|
|
52
52
|
uso:null}elision(){return this.elisionObservada}};function ze(e){if(e===null||typeof e!="object")return null;let t=e.applied_edits;if(!Array.isArray(t)||t.length===0)return null;let n=0;for(let r of t){
|
|
53
53
|
let o=r.cleared_input_tokens;typeof o=="number"&&Number.isFinite(o)&&o>0&&(n+=o);}return {borrados:t.length,tokensLimpiados:n}}function Be(e){try{let t=JSON.parse(typeof e=="string"?e:e.toString("utf8"));
|
|
54
54
|
return ze(t.context_management)}catch{return null}}var te=class{resto="";uso=null;eventos={};observar(t){this.resto+=typeof t=="string"?t:t.toString("utf8");let n;for(;(n=this.resto.indexOf(`
|
|
55
55
|
|
|
56
56
|
`))>=0;){let r=this.resto.slice(0,n);this.resto=this.resto.slice(n+2);let o=/^event: (.+)$/m.exec(r)?.[1];o&&(this.eventos[o]=(this.eventos[o]??0)+1);let s=/^data: (.+)$/m.exec(r)?.[1];if(s)try{let i=JSON.
|
|
57
|
-
parse(s);if((o??i.type)!=="response.completed")continue;let
|
|
57
|
+
parse(s);if((o??i.type)!=="response.completed")continue;let a=i.response?.usage;a&&(this.uso=$t(a));}catch{}}}usage(){return this.uso}usageFinal(){return this.uso}};function $t(e){let t=Math.max(0,e.input_tokens??
|
|
58
58
|
0),n=Math.min(Math.max(0,e.input_tokens_details?.cached_tokens??0),t),r=Math.min(Math.max(0,e.input_tokens_details?.cache_write_tokens??0),t-n);return {input_tokens:t-n-r,output_tokens:Math.max(0,e.output_tokens??
|
|
59
59
|
0),cache_read_input_tokens:n,cache_creation_input_tokens:r}}var je=1.25,fe=2;function Ue(e,t){let n=M(e);if(!n)return null;let r=t.input_tokens??0,o=t.output_tokens??0,s=t.cache_read_input_tokens??0,i=t.
|
|
60
|
-
cache_creation,
|
|
61
|
-
costeUsd:r/1e3*n.inputPer1k+s/1e3*p+(
|
|
62
|
-
let r=he(e,t)?.model;return typeof r=="string"?r:""}function he(e,t){try{let n=e,r={maxOutputLength:Nt};switch((t??"").trim().toLowerCase()){case "gzip":case "x-gzip":n=
|
|
63
|
-
ate":n=
|
|
64
|
-
toString("utf8"))}catch{return null}}var Nt=5*1024*1024;function Fe(){return typeof
|
|
60
|
+
cache_creation,a=t.cache_creation_input_tokens??(i?.ephemeral_5m_input_tokens??0)+(i?.ephemeral_1h_input_tokens??0),u=Math.min(i?.ephemeral_1h_input_tokens??0,a),p=n.cachedInputPer1k??n.inputPer1k;return {
|
|
61
|
+
costeUsd:r/1e3*n.inputPer1k+s/1e3*p+(a-u)/1e3*n.inputPer1k*ge(e)+u/1e3*n.inputPer1k*fe+o/1e3*n.outputPer1k,precio:n,tokens:{entrada:r,salida:o,cacheLeida:s,cacheEscrita:a,cacheEscrita1h:u}}}function Ve(e,t){
|
|
62
|
+
let r=he(e,t)?.model;return typeof r=="string"?r:""}function he(e,t){try{let n=e,r={maxOutputLength:Nt};switch((t??"").trim().toLowerCase()){case "gzip":case "x-gzip":n=A.gunzipSync(e,r);break;case "defl\
|
|
63
|
+
ate":n=A.inflateSync(e,r);break;case "br":n=A.brotliDecompressSync(e,r);break;case "zstd":{let o=A.zstdDecompressSync;if(typeof o!="function")return null;n=o(e,r);break}default:break}return JSON.parse(n.
|
|
64
|
+
toString("utf8"))}catch{return null}}var Nt=5*1024*1024;function Fe(){return typeof A.zstdDecompressSync=="function"}function ge(e){let t=e.toLowerCase();return t.startsWith("gpt-")||t.startsWith("o1")||
|
|
65
65
|
t.startsWith("o3")||t.startsWith("o4")?/^gpt-5\.6/.test(t)?je:1:t.startsWith("gemini")?1:je}function be(e){try{return JSON.parse(typeof e=="string"?e:e.toString("utf8")).usage??null}catch{return null}}
|
|
66
|
-
function qe(e,t,n,r){return Je(e,t,n,false,r)}function Ke(e,t,n,r){return Je(e,t,n,true,r)}function He(e,t,n,r,o){return {requestId:e,model:t,...o&&(o.sessionId||o.agentId)?{attribution:o}:{},calls:{avoidedLlm:0,
|
|
66
|
+
function qe(e,t,n,r,o){return Je(e,t,n,false,r,o)}function Ke(e,t,n,r){return Je(e,t,n,true,r)}function He(e,t,n,r,o){return {requestId:e,model:t,...o&&(o.sessionId||o.agentId)?{attribution:o}:{},calls:{avoidedLlm:0,
|
|
67
67
|
actualLlm:0},tokens:{baselineInput:0,actualInput:0,eliminatedInput:0,compressedInput:0,baselineOutput:0,actualOutput:0,providerCachedInput:0},cache:{result:"miss"},cost:{baselineEstimate:n,actual:r,netSavings:n>
|
|
68
|
-
0?Math.max(-100,Math.min(1,(n-r)/n)):0,basis:"shadow"}}}function Je(e,t,n,r,o){let
|
|
69
|
-
{attribution:o}:{},calls:r?{avoidedLlm:1,actualLlm:0}:{avoidedLlm:0,actualLlm:1},tokens:{baselineInput:
|
|
70
|
-
0:n.tokens.salida,providerCachedInput:r?0:n.tokens.cacheLeida},cache:{result:r?"singleflight":"miss"},cost:r?{baselineEstimate:n.costeUsd,actual:0,netSavings:1,basis:"
|
|
71
|
-
actual:n.costeUsd,netSavings:0,basis:"measured"}}}var zt=1024,q=120,Bt=8,Ut=256*1024,Vt=/error|exception|traceback|warn|fatal|fail|panic|assert|denied|refused|timeout|\bat\s+\S+:\d+/i,Ge=/^\s*(export\s|import\s|function\s|class\s|interface\s|type\s|enum\s|def\s|fn\s|func\s|impl\s|struct\s|trait\s|package\s|module\s|@\w)/;
|
|
68
|
+
0?Math.max(-100,Math.min(1,(n-r)/n)):0,basis:"shadow"}}}function Je(e,t,n,r,o,s){let i=n.tokens.entrada+n.tokens.cacheLeida+n.tokens.cacheEscrita;return {requestId:e,model:t,...o&&(o.sessionId||o.agentId)?
|
|
69
|
+
{attribution:o}:{},calls:r?{avoidedLlm:1,actualLlm:0}:{avoidedLlm:0,actualLlm:1},tokens:{baselineInput:i,actualInput:r?0:i,eliminatedInput:r?0:s?.tokensLimpiados??0,compressedInput:0,baselineOutput:n.
|
|
70
|
+
tokens.salida,actualOutput:r?0:n.tokens.salida,providerCachedInput:r?0:n.tokens.cacheLeida},cache:{result:r?"singleflight":"miss"},cost:r?{baselineEstimate:n.costeUsd,actual:0,netSavings:1,basis:"esti\
|
|
71
|
+
mated"}:{baselineEstimate:n.costeUsd,actual:n.costeUsd,netSavings:0,basis:"measured"}}}var zt=1024,q=120,Bt=8,Ut=256*1024,Vt=/error|exception|traceback|warn|fatal|fail|panic|assert|denied|refused|timeout|\bat\s+\S+:\d+/i,Ge=/^\s*(export\s|import\s|function\s|class\s|interface\s|type\s|enum\s|def\s|fn\s|func\s|impl\s|struct\s|trait\s|package\s|module\s|@\w)/;
|
|
72
72
|
function Ft(e){return Buffer.byteLength(typeof e=="string"?e:JSON.stringify(e??""))}function qt(e){return typeof e=="string"?e:Array.isArray(e)?e.map(t=>t&&typeof t=="object"&&typeof t.text=="string"?
|
|
73
73
|
t.text:"").join(`
|
|
74
74
|
`):""}var Kt=/^\s*\d+[\t→]/;function Ye(e){return e.replace(Kt,"")}function Ht(e){if(!e)return "otro";let t=e.split(`
|
|
75
|
-
`),n=Math.max(1,t.length),r=0,o=0,s=0;for(let i of t){let
|
|
76
|
-
test(
|
|
75
|
+
`),n=Math.max(1,t.length),r=0,o=0,s=0;for(let i of t){let a=Ye(i);(/^[+-](?![+-])/.test(a)||a.startsWith("@@")||a.startsWith("diff --git"))&&(r+=1),Ge.test(a)&&(o+=1),(/^\s*(\d{4}-\d{2}-\d{2}|\[\d|\d{2}:\d{2}:\d{2})/.
|
|
76
|
+
test(a)||/\b(INFO|DEBUG|TRACE|WARN|ERROR)\b/.test(a))&&(s+=1);}return r/n>.25?"diff":s/n>.3?"log":o/n>.08?"codigo":"otro"}function Jt(e,t){if(t==="diff"||t==="otro")return Buffer.byteLength(e);let n=e.
|
|
77
77
|
split(`
|
|
78
78
|
`),r=new Set;for(let s=0;s<n.length;s++){let i=Ye(n[s]);(t==="log"?Vt.test(i):Ge.test(i))&&(r.add(s),t==="log"&&(s>0&&r.add(s-1),s<n.length-1&&r.add(s+1)));}let o=q;for(let s of r)o+=Buffer.byteLength(
|
|
79
79
|
n[s])+1;return Math.min(o,Buffer.byteLength(e))}function Qe(e){let t=[],n=(r,o)=>{let s=Ft(o),i={clave:createHash("sha256").update(typeof o=="string"?o:JSON.stringify(o??"")).digest("hex").slice(0,16),tipo:r,
|
|
80
|
-
bytes:s,bytesV1:s,clase:"otro",esError:false};if(r.endsWith(":tool_result")&&o&&typeof o=="object"){let
|
|
80
|
+
bytes:s,bytesV1:s,clase:"otro",esError:false};if(r.endsWith(":tool_result")&&o&&typeof o=="object"){let a=o;i.esError=a.is_error===true;let u=qt(a.content);i.clase=Ht(u);let p=s-Buffer.byteLength(u);i.bytesV1=
|
|
81
81
|
Math.min(s,Math.max(0,p)+Jt(u,i.clase));}t.push(i);};if((e.system??void 0)!==void 0&&n("system",e.system),Array.isArray(e.tools))for(let r of e.tools)n("tools",r);for(let r of Array.isArray(e.messages)?
|
|
82
82
|
e.messages:[]){if(!r||typeof r!="object"){n("?:invalido",r);continue}let o=r,s=typeof o.role=="string"?o.role:"?";if(typeof o.content=="string")n(`${s}:text`,o.content);else if(Array.isArray(o.content))
|
|
83
83
|
for(let i of o.content)n(`${s}:${i?.type??"?"}`,i);}return t}function Wt(){return {nacimiento:new Map,turno:0,elididosV2m:new Set}}function Gt(e,t){let n=e.turno++;for(let r of t)e.nacimiento.has(r.clave)||
|
|
84
|
-
e.nacimiento.set(r.clave,n);return n}function Xe(e,t,n,r,o=Ut){let s=t.reduce((l,
|
|
84
|
+
e.nacimiento.set(r.clave,n);return n}function Xe(e,t,n,r,o=Ut){let s=t.reduce((l,c,d)=>c.tipo.endsWith(":tool_result")?d:l,-1),i=(l,c)=>l.tipo.endsWith(":tool_result")&&l.bytes>=zt&&c!==s;return t.map((l,c)=>{if(!i(l,c))return {clave:l.clave,bytes:l.bytes};let d=r-(n.nacimiento.get(l.clave)??r);return d>=2&&d*l.bytes/1024>=Bt?{clave:`${l.clave}:e`,bytes:q}:{clave:l.clave,bytes:l.bytes}});
|
|
85
85
|
}function Yt(e){let t=M(e);return t?{lecturaPer1k:t.cachedInputPer1k??t.inputPer1k,escrituraPer1k:t.
|
|
86
86
|
inputPer1k*ge(e),escritura1hPer1k:t.inputPer1k*fe}:null}function We(){return {lecturaUsd:0,escrituraUsd:0,totalUsd:0,tokensLeidos:0,tokensEscritos:0,tokensInvalidados:0,invalidacionUsd:0}}var Qt={"1h":36e5,
|
|
87
87
|
"5m":3e5},K=class{constructor(t){this.transformar=t;}transformar;estado=Wt();previo=[];hayPrevio=false;atPrevio=0;acumulado=We();paso(t){let n=We(),r=Gt(this.estado,t.bloques),o=Yt(t.model),s=this.transformar(
|
|
88
|
-
t.bloques,this.estado,r);if(!o||t.entradaReal<=0)return this.previo=s,this.hayPrevio=true,this.atPrevio=t.at,n;let i=t.bloques.reduce((h,b)=>h+b.bytes,0),
|
|
89
|
-
"5m"],p=this.hayPrevio&&t.at-this.atPrevio>u,m=0;if(!p)for(;m<s.length&&m<this.previo.length&&s[m].clave===this.previo[m].clave&&s[m].bytes===this.previo[m].bytes;)m+=1;let l=this.previo.slice(m),
|
|
90
|
-
d=t.escritura1h?o.escritura1hPer1k:o.escrituraPer1k;for(let h=0;h<s.length;h++){let b=s[h],v=b.bytes*
|
|
91
|
-
v/1e3*d,!p){let f=
|
|
88
|
+
t.bloques,this.estado,r);if(!o||t.entradaReal<=0)return this.previo=s,this.hayPrevio=true,this.atPrevio=t.at,n;let i=t.bloques.reduce((h,b)=>h+b.bytes,0),a=i>0?t.entradaReal/i:0,u=Qt[t.escritura1h?"1h":
|
|
89
|
+
"5m"],p=this.hayPrevio&&t.at-this.atPrevio>u,m=0;if(!p)for(;m<s.length&&m<this.previo.length&&s[m].clave===this.previo[m].clave&&s[m].bytes===this.previo[m].bytes;)m+=1;let l=this.previo.slice(m),c=0,
|
|
90
|
+
d=t.escritura1h?o.escritura1hPer1k:o.escrituraPer1k;for(let h=0;h<s.length;h++){let b=s[h],v=b.bytes*a;if(h<m){n.tokensLeidos+=v,n.lecturaUsd+=v/1e3*o.lecturaPer1k;continue}if(n.tokensEscritos+=v,n.escrituraUsd+=
|
|
91
|
+
v/1e3*d,!p){let f=c;for(;f<l.length&&l[f].clave!==b.clave;)f+=1;f<l.length&&(l[f].bytes===b.bytes&&(n.tokensInvalidados+=v,n.invalidacionUsd+=v/1e3*(d-o.lecturaPer1k)),c=f+1);}}return this.previo=s,this.
|
|
92
92
|
hayPrevio=true,this.atPrevio=t.at,n.totalUsd=n.lecturaUsd+n.escrituraUsd,this.acumulado.lecturaUsd+=n.lecturaUsd,this.acumulado.escrituraUsd+=n.escrituraUsd,this.acumulado.totalUsd+=n.totalUsd,this.acumulado.
|
|
93
93
|
tokensLeidos+=n.tokensLeidos,this.acumulado.tokensEscritos+=n.tokensEscritos,this.acumulado.tokensInvalidados+=n.tokensInvalidados,this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function Ze(e){return e.map(t=>({clave:t.clave,bytes:t.bytes}))}var Zt=64,ne=class{cadenas=new Map;observar(t){let n=t.uso.cache_creation_input_tokens??(t.uso.cache_creation?.ephemeral_5m_input_tokens??0)+(t.uso.cache_creation?.ephemeral_1h_input_tokens??0),r=(t.uso.
|
|
94
94
|
input_tokens??0)+(t.uso.cache_read_input_tokens??0)+n;if(r<=0)return null;let o={bloques:Qe(t.cuerpo),at:t.at,model:t.model,entradaReal:r,escritura1h:(t.uso.cache_creation?.ephemeral_1h_input_tokens??
|
|
95
|
-
0)>0};if(o.bloques.length===0)return null;let s=this.cadenaPara(this.clave(t)),i=s.base.paso(o),
|
|
95
|
+
0)>0};if(o.bloques.length===0)return null;let s=this.cadenaPara(this.clave(t)),i=s.base.paso(o),a=s.v0.paso(o);return i.totalUsd<=0&&a.totalUsd<=0?null:{baselineUsd:i.totalUsd,politicaUsd:a.totalUsd}}clave(t){
|
|
96
96
|
if(t.sessionId)return `s:${t.sessionId}\xB7a:${t.agentId??""}\xB7${t.model}`;let n=Array.isArray(t.cuerpo.messages)?t.cuerpo.messages[0]:void 0;return `m:${createHash("sha256").update(JSON.stringify(n??null)).digest(
|
|
97
97
|
"hex").slice(0,16)}\xB7${t.model}`}cadenaPara(t){let n=this.cadenas.get(t);if(!n&&(n={base:new K(r=>Ze(r)),v0:new K((r,o,s)=>Xe("v0",r,o,s)),ultimoUso:0},this.cadenas.set(t,n),this.cadenas.size>Zt)){let r=null,
|
|
98
98
|
o=1/0;for(let[s,i]of this.cadenas)i.ultimoUso<o&&(o=i.ultimoUso,r=s);r!==null&&this.cadenas.delete(r);}return n.ultimoUso=Date.now(),n}};var oe=class{url;clave;ttlMs;fetchImpl;log;features=new Set;validoHasta=0;enVuelo=null;avisado=false;constructor(t){this.url=t.url,this.clave=t.serviceAccountKey,this.ttlMs=t.ttlMs??3e5,this.fetchImpl=t.
|
|
@@ -107,46 +107,46 @@ n.messages)?null:(n.context_management=et(),Buffer.from(JSON.stringify(n),"utf8"
|
|
|
107
107
|
`).update(t).update(`
|
|
108
108
|
`).update(r).update(`
|
|
109
109
|
`).update(n).digest("hex")}function rt(e){return tn.map(t=>`${t}=${e(t)??""}`).join(`
|
|
110
|
-
`)}var se=class{enVuelo=new Map;primarias=0;gemelas=0;registrar(t){if(this.enVuelo.has(t))return null;this.primarias+=1;let n,r=new Promise(
|
|
111
|
-
s=0,i=false;return {capturar:
|
|
110
|
+
`)}var se=class{enVuelo=new Map;primarias=0;gemelas=0;registrar(t){if(this.enVuelo.has(t))return null;this.primarias+=1;let n,r=new Promise(a=>n=a);this.enVuelo.set(t,{promesa:r,resolver:n});let o=[],
|
|
111
|
+
s=0,i=false;return {capturar:a=>{if(!i){if(s+=a.length,s>ve){i=true,o.length=0;return}o.push(a);}},terminar:(a,u)=>{let p=!i&&a>=200&&a<300;this.enVuelo.get(t)?.resolver(p?{status:a,headers:u,chunks:o}:null),
|
|
112
112
|
this.enVuelo.delete(t);},abortar:()=>{this.enVuelo.get(t)?.resolver(null),this.enVuelo.delete(t);}}}async esperar(t){let n=this.enVuelo.get(t);if(!n)return null;let r=await n.promesa;return r&&(this.gemelas+=
|
|
113
|
-
1),r}tieneEnVuelo(t){return this.enVuelo.has(t)}};var rn=["content-encoding","content-length","transfer-encoding"];async function st(e={}){let t=(e.upstream??"https://api.anthropic.com").replace(/\/+$/,""),n=e.fetchImpl??fetch,r=e.log??(
|
|
114
|
-
|
|
113
|
+
1),r}tieneEnVuelo(t){return this.enVuelo.has(t)}};var rn=["content-encoding","content-length","transfer-encoding"];async function st(e={}){let t=(e.upstream??"https://api.anthropic.com").replace(/\/+$/,""),n=e.fetchImpl??fetch,r=e.log??(c=>console.log(
|
|
114
|
+
c)),o;if(e.serviceAccountKey){o=new z({url:e.meteringUrl??"https://savings.bivelio.com/api/metering/usage",serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},onAuthError:d=>E(
|
|
115
115
|
"gateway-ingest-auth",`[bvsala gateway] la ingesta de uso rechaza la credencial (${d}). El tr\xE1fico sigue fluyendo (avisar, nunca romper), pero este uso no est\xE1 llegando al panel. Revisa BIVELIO_SERVIC\
|
|
116
|
-
E_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let
|
|
116
|
+
E_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let c=Z();e.seatId?o.setSeat(e.seatId,c):ee(e.serviceAccountKey).then(d=>o?.setSeat(d,c)).catch(()=>{}),o.start();}else E("gateway-sin\
|
|
117
117
|
-clave","[bvsala gateway] sin BIVELIO_SERVICE_KEY: el gateway reenv\xEDa el tr\xE1fico pero NO mide. Consigue tu clave en savings.bivelio.com/dashboard/install para ver el gasto en tu panel.");let s=e.
|
|
118
|
-
coalescer?new se:null,i=e.sombra&&o?new ne:null,
|
|
119
|
-
serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},log:r}):null,u=
|
|
118
|
+
coalescer?new se:null,i=e.sombra&&o?new ne:null,a=e.elision&&e.serviceAccountKey?new oe({url:new URL("/api/org/entitlements",e.meteringUrl??"https://savings.bivelio.com/api/metering/usage").toString(),
|
|
119
|
+
serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},log:r}):null,u=c=>c==="/v1/messages"?new $:c.endsWith("/responses")?new te:null,p=(c,d,h,b,v,f,y,R)=>{if(!o||!h)return;let W=o,
|
|
120
120
|
V=h,S=Ve(d,f);if(!S){E(`gateway-sin-modelo:${v}`,`[bvsala gateway] no se pudo leer el modelo del cuerpo de ${v} (content-encoding: ${f??"ninguno"}); su uso se reenv\xEDa pero no se mide.`);return}let T=Ue(
|
|
121
|
-
S,h);T?(o.record(b?Ke(
|
|
122
|
-
tokens.cacheEscrita1h?` (1h ${T.tokens.cacheEscrita1h})`:""} cache\u2193${T.tokens.cacheLeida}, out ${T.tokens.salida})`+(
|
|
123
|
-
|
|
124
|
-
{sessionId:y.sessionId}:{},...y?.agentId!==void 0?{agentId:y.agentId}:{}});if(!
|
|
125
|
-
toFixed(6)} \u2192 v0 $${
|
|
126
|
-
m=createServer(async(
|
|
127
|
-
isArray(V)?V[0]:V,T=
|
|
128
|
-
G=L!==void 0||
|
|
129
|
-
|
|
130
|
-
d.writeHead(g.status,g.headers);let x=u(f.pathname)??new $;for(let Me of g.chunks)d.write(Me),x.observar(Me);d.end();let Et=x.usage()??(f.pathname==="/v1/messages"?be(Buffer.concat(g.
|
|
131
|
-
h,w,Et,!0,f.pathname,S,G);return}}else v=s.registrar(le);let Q={};for(let[g,x]of Object.entries(
|
|
132
|
-
if(
|
|
133
|
-
method,headers:Q,body:["GET","HEAD"].includes(
|
|
134
|
-
JSON.stringify({error:"bvsala gateway: upstream unreachable",detail:String(g)}))),r(`[gateway] ${
|
|
135
|
-
headers.entries());for(let g of rn)delete ue[g];d.writeHead(C.status,ue);let De=C.headers.get("content-type")??"",de=De.includes("text/event-stream")||De===""&&C.ok&&u(f.pathname)!==null;
|
|
136
|
-
null;let F=!de&&C.ok&&o!==void 0&&
|
|
137
|
-
from(g);d.write(x),y?.observar(x),F&&(Le+=x.length,Le>ve?F=null:F.push(x)),v?.capturar(x);}if(d.end(),v?.terminar(C.status,ue),y&&C.ok){W=!0;let g=y instanceof $?y.elision():null;p(h,
|
|
138
|
-
S,G,g);}else if(F){let g=Buffer.concat(F);p(h,w,be(g),!1,f.pathname,S,G,Be(g));}else de||r(`[gateway] ${
|
|
139
|
-
y?y.usageFinal():null;if(w){r(`[gateway] ${
|
|
140
|
-
r(`[gateway] ${
|
|
141
|
-
502,{"content-type":"application/json"}),d.end(JSON.stringify({error:"bvsala gateway: stream interrupted",detail:String(
|
|
142
|
-
|
|
143
|
-
|
|
121
|
+
S,h);T?(o.record(b?Ke(c,S,T,y):qe(c,S,T,y,R)),r(`[gateway] POST ${v} ${b?"\xB7 COALESCIDA (llamada evitada)":""} \xB7 ${S} \xB7 $${T.costeUsd.toFixed(6)} (in ${T.tokens.entrada}, cache\u2191${T.tokens.
|
|
122
|
+
cacheEscrita}${T.tokens.cacheEscrita1h?` (1h ${T.tokens.cacheEscrita1h})`:""} cache\u2193${T.tokens.cacheLeida}, out ${T.tokens.salida})`+(R?` \xB7 elisi\xF3n: ${R.borrados} borrado(s), ${R.tokensLimpiados}\
|
|
123
|
+
tok limpiados por el proveedor`:"")),i&&!b&&v==="/v1/messages"&&setImmediate(()=>{try{let L=he(d,f);if(!L||typeof L!="object")return;let _=i.observar({cuerpo:L,uso:V,model:S,at:Date.now(),...y?.sessionId!==
|
|
124
|
+
void 0?{sessionId:y.sessionId}:{},...y?.agentId!==void 0?{agentId:y.agentId}:{}});if(!_)return;W.record(He(`${c}:shadow`,S,_.baselineUsd,_.politicaUsd,y)),r(`[gateway] sombra \xB7 ${S} \xB7 baseline $${_.
|
|
125
|
+
baselineUsd.toFixed(6)} \u2192 v0 $${_.politicaUsd.toFixed(6)}`);}catch{}})):E(`gateway-sin-precio:${S}`,`[bvsala gateway] el modelo "${S}" no est\xE1 en el cat\xE1logo de precios; su uso se reenv\xEDa pero no \
|
|
126
|
+
se mide.`);},m=createServer(async(c,d)=>{let h=randomUUID(),b=new AbortController;d.on("close",()=>{d.writableEnded||b.abort();});let v=null,f=new URL(c.url??"/",t),y=null,R=Buffer.alloc(0),W=false,V=c.headers["content-enco\
|
|
127
|
+
ding"],S=Array.isArray(V)?V[0]:V,T=I=>{let w=Array.isArray(I)?I[0]:I;return w!==void 0&&/^[A-Za-z0-9._:/-]{1,128}$/.test(w)?w:void 0},L=T(c.headers["x-claude-code-session-id"]),_=T(c.headers["x-claude\
|
|
128
|
+
-code-agent-id"]),G=L!==void 0||_!==void 0?{...L!==void 0?{sessionId:L}:{},..._!==void 0?{agentId:_}:{}}:void 0;try{let I=[];for await(let g of c)I.push(g);let w=Buffer.concat(I);R=w,f=new URL(c.url??
|
|
129
|
+
"/",t);let Y=s!==null&&c.method==="POST"&&w.length>0,Ct=rt(g=>{let x=c.headers[g];return Array.isArray(x)?x.join(", "):x}),le=Y?ot("POST",f.pathname+f.search,w,Ct):"";if(Y)if(s.tieneEnVuelo(le)){let g=await s.
|
|
130
|
+
esperar(le);if(g){d.writeHead(g.status,g.headers);let x=u(f.pathname)??new $;for(let Me of g.chunks)d.write(Me),x.observar(Me);d.end();let Et=x.usage()??(f.pathname==="/v1/messages"?be(Buffer.concat(g.
|
|
131
|
+
chunks)):null);p(h,w,Et,!0,f.pathname,S,G);return}}else v=s.registrar(le);let Q={};for(let[g,x]of Object.entries(c.headers))g==="host"||g==="content-length"||x===void 0||(Q[g]=Array.isArray(x)?x.join(
|
|
132
|
+
", "):x);let Oe=w;if(a!==null&&c.method==="POST"&&f.pathname==="/v1/messages"&&a.tiene("context_elision"))try{let g=tt(w,S);g!==null&&(Oe=g,Q["anthropic-beta"]=nt(Q["anthropic-beta"]));}catch{}let C;try{
|
|
133
|
+
C=await n(f,{method:c.method,headers:Q,body:["GET","HEAD"].includes(c.method??"")?void 0:Oe,redirect:"manual",signal:b.signal});}catch(g){v?.abortar(),d.headersSent||(d.writeHead(502,{"content-type":"a\
|
|
134
|
+
pplication/json"}),d.end(JSON.stringify({error:"bvsala gateway: upstream unreachable",detail:String(g)}))),r(`[gateway] ${c.method} ${f.pathname} \u2192 upstream inalcanzable: ${String(g)}`);return}let ue=Object.
|
|
135
|
+
fromEntries(C.headers.entries());for(let g of rn)delete ue[g];d.writeHead(C.status,ue);let De=C.headers.get("content-type")??"",de=De.includes("text/event-stream")||De===""&&C.ok&&u(f.pathname)!==null;
|
|
136
|
+
y=de?u(f.pathname):null;let F=!de&&C.ok&&o!==void 0&&c.method==="POST"&&f.pathname==="/v1/messages"&&(C.headers.get("content-type")??"").includes("application/json")?[]:null,Le=0;if(C.body)for await(let g of C.
|
|
137
|
+
body){let x=Buffer.from(g);d.write(x),y?.observar(x),F&&(Le+=x.length,Le>ve?F=null:F.push(x)),v?.capturar(x);}if(d.end(),v?.terminar(C.status,ue),y&&C.ok){W=!0;let g=y instanceof $?y.elision():null;p(h,
|
|
138
|
+
w,y.usage(),!1,f.pathname,S,G,g);}else if(F){let g=Buffer.concat(F);p(h,w,be(g),!1,f.pathname,S,G,Be(g));}else de||r(`[gateway] ${c.method} ${f.pathname} \u2192 ${C.status}`);}catch(I){if(v?.abortar(),b.
|
|
139
|
+
signal.aborted){let w=!W&&y?y.usageFinal():null;if(w){r(`[gateway] ${c.method} ${f.pathname} \u2192 el cliente cerr\xF3 tras el usage final; se mide igual`);let Y=y instanceof $?y.elision():null;p(h,R,
|
|
140
|
+
w,false,f.pathname,S,G,Y);}else r(`[gateway] ${c.method} ${f.pathname} \u2192 el cliente abort\xF3; upstream cancelado`);}else if(r(`[gateway] ${c.method} ${f.pathname} \u2192 error sirviendo: ${String(I)}`),
|
|
141
|
+
!d.headersSent){d.writeHead(502,{"content-type":"application/json"}),d.end(JSON.stringify({error:"bvsala gateway: stream interrupted",detail:String(I)}));return}d.writableEnded||d.end();}});return m.on(
|
|
142
|
+
"upgrade",(c,d)=>{r(`[gateway] ${c.method} ${new URL(c.url??"/","http://x").pathname} \u2192 426 (WebSocket no soportado; el cliente cae a HTTP)`),d.once("error",()=>{}),d.once("finish",()=>d.destroy()),
|
|
143
|
+
d.end(`HTTP/1.1 426 Upgrade Required\r
|
|
144
144
|
connection: close\r
|
|
145
145
|
content-length: 0\r
|
|
146
146
|
\r
|
|
147
|
-
`);}),await new Promise((
|
|
148
|
-
existe??existsSync,o=null;for(let s of n.split(";").filter(i=>i.length>0)){for(let i of [".exe",".com"]){let
|
|
149
|
-
i);if(r(
|
|
147
|
+
`);}),await new Promise((c,d)=>{m.once("error",d),m.listen(e.puerto??8402,"127.0.0.1",()=>c());}),{puerto:m.address().port,cerrar:async()=>{await o?.stopAndDrain(),await new Promise(c=>m.close(()=>c()));}}}var ye=["claude","codex","goose","qwen"];function at(e){return ye.includes(e??"")}function ct(e,t={}){let n=t.path??process.env.PATH??"",r=t.
|
|
148
|
+
existe??existsSync,o=null;for(let s of n.split(";").filter(i=>i.length>0)){for(let i of [".exe",".com"]){let a=join(s,e+i);if(r(a))return {tipo:"exe",ruta:a}}if(o===null)for(let i of [".cmd",".bat"]){let a=join(s,e+
|
|
149
|
+
i);if(r(a)){o=a;break}}}return o!==null?{tipo:"solo-shim",ruta:o}:{tipo:"no-encontrado"}}function lt(e={}){let n=(e.env??process.env).BVSALA_CODEX_AUTH?.toLowerCase();if(n==="api-key"||n==="apikey")return "\
|
|
150
150
|
api-key";if(n==="chatgpt")return "chatgpt";let r=null;try{r=e.leerAuth?e.leerAuth():null;}catch{r=null;}if(r===null)return "api-key";try{let o=JSON.parse(r);return typeof o.auth_mode=="string"?o.auth_mode.
|
|
151
151
|
toLowerCase().replace(/[^a-z]/g,"")==="apikey"?"api-key":"chatgpt":o.tokens!==void 0&&o.tokens!==null?"chatgpt":"api-key"}catch{return "api-key"}}var an={"api-key":{upstream:"https://api.openai.com",prefijo:"\
|
|
152
152
|
/v1"},chatgpt:{upstream:"https://chatgpt.com",prefijo:"/backend-api/codex"}};function ke(e,t,n,r={}){let o=`http://127.0.0.1:${t}`;switch(e){case "claude":return {bin:"claude",args:n,env:{ANTHROPIC_BASE_URL:o}};case "\
|
|
@@ -173,24 +173,24 @@ idar en mano contra el log del gateway].`,"{",' "customModels": ['," {",'
|
|
|
173
173
|
receta:({baseV1:e})=>["mecanismo: UI \u2192 proveedor custom, Provider API \xABAnthropic Messages\xBB. Probar CON /v1 primero (linaje Cline) [inferido: validar en mano].",`Base URL: ${e}`]}];function mn(e,t){
|
|
174
174
|
let n=e.split(delimiter).filter(o=>o.length>0),r=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return o=>n.some(s=>r.some(i=>t(join(s,o+i))))}async function ut(e,t={}){if(!Number.isInteger(e)||e<1||
|
|
175
175
|
e>65535)throw new RangeError(`[bvsala doctor] puerto inv\xE1lido: ${String(e)}`);let n=t.home??homedir(),r=t.existe??existsSync,o=t.enPath??mn(t.path??process.env.PATH??"",r),s=`http://127.0.0.1:${e}`,i=`${s}/v1`,
|
|
176
|
-
|
|
177
|
-
se lee el contenido de ning\xFAn archivo.",""];for(let p of pn){let m=p.configs.map(b=>join(n,b)),l=p.binario!==void 0&&o(p.binario),
|
|
178
|
-
d?h=`detectado \u2014 ${[...l?[`binario \`${p.binario}\` en PATH`]:[],...
|
|
176
|
+
a=[],u=[`bvsala doctor \u2014 gateway local en ${s}`,"Solo imprime: no escribe ninguna configuraci\xF3n. Detecci\xF3n por existencia (binarios en PATH y","archivos de configuraci\xF3n de usuario); nunca \
|
|
177
|
+
se lee el contenido de ning\xFAn archivo.",""];for(let p of pn){let m=p.configs.map(b=>join(n,b)),l=p.binario!==void 0&&o(p.binario),c=m.filter(b=>r(b)),d=l||c.length>0;d&&a.push(p.id);let h;p.detectable?
|
|
178
|
+
d?h=`detectado \u2014 ${[...l?[`binario \`${p.binario}\` en PATH`]:[],...c.map(v=>`config presente: ${v}`)].join("; ")}`:h="no detectado":h="sin detecci\xF3n autom\xE1tica (extensi\xF3n de editor)",u.
|
|
179
179
|
push(`\xBB ${p.id}: ${h}`),u.push(` ${p.nombre}`);for(let b of p.receta({base:s,baseV1:i,rutas:m}))u.push(` ${b}`);u.push(` ${dn}`),u.push("");}return u.push("Regla BYOK: las recetas del anillo Anth\
|
|
180
180
|
ropic (Goose, Qwen Code, opencode, Crush, Droid, Cline, Kilo) son","para API key. Nunca enrutes por el gateway el OAuth de una suscripci\xF3n Claude Pro/Max desde un harness","de terceros \u2014 Anthropic \
|
|
181
181
|
lo proh\xEDbe. Claude Code y Codex con suscripci\xF3n se enrutan y se miden, pero no","se monetizan: no hay factura por tokens.","Detalle por terminal: docs/terminales/<terminal>.md"),{texto:u.join(`
|
|
182
|
-
`),detectados:
|
|
182
|
+
`),detectados:a}}var dt="savings-mode";function pt(e,t){for(let n of e){let r=join(n,"skills",dt,"SKILL.md");if(t.existe(r))return r}return null}var mt="<!-- bvsala:savings-mode:inicio -->",ie="\
|
|
183
183
|
<!-- bvsala:savings-mode:fin -->";function fn(e){let t=e.replace(/^---\n[\s\S]*?\n---\n*/,"").trim();return `${mt}
|
|
184
184
|
${t}
|
|
185
185
|
|
|
186
186
|
_Always on (AGENTS.md has no activation step). Delete this block to turn it off; \`bvsala skill --codex --forzar\` restores it._
|
|
187
187
|
${ie}`}function ft(e){let t=pt(e.origenes,e.fs);if(!t)return {ok:false,destino:"",mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${e.origenes.join(", ")})`};let n=fn(e.fs.
|
|
188
188
|
leer(t)),r=e.proyecto?e.cwd:join(e.home,".codex"),o=join(r,"AGENTS.md");if(!e.fs.existe(o))return e.fs.crearDir(r),e.fs.escribir(o,n+`
|
|
189
|
-
`),{ok:true,destino:o,mensaje:xe(o,"instalado")};let s=e.fs.leer(o),i=s.indexOf(mt),
|
|
189
|
+
`),{ok:true,destino:o,mensaje:xe(o,"instalado")};let s=e.fs.leer(o),i=s.indexOf(mt),a=s.indexOf(ie);return i===-1||a===-1||a<i?(e.fs.escribir(o,s.trimEnd()+`
|
|
190
190
|
|
|
191
191
|
`+n+`
|
|
192
|
-
`),{ok:true,destino:o,mensaje:xe(o,"a\xF1adido al AGENTS.md existente")}):s.slice(i,
|
|
193
|
-
slice(0,i)+n+s.slice(
|
|
192
|
+
`),{ok:true,destino:o,mensaje:xe(o,"a\xF1adido al AGENTS.md existente")}):s.slice(i,a+ie.length)===n?{ok:true,destino:o,mensaje:`[bvsala skill] ya instalado y al d\xEDa: ${o}`}:e.forzar?(e.fs.escribir(o,s.
|
|
193
|
+
slice(0,i)+n+s.slice(a+ie.length)),{ok:true,destino:o,mensaje:xe(o,"bloque actualizado")}):{ok:false,destino:o,mensaje:`[bvsala skill] el bloque savings-mode de ${o} tiene contenido DISTINTO \u2014 no lo piso; \
|
|
194
194
|
usa --forzar para actualizarlo`}}function xe(e,t){return `[bvsala skill] ${t}: ${e}
|
|
195
195
|
[bvsala skill] AGENTS.md va SIEMPRE activo en Codex (no hay paso de activaci\xF3n); borra el bloque para apagarlo.
|
|
196
196
|
[bvsala skill] para medir su efecto: trabaja unos d\xEDas con \xE9l y otros sin \xE9l bajo \`bvsala codex\`, y compara en el panel.`}function ht(e){let t=pt(e.origenes,e.fs);if(!t)return {ok:false,destino:"",
|
|
@@ -203,7 +203,7 @@ match(/\n/g)??[]).length;r+=i+Math.floor(Math.max(0,o.length-1)/2);}else /[A-Za-
|
|
|
203
203
|
Math.ceil(t.length/4))}},we=new Se;var Te=class{estimators=new Map;modelToTokenizer=new Map;fallbackId;constructor(t=we){this.fallbackId=t.id,this.estimators.set(t.id,t);}register(t){return this.estimators.set(t.id,t),this}mapModel(t,n){
|
|
204
204
|
return this.modelToTokenizer.set(t,n),this}resolve(t){let n=t.tokenizer?this.estimators.get(t.tokenizer):void 0;if(n)return n;if(t.model){let r=this.modelToTokenizer.get(t.model);if(r){let o=this.estimators.
|
|
205
205
|
get(r);if(o)return o}}return this.estimators.get(this.fallbackId)}count(t,n){return this.resolve(n).count(t)}};new Te;new TextEncoder;new TextDecoder;new TextDecoder;var An={"gpt-4o-mini":{deltaTokens:-16,salidaDelBrazoA:72,contrato:"triage (6 fields, long enums)",pares:8},"gpt-4o":{deltaTokens:3,salidaDelBrazoA:75,contrato:"triage (6 fields, long enums)",pares:8}};
|
|
206
|
-
me(An);var _e="0.4.
|
|
206
|
+
me(An);var _e="0.4.13";var[,,k,...O]=process.argv;function Nn(){console.log(`bvsala ${_e} \u2014 BiVelio Savings Layer
|
|
207
207
|
|
|
208
208
|
Comandos:
|
|
209
209
|
gateway [--puerto N] Proxy local medidor (por defecto 8402) para terminales que
|
|
@@ -244,18 +244,18 @@ Entorno:
|
|
|
244
244
|
|
|
245
245
|
El gateway nunca corta el tr\xE1fico: sin clave o con la ingesta ca\xEDda, reenv\xEDa y avisa.
|
|
246
246
|
Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}var J=at(k);k!=="gateway"&&k!=="doctor"&&k!=="skill"&&!J&&(Nn(),process.exit(k===void 0||k==="hel\
|
|
247
|
-
p"||k==="--help"?0:1));if(k==="skill"){let e=dirname(fileURLToPath(import.meta.url)),t={origenes:[join(e,"..",".."),join(e,"..")],home:homedir(),cwd:process.cwd(),proyecto:
|
|
248
|
-
fs:{existe:existsSync,leer:r=>readFileSync(r,"utf8"),escribir:(r,o)=>writeFileSync(r,o),crearDir:r=>mkdirSync(r,{recursive:true})}},n=
|
|
249
|
-
to"),U=J?0:Ae>=0?Number(
|
|
250
|
-
"--write")&&(console.error("[bvsala doctor] --write todav\xEDa no existe: el doctor solo imprime; copia el bloque a mano."),process.exit(1));let e=await ut(U);console.log(e.texto),process.exit(0);}var
|
|
251
|
-
ke(k,0,
|
|
247
|
+
p"||k==="--help"?0:1));if(k==="skill"){let e=dirname(fileURLToPath(import.meta.url)),t={origenes:[join(e,"..",".."),join(e,"..")],home:homedir(),cwd:process.cwd(),proyecto:O.includes("--proyecto"),forzar:O.includes("--forzar"),
|
|
248
|
+
fs:{existe:existsSync,leer:r=>readFileSync(r,"utf8"),escribir:(r,o)=>writeFileSync(r,o),crearDir:r=>mkdirSync(r,{recursive:true})}},n=O.includes("--codex")?ft(t):ht(t);console.log(n.mensaje),process.exit(n.ok?0:1);}var Ae=O.indexOf("--puer\
|
|
249
|
+
to"),U=J?0:Ae>=0?Number(O[Ae+1]):8402;(!Number.isInteger(U)||(k==="doctor"?U<1:U<0)||U>65535)&&(console.error(`[bvsala ${k}] puerto inv\xE1lido: ${O[Ae+1]}`),process.exit(1));if(k==="doctor"){O.includes(
|
|
250
|
+
"--write")&&(console.error("[bvsala doctor] --write todav\xEDa no existe: el doctor solo imprime; copia el bloque a mano."),process.exit(1));let e=await ut(U);console.log(e.texto),process.exit(0);}var D=J?
|
|
251
|
+
ke(k,0,O,{modoCodex:k==="codex"?lt({leerAuth:()=>readFileSync(join(homedir(),".codex","auth.json"),"utf8")}):void 0}):null,Pe=process.env.BIVELIO_SERVICE_KEY,jn=J&&process.env.BVSALA_GATEWAY_LOG!=="1",j=await st({puerto:U,
|
|
252
252
|
...jn?{log:()=>{}}:{},...Pe?{serviceAccountKey:Pe}:{},...process.env.BVSALA_SEAT_ID?{seatId:process.env.BVSALA_SEAT_ID}:{},...process.env.BVSALA_GATEWAY_UPSTREAM?{upstream:process.env.BVSALA_GATEWAY_UPSTREAM}:
|
|
253
|
-
|
|
254
|
-
{elision:true}:{},...process.env.BVSALA_METERING_URL?{meteringUrl:process.env.BVSALA_METERING_URL}:{}}),zn=process.env.BVSALA_GATEWAY_UPSTREAM??
|
|
253
|
+
D?.upstream?{upstream:D.upstream}:{},...process.env.BVSALA_GATEWAY_COALESCE==="1"?{coalescer:true}:{},...process.env.BVSALA_GATEWAY_SHADOW==="1"?{sombra:true}:{},...process.env.BVSALA_GATEWAY_ELISION==="1"?
|
|
254
|
+
{elision:true}:{},...process.env.BVSALA_METERING_URL?{meteringUrl:process.env.BVSALA_METERING_URL}:{}}),zn=process.env.BVSALA_GATEWAY_UPSTREAM??D?.upstream??"https://api.anthropic.com";console.log(`[bvs\
|
|
255
255
|
ala gateway] v${_e} escuchando en http://127.0.0.1:${j.puerto} \u2192 ${zn}`);console.log(`[bvsala gateway] medici\xF3n: ${Pe?"ACTIVA (clave de servicio presente)":"APAGADA (falta BIVELIO_SERVICE_KEY)"}`);
|
|
256
|
-
process.env.BVSALA_GATEWAY_UPSTREAM&&
|
|
257
|
-
isa el upstream de este terminal (${
|
|
258
|
-
std y Codex manda el cuerpo en zstd: el tr\xE1fico pasa pero NO se mide. Usa Node \u2265 22.15.`);if(
|
|
256
|
+
process.env.BVSALA_GATEWAY_UPSTREAM&&D?.upstream&&process.env.BVSALA_GATEWAY_UPSTREAM!==D.upstream&&console.error(`[bvsala ${k}] AVISO: BVSALA_GATEWAY_UPSTREAM=${process.env.BVSALA_GATEWAY_UPSTREAM} p\
|
|
257
|
+
isa el upstream de este terminal (${D.upstream}). Si no es lo que quieres, quita la variable.`);k==="codex"&&!Fe()&&console.error(`[bvsala codex] AVISO: este Node (${process.version}) no descomprime z\
|
|
258
|
+
std y Codex manda el cuerpo en zstd: el tr\xE1fico pasa pero NO se mide. Usa Node \u2265 22.15.`);if(D&&J){let e=ke(k,j.puerto,O,{...D.upstream?{modoCodex:D.upstream.includes("chatgpt.com")?"chatgpt":
|
|
259
259
|
"api-key"}:{}});e.nota&&console.log(`[bvsala ${k}] ${e.nota}`);let t=e.bin;if(process.platform==="win32"){let r=ct(e.bin);r.tipo==="exe"?t=r.ruta:r.tipo==="solo-shim"&&(console.error(`[bvsala ${k}] \`${e.
|
|
260
260
|
bin}\` est\xE1 instalado como shim de npm (${r.ruta}) y Windows no puede lanzarlo de forma segura con argumentos (CVE-2024-27980). Inst\xE1lalo con su instalador nativo (deja un ${e.bin}.exe en el PAT\
|
|
261
261
|
H) o usa la receta manual de docs/terminales/.`),await j.cerrar(),process.exit(127));}let n=spawn(t,e.args,{stdio:"inherit",env:{...process.env,...e.env}});n.on("error",r=>{console.error(`[bvsala ${k}] no\
|
package/dist/index.d.ts
CHANGED
|
@@ -3262,6 +3262,6 @@ declare function createSavingsLayer(config: Omit<SavingsLayerConfig, "tokenizer"
|
|
|
3262
3262
|
* constant to package.json so the two can never drift.
|
|
3263
3263
|
*/
|
|
3264
3264
|
|
|
3265
|
-
declare const BV_SALA_VERSION = "0.4.
|
|
3265
|
+
declare const BV_SALA_VERSION = "0.4.13";
|
|
3266
3266
|
|
|
3267
3267
|
export { type AnthropicOptions, AnthropicProvider, BV_SALA_VERSION, type BivelioHandoff, CATALOGO, COMPACT_ROWS_INSTRUCTION, type CacheOutcome, type CacheTier, type CachedAnswer, type CanonicalRequest, type ChatMessage, type CompactRowsDecodeOptions, type CompactRowsOptions, type CompactVerification, type CompressionEconomics, type CompressionPolicyInput, type CompressionRequest, type CompressionResult, type Compressor, type ConstraintBackend, type ConstraintBackendId, type ConstraintPlan, type ConversationState, type CostBasis, type CostModel, DEFAULT_COST_MODEL, DEFAULT_MAX_STALENESS_SECONDS, type DeferredExecutionReport, type DeterministicResolver, EMBEDDED_PUBLIC_KEY, type EmbeddingFn, type EvidenceDoc, type ExactCache, ExactTokenizer, type ExecutionClass, ExecutionRouter, type FormatChoice, FormatSelector, type FormatSelectorOptions, type HandoffFact, HeuristicEstimator, InMemoryExactCache, InMemorySemanticCache, type JsonSchema, LicenseError, type LicenseGate, type LicenseKeyset, type LicenseStatus, type LicenseTokenPayload, type LocalClassifier, MODELOS_POR_CODIFICACION, MODELS_BY_ENCODING, type MemoryDelta, type MessageRole, MockProvider, type MockProviderOptions, type ModelCascadeMode, type ModelCascadeReport, type ModelCascadeSettings, type OpenAICompatibleOptions, OpenAICompatibleProvider, type OutputContract, PRECIOS_AL_DIA, type Policy, type ProtectedSpan, type Provider, type ProviderRequest, type ProviderResponse, type ProviderUsage, QUALITY_STATUSES, type QualityStatus, type RequestContext, type Reranker, type ResolvedDeps, type ResolvedGate, type ResolvedLicense, ResolverRegistry, type ResolverResult, type RetrievalOptions, type RetrievalOutcome, type RetrievalPlan, type Retriever, type RevocationListBody, type RevocationListVerification, type RevocationPollEvent, RevocationPoller, type RevocationPollerOptions, RevocationSnapshot, type RouteDecision, type SavingsLayer, type SavingsLayerConfig, SavingsLedger, type SavingsReport, type SavingsRequest, type SavingsResult, type SavingsToggles, SchemaRegistry, type SemanticCacheOptions, type SemanticHit, type SemanticRecord, type SemanticVerifier, type SerializationFormat, type Serializer, Singleflight, type TokenEstimator, TokenizerRegistry, type ToolCallRequest, type ToolDescriptor, type ToolRisk, type ToolSelection, ToolSelector, type ToolSelectorOptions, TraceCollector, type TraceEvent, UMBRAL_LOCAL, UsageEmitter, type UsageEmitterOptions, type ValidationError, type ValidationResult, adaptiveK, arithmeticResolver, buildExactKey, buildInflightKey, canonicalize, compactRowsSerializer, compresionFiel, computeNextDelay, cosine, createCompactRowsSerializer, createDefaultResolvers, createHandoff, createMockProvider, createSavingsLayer, csvSerializer, decodeCompactRows, dedupe, defaultTokenizerRegistry, deriveSeatId, deriveStatus, detectCi, embebedorLocal, emptyState, encodeCompactRows, evalArithmetic, evaluatePolicy, executeRetrievalPlan, gateFromKey, heuristicEstimator, isKeyset, isStrictCompatible, jsonCompactSerializer, keyTokensMatch, liveGateFromKey, mergeDelta, modelFamilyOf, multisetEqual, negationCount, noopCompressor, normalizeText, numericTokens, precioDeLista, projectContext, providerNativeBackend, randomId, registerExactTokenizer, registrarTokenizadorExacto, renderState, resolveConstraintBackend, resolveDependencies, resolveLicense, sha256, shouldCompress, stableStringify, uniformColumns, validateAgainstSchema, vectorLocal, verifyCompactSignature, verifyLicenseToken, verifyRevocationList, withProtectedSpans, words };
|
package/dist/index.js
CHANGED
|
@@ -782,7 +782,7 @@ ng/usage`:void 0);if(a){i=new dt({url:a,serviceAccountKey:t.serviceAccountKey,..
|
|
|
782
782
|
{},...t.metering?.maxBatch!=null?{maxBatch:t.metering.maxBatch}:{},...t.metering?.maxBuffer!=null?{maxBuffer:t.metering.maxBuffer}:{},...t.meteringFetch?{fetchImpl:t.meteringFetch}:t.licenseFetch?{fetchImpl:t.
|
|
783
783
|
licenseFetch}:{},...t.now?{now:t.now}:{},...t.metering?.ci!=null?{ci:t.metering.ci}:{},...t.silenceWarnings!=null?{silenceWarnings:t.silenceWarnings}:{}});let c=t.metering?.ci??cr();if(t.metering?.seatId)
|
|
784
784
|
i.setSeat(t.metering.seatId,c);else {let l=i;lr(t.serviceAccountKey).then(u=>l.setSeat(u,c)).catch(()=>{});}i.start();}}return {generate:async a=>{let c=await s.generate(a);if(i)try{i.record(c.report);}catch{}
|
|
785
|
-
return c},close:()=>{r?.stop(),o?.stop(),i?.stop();}}}var af="0.4.
|
|
785
|
+
return c},close:()=>{r?.stop(),o?.stop(),i?.stop();}}}var af="0.4.13";/*! Bundled license information:
|
|
786
786
|
|
|
787
787
|
@noble/curves/utils.js:
|
|
788
788
|
@noble/curves/abstract/modular.js:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bivelio/savings-layer",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.13",
|
|
4
4
|
"description": "BV-SALA — provider-neutral LLM execution optimizer. A decision layer in front of any LLM provider that cuts the cost of every request while preserving required quality, and reports the saving per call with token-level accounting you can check against your bill. Proprietary and confidential — property of BiVelio Inc.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm",
|