@bivelio/savings-layer 0.4.14 → 0.4.15
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 +126 -119
- 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,12 @@
|
|
|
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 A from'zlib';var $e
|
|
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 X="context-management-2025-06-27";function $e(){return {edits:[{type:"clear_tool_uses_20250919",trigger:{type:"input_tokens",value:5e4},keep:{type:"tool_uses",value:8},clear_at_least:{type:"input_tokens",value:5e3}}]}}function je(e,t){if(t!==void 0&&t!==""&&t!=="identity")return null;try{let n=JSON.parse(e.toString("utf8"));return n===null||typeof n!="object"||Array.isArray(n)||typeof n.model!="string"||!Array.isArray(
|
|
3
|
+
n.messages)?null:(n.context_management=At(n.context_management),Buffer.from(JSON.stringify(n),"utf8"))}catch{return null}}var It="clear_tool_uses_20250919",Ne="clear_thinking_20251015";function At(e){
|
|
4
|
+
let t=$e().edits[0],n=e!==null&&typeof e=="object"&&!Array.isArray(e)?{...e}:{},r=(Array.isArray(n.edits)?n.edits:[]).filter(i=>i!==null&&typeof i=="object"&&!Array.isArray(i)&&i.type!==It),o=r.filter(
|
|
5
|
+
i=>i.type===Ne),s=r.filter(i=>i.type!==Ne);return {...n,edits:[...o,...s,t]}}function ze(e,t){let n=" (se enciende solo si la licencia de la org trae context_elision; fail-closed)";return e==="0"?{linea:"\
|
|
6
|
+
elisi\xF3n S4a: APAGADA (BVSALA_GATEWAY_ELISION=0) \u2014 brazo CONTROL",aviso:false}:t?e==="1"?{linea:"elisi\xF3n S4a: ARMADA (BVSALA_GATEWAY_ELISION=1) \u2014 brazo PALANCA"+n,aviso:false}:{linea:"elisi\xF3n\
|
|
7
|
+
S4a: ARMADA por defecto (sin bandera; =0 la apaga) \u2014 brazo PALANCA"+n,aviso:false}:{linea:"elisi\xF3n S4a: NO SE ARMA \u2014 falta BIVELIO_SERVICE_KEY (sin clave no hay org que consultar); este proceso es \
|
|
8
|
+
brazo CONTROL"+(e==="1"?" AUNQUE la bandera diga =1. Abre un terminal nuevo o exporta la clave y relanza":""),aviso:e==="1"}}function Be(e){return e===void 0||e.trim()===""?X:e.split(",").map(n=>n.trim()).
|
|
9
|
+
filter(n=>n.length>0).includes(X)?e:`${e},${X}`}var Ue=new Set;function C(e,t){Ue.has(e)||(Ue.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
10
|
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
11
|
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
12
|
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??
|
|
@@ -7,7 +14,7 @@ Math.ceil(this.maxBuffer/this.maxBatch)+4,r=0;for(let o=0;o<n&&this.buffer.lengt
|
|
|
7
14
|
inflight)return this.inflight;if(this.buffer.length!==0){this.inflight=this.hacerFlush();try{await this.inflight;}finally{this.inflight=null;}}}async hacerFlush(){let t=this.options.fetchImpl??globalThis.
|
|
8
15
|
fetch;if(!t)return;let n=this.buffer.splice(0,this.maxBatch);try{let r=n.map(s=>this.toWire(s)),o=await t(this.options.url,{method:"POST",headers:{"content-type":"application/json",authorization:`Bear\
|
|
9
16
|
er ${this.options.serviceAccountKey}`},body:JSON.stringify(r)});o.ok?this.fallosSeguidos=0:o.status>=500?(this.fallosSeguidos++,this.requeue(n),this.avisarDeFallo(`el servidor respondi\xF3 ${o.status}`)):
|
|
10
|
-
o.status===401||o.status===403?(
|
|
17
|
+
o.status===401||o.status===403?(C(`metering-auth-${o.status}`,`[bv-sala] el env\xEDo de uso est\xE1 siendo rechazado con HTTP ${o.status} en ${this.options.url}. Revisa 'serviceAccountKey' (\xBFrotada? \xBF\
|
|
11
18
|
revocada? \xBFde otra organizaci\xF3n?). Mientras no funcione NO se reporta uso: el panel dir\xE1 que no ve tr\xE1fico y los asientos facturables saldr\xE1n a cero.`),this.options.onAuthError?.(o.status)):
|
|
12
19
|
(this.fallosSeguidos++,this.avisarDeFallo(o.status===404||o.status===405?`HTTP ${o.status}: la URL de env\xEDo parece equivocada`:`el servidor rechaz\xF3 el lote con HTTP ${o.status}`));}catch(r){this.
|
|
13
20
|
fallosSeguidos++,this.requeue(n),this.avisarDeFallo(r instanceof Error?r.message:"error de red");}}avisarDeFallo(t){if(this.options.silenceWarnings)return;let n=this.fallosSeguidos;n<3||(n-3)%12!==0||console.
|
|
@@ -17,16 +24,16 @@ length>this.maxBuffer&&(this.buffer.length=this.maxBuffer);}toWire(t){let n=t.re
|
|
|
17
24
|
model:n.model,at:t.at,avoidedLlm:n.calls.avoidedLlm,actualLlm:n.calls.actualLlm,baselineInputTokens:n.tokens.baselineInput,actualInputTokens:n.tokens.actualInput,eliminatedInputTokens:n.tokens.eliminatedInput,
|
|
18
25
|
compressedInputTokens:n.tokens.compressedInput,baselineOutputTokens:n.tokens.baselineOutput,actualOutputTokens:n.tokens.actualOutput,providerCachedInputTokens:n.tokens.providerCachedInput??0,cacheResult:n.
|
|
19
26
|
cache.result,baselineCost:n.cost.baselineEstimate,actualCost:n.cost.actual,netSavings:n.cost.netSavings,...n.cost.basis?{basis:n.cost.basis}:{},...n.attribution?.sessionId?{sessionId:n.attribution.sessionId}:
|
|
20
|
-
{},...n.attribution?.agentId?{agentId:n.attribution.agentId}:{}}}};function
|
|
21
|
-
return new RegExp(`-${t}{8,10}-${t}{5}$`).test(e)}function
|
|
22
|
-
e.NETLIFY)}async function
|
|
23
|
-
if(e.KUBERNETES_SERVICE_HOST||
|
|
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
|
|
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
|
|
26
|
-
return false;for(let t of
|
|
27
|
+
{},...n.attribution?.agentId?{agentId:n.attribution.agentId}:{}}}};function Z(){return globalThis.process}function Pt(e){if(/^[0-9a-f]{12}$/.test(e)||/^\d{1,3}(\.\d{1,3}){3}$/.test(e)||/^ip-\d{1,3}(-\d{1,3}){3}$/i.test(e))return true;let t="[bcdfghjklmnpqrstvwxz2456789]";
|
|
28
|
+
return new RegExp(`-${t}{8,10}-${t}{5}$`).test(e)}function Ot(e){return !!(e.AWS_LAMBDA_FUNCTION_NAME??e.LAMBDA_TASK_ROOT??e.VERCEL??e.VERCEL_ENV??e.K_SERVICE??e.FUNCTION_TARGET??e.FUNCTIONS_WORKER_RUNTIME??
|
|
29
|
+
e.NETLIFY)}async function Dt(){if(Z()?.execPath)try{let t=await import(["node","os"].join(":")),n=typeof t.hostname=="function"?t.hostname():"";return n.length>0?n:void 0}catch{return}}async function Lt(e,t=Dt){
|
|
30
|
+
if(e.KUBERNETES_SERVICE_HOST||Ot(e))return;let n=e.HOSTNAME??e.COMPUTERNAME??await t();if(!(!n||Pt(n)))return n}async function Mt(){let e=Z();if(!e||!e.env)return;let t=e.env,n=await Lt(t),r=[e.platform,
|
|
31
|
+
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 $t=["CI","CONTINUOUS_INTEGRATION","GITHUB_ACTI\
|
|
32
|
+
ONS","GITLAB_CI","CIRCLECI","TRAVIS","JENKINS_URL","BUILDKITE","TF_BUILD","TEAMCITY_VERSION","BITBUCKET_BUILD_NUMBER","CODEBUILD_BUILD_ID","HEROKU_TEST_RUN_ID","DRONE"];function ee(){let e=Z()?.env;if(!e)
|
|
33
|
+
return false;for(let t of $t){let n=e[t];if(n&&n!=="false"&&n!=="0")return true}return false}async function Nt(e,t){let n=globalThis.crypto,r=new TextEncoder;if(n?.subtle)try{let i=await n.subtle.importKey("raw",
|
|
27
34
|
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
|
-
|${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
|
|
29
|
-
if(!r)return;let o=await
|
|
35
|
+
|${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 te(e){let n=Z()?.env?.BVSALA_SEAT_ID;if(n&&jt.test(n))return n;let r=await Mt();
|
|
36
|
+
if(!r)return;let o=await Nt(e,r);if(o)return `m-${o.slice(0,32)}`}var jt=/^[A-Za-z0-9._:/-]{1,128}$/;var me={"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
37
|
"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,
|
|
31
38
|
outputPer1k:.06},"gpt-3.5-turbo":{inputPer1k:5e-4,outputPer1k:.0015},"gpt-5":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},"gpt-5-codex":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},
|
|
32
39
|
"gpt-5-mini":{inputPer1k:25e-5,outputPer1k:.002,cachedInputPer1k:25e-6},"gpt-5-nano":{inputPer1k:5e-5,outputPer1k:4e-4,cachedInputPer1k:5e-6},"gpt-5.1-codex":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},
|
|
@@ -43,101 +50,99 @@ able-5":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:.001},"claude-fable-5-1
|
|
|
43
50
|
cachedInputPer1k:1e-4},"claude-3-5-sonnet":{inputPer1k:.003,outputPer1k:.015,cachedInputPer1k:3e-4},"claude-3-5-haiku":{inputPer1k:8e-4,outputPer1k:.004,cachedInputPer1k:8e-5},"claude-3-opus":{inputPer1k:.015,
|
|
44
51
|
outputPer1k:.075,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},"g\
|
|
45
52
|
emini-3.5-flash":{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,
|
|
46
|
-
outputPer1k:.012,cachedInputPer1k:2e-4},"gemini-2.5-pro":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},"gemini-2.5-flash":{inputPer1k:3e-4,outputPer1k:.0025,cachedInputPer1k:3e-5}};function
|
|
53
|
+
outputPer1k:.012,cachedInputPer1k:2e-4},"gemini-2.5-pro":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},"gemini-2.5-flash":{inputPer1k:3e-4,outputPer1k:.0025,cachedInputPer1k:3e-5}};function Ve(e,t,n){
|
|
47
54
|
if(!n)return;let r=e[n];if(r)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!==
|
|
48
|
-
"."&&u!=="_")continue;let p=s.slice(a.length+1);if(!(/^\d/.test(p)&&!/^\d{4}/.test(p)))return e[a]}}function
|
|
49
|
-
|
|
55
|
+
"."&&u!=="_")continue;let p=s.slice(a.length+1);if(!(/^\d/.test(p)&&!/^\d{4}/.test(p)))return e[a]}}function fe(e){return Object.keys(e).sort((t,n)=>n.length-t.length)}var zt=fe(me);function M(e){return Ve(
|
|
56
|
+
me,zt,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(`
|
|
50
57
|
|
|
51
58
|
`))>=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;
|
|
52
|
-
let s=/^data: (.+)$/m.exec(r)?.[1];if(s)try{let i=JSON.parse(s),a=
|
|
59
|
+
let s=/^data: (.+)$/m.exec(r)?.[1];if(s)try{let i=JSON.parse(s),a=qe(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?
|
|
53
60
|
{...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.
|
|
54
|
-
uso:null}elision(){return this.elisionObservada}};function
|
|
55
|
-
let o=r.cleared_input_tokens;typeof o=="number"&&Number.isFinite(o)&&o>0&&(n+=o);}return {borrados:t.length,tokensLimpiados:n}}function
|
|
56
|
-
return
|
|
61
|
+
uso:null}elision(){return this.elisionObservada}};function qe(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){
|
|
62
|
+
let o=r.cleared_input_tokens;typeof o=="number"&&Number.isFinite(o)&&o>0&&(n+=o);}return {borrados:t.length,tokensLimpiados:n}}function Ke(e){try{let t=JSON.parse(typeof e=="string"?e:e.toString("utf8"));
|
|
63
|
+
return qe(t.context_management)}catch{return null}}var ne=class{resto="";uso=null;eventos={};observar(t){this.resto+=typeof t=="string"?t:t.toString("utf8");let n;for(;(n=this.resto.indexOf(`
|
|
57
64
|
|
|
58
65
|
`))>=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.
|
|
59
|
-
parse(s);if((o??i.type)!=="response.completed")continue;let a=i.response?.usage;a&&(this.uso
|
|
66
|
+
parse(s);if((o??i.type)!=="response.completed")continue;let a=i.response?.usage;a&&(this.uso=Bt(a));}catch{}}}usage(){return this.uso}usageFinal(){return this.uso}};function Bt(e){let t=Math.max(0,e.input_tokens??
|
|
60
67
|
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??
|
|
61
|
-
0),cache_read_input_tokens:n,cache_creation_input_tokens:r}}var
|
|
68
|
+
0),cache_read_input_tokens:n,cache_creation_input_tokens:r}}var Fe=1.25,he=2;function He(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.
|
|
62
69
|
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 {
|
|
63
|
-
costeUsd:r/1e3*n.inputPer1k+s/1e3*p+(a-u)/1e3*n.inputPer1k*
|
|
64
|
-
let r=
|
|
70
|
+
costeUsd:r/1e3*n.inputPer1k+s/1e3*p+(a-u)/1e3*n.inputPer1k*be(e)+u/1e3*n.inputPer1k*he+o/1e3*n.outputPer1k,precio:n,tokens:{entrada:r,salida:o,cacheLeida:s,cacheEscrita:a,cacheEscrita1h:u}}}function Je(e,t){
|
|
71
|
+
let r=ge(e,t)?.model;return typeof r=="string"?r:""}function ge(e,t){try{let n=e,r={maxOutputLength:Ut};switch((t??"").trim().toLowerCase()){case "gzip":case "x-gzip":n=A.gunzipSync(e,r);break;case "defl\
|
|
65
72
|
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.
|
|
66
|
-
toString("utf8"))}catch{return null}}var
|
|
67
|
-
t.startsWith("o3")||t.startsWith("o4")?/^gpt-5\.6/.test(t)?
|
|
68
|
-
function
|
|
73
|
+
toString("utf8"))}catch{return null}}var Ut=5*1024*1024;function We(){return typeof A.zstdDecompressSync=="function"}function be(e){let t=e.toLowerCase();return t.startsWith("gpt-")||t.startsWith("o1")||
|
|
74
|
+
t.startsWith("o3")||t.startsWith("o4")?/^gpt-5\.6/.test(t)?Fe:1:t.startsWith("gemini")?1:Fe}function ve(e){try{return JSON.parse(typeof e=="string"?e:e.toString("utf8")).usage??null}catch{return null}}
|
|
75
|
+
function Ge(e,t,n,r,o){return Xe(e,t,n,false,r,o)}function Ye(e,t,n,r){return Xe(e,t,n,true,r)}function Qe(e,t,n,r,o){return {requestId:e,model:t,...o&&(o.sessionId||o.agentId)?{attribution:o}:{},calls:{avoidedLlm:0,
|
|
69
76
|
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>
|
|
70
|
-
0?Math.max(-100,Math.min(1,(n-r)/n)):0,basis:"shadow"}}}function
|
|
77
|
+
0?Math.max(-100,Math.min(1,(n-r)/n)):0,basis:"shadow"}}}function Xe(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)?
|
|
71
78
|
{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.
|
|
72
79
|
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\
|
|
73
|
-
mated"}:{baselineEstimate:n.costeUsd,actual:n.costeUsd,netSavings:0,basis:"measured"}}}var
|
|
74
|
-
function
|
|
80
|
+
mated"}:{baselineEstimate:n.costeUsd,actual:n.costeUsd,netSavings:0,basis:"measured"}}}var Ft=1024,q=120,qt=8,Kt=256*1024,Ht=/error|exception|traceback|warn|fatal|fail|panic|assert|denied|refused|timeout|\bat\s+\S+:\d+/i,et=/^\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)/;
|
|
81
|
+
function Jt(e){return Buffer.byteLength(typeof e=="string"?e:JSON.stringify(e??""))}function Wt(e){return typeof e=="string"?e:Array.isArray(e)?e.map(t=>t&&typeof t=="object"&&typeof t.text=="string"?
|
|
75
82
|
t.text:"").join(`
|
|
76
|
-
`):""}var
|
|
77
|
-
`),n=Math.max(1,t.length),r=0,o=0,s=0;for(let i of t){let a=
|
|
78
|
-
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
|
|
83
|
+
`):""}var Gt=/^\s*\d+[\t→]/;function tt(e){return e.replace(Gt,"")}function Yt(e){if(!e)return "otro";let t=e.split(`
|
|
84
|
+
`),n=Math.max(1,t.length),r=0,o=0,s=0;for(let i of t){let a=tt(i);(/^[+-](?![+-])/.test(a)||a.startsWith("@@")||a.startsWith("diff --git"))&&(r+=1),et.test(a)&&(o+=1),(/^\s*(\d{4}-\d{2}-\d{2}|\[\d|\d{2}:\d{2}:\d{2})/.
|
|
85
|
+
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 Qt(e,t){if(t==="diff"||t==="otro")return Buffer.byteLength(e);let n=e.
|
|
79
86
|
split(`
|
|
80
|
-
`),r=new Set;for(let s=0;s<n.length;s++){let i=
|
|
81
|
-
n[s])+1;return Math.min(o,Buffer.byteLength(e))}function
|
|
82
|
-
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=
|
|
83
|
-
Math.min(s,Math.max(0,p)+
|
|
87
|
+
`),r=new Set;for(let s=0;s<n.length;s++){let i=tt(n[s]);(t==="log"?Ht.test(i):et.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(
|
|
88
|
+
n[s])+1;return Math.min(o,Buffer.byteLength(e))}function nt(e){let t=[],n=(r,o)=>{let s=Jt(o),i={clave:createHash("sha256").update(typeof o=="string"?o:JSON.stringify(o??"")).digest("hex").slice(0,16),tipo:r,
|
|
89
|
+
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=Wt(a.content);i.clase=Yt(u);let p=s-Buffer.byteLength(u);i.bytesV1=
|
|
90
|
+
Math.min(s,Math.max(0,p)+Qt(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)?
|
|
84
91
|
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))
|
|
85
|
-
for(let i of o.content)n(`${s}:${i?.type??"?"}`,i);}return t}function
|
|
86
|
-
e.nacimiento.set(r.clave,n);return n}function
|
|
87
|
-
}function
|
|
88
|
-
inputPer1k*
|
|
89
|
-
"5m":3e5},K=class{constructor(t){this.transformar=t;}transformar;estado=
|
|
90
|
-
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=
|
|
92
|
+
for(let i of o.content)n(`${s}:${i?.type??"?"}`,i);}return t}function Xt(){return {nacimiento:new Map,turno:0,elididosV2m:new Set}}function Zt(e,t){let n=e.turno++;for(let r of t)e.nacimiento.has(r.clave)||
|
|
93
|
+
e.nacimiento.set(r.clave,n);return n}function ot(e,t,n,r,o=Kt){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>=Ft&&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>=qt?{clave:`${l.clave}:e`,bytes:q}:{clave:l.clave,bytes:l.bytes}});
|
|
94
|
+
}function en(e){let t=M(e);return t?{lecturaPer1k:t.cachedInputPer1k??t.inputPer1k,escrituraPer1k:t.
|
|
95
|
+
inputPer1k*be(e),escritura1hPer1k:t.inputPer1k*he}:null}function Ze(){return {lecturaUsd:0,escrituraUsd:0,totalUsd:0,tokensLeidos:0,tokensEscritos:0,tokensInvalidados:0,invalidacionUsd:0}}var tn={"1h":36e5,
|
|
96
|
+
"5m":3e5},K=class{constructor(t){this.transformar=t;}transformar;estado=Xt();previo=[];hayPrevio=false;atPrevio=0;acumulado=Ze();paso(t){let n=Ze(),r=Zt(this.estado,t.bloques),o=en(t.model),s=this.transformar(
|
|
97
|
+
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=tn[t.escritura1h?"1h":
|
|
91
98
|
"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,
|
|
92
99
|
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+=
|
|
93
100
|
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.
|
|
94
101
|
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.
|
|
95
|
-
tokensLeidos+=n.tokensLeidos,this.acumulado.tokensEscritos+=n.tokensEscritos,this.acumulado.tokensInvalidados+=n.tokensInvalidados,this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function
|
|
96
|
-
input_tokens??0)+(t.uso.cache_read_input_tokens??0)+n;if(r<=0)return null;let o={bloques:
|
|
102
|
+
tokensLeidos+=n.tokensLeidos,this.acumulado.tokensEscritos+=n.tokensEscritos,this.acumulado.tokensInvalidados+=n.tokensInvalidados,this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function rt(e){return e.map(t=>({clave:t.clave,bytes:t.bytes}))}var on=64,oe=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.
|
|
103
|
+
input_tokens??0)+(t.uso.cache_read_input_tokens??0)+n;if(r<=0)return null;let o={bloques:nt(t.cuerpo),at:t.at,model:t.model,entradaReal:r,escritura1h:(t.uso.cache_creation?.ephemeral_1h_input_tokens??
|
|
97
104
|
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){
|
|
98
105
|
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(
|
|
99
|
-
"hex").slice(0,16)}\xB7${t.model}`}cadenaPara(t){let n=this.cadenas.get(t);if(!n&&(n={base:new K(r=>
|
|
100
|
-
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
|
|
106
|
+
"hex").slice(0,16)}\xB7${t.model}`}cadenaPara(t){let n=this.cadenas.get(t);if(!n&&(n={base:new K(r=>rt(r)),v0:new K((r,o,s)=>ot("v0",r,o,s)),ultimoUso:0},this.cadenas.set(t,n),this.cadenas.size>on)){let r=null,
|
|
107
|
+
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 re=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.
|
|
101
108
|
fetchImpl??fetch,this.log=t.log??(()=>{}),this.refrescar();}tiene(t){return Date.now()>this.validoHasta&&this.enVuelo===null&&this.refrescar(),this.features.has(t)}refrescar(){return this.enVuelo?this.
|
|
102
109
|
enVuelo:(this.enVuelo=this.pedir().finally(()=>{this.enVuelo=null;}),this.enVuelo)}async pedir(){try{let t=await this.fetchImpl(this.url,{method:"GET",headers:{authorization:`Bearer ${this.clave}`},signal:AbortSignal.
|
|
103
110
|
timeout(1e4)});if(!t.ok){this.cerrar(`entitlements HTTP ${t.status}`);return}let n=await t.json();if(!Array.isArray(n.features)||!n.features.every(o=>typeof o=="string")){this.cerrar("entitlements con\
|
|
104
111
|
forma inesperada");return}this.features=new Set(n.features);let r=typeof n.refreshAfterSeconds=="number"&&n.refreshAfterSeconds>0?Math.min(n.refreshAfterSeconds*1e3,this.ttlMs):this.ttlMs;this.validoHasta=
|
|
105
112
|
Date.now()+r,this.avisado=!1;}catch(t){this.cerrar(String(t));}}cerrar(t){this.features=new Set,this.validoHasta=Date.now()+Math.min(6e4,this.ttlMs),this.avisado||(this.avisado=true,this.log(`[gateway] en\
|
|
106
|
-
titlements no disponibles (${t}) \u2014 palanca apagada (fail-closed)`));}};var
|
|
107
|
-
n.messages)?null:(n.context_management=et(),Buffer.from(JSON.stringify(n),"utf8"))}catch{return null}}function nt(e){return e===void 0||e.trim()===""?re:e.split(",").map(n=>n.trim()).filter(n=>n.length>
|
|
108
|
-
0).includes(re)?e:`${e},${re}`}var ve=5*1024*1024,tn=["authorization","x-api-key","anthropic-version","anthropic-beta"];function ot(e,t,n,r=""){return createHash("sha256").update(e).update(`
|
|
113
|
+
titlements no disponibles (${t}) \u2014 palanca apagada (fail-closed)`));}};var ye=5*1024*1024,sn=["authorization","x-api-key","anthropic-version","anthropic-beta"];function st(e,t,n,r=""){return createHash("sha256").update(e).update(`
|
|
109
114
|
`).update(t).update(`
|
|
110
115
|
`).update(r).update(`
|
|
111
|
-
`).update(n).digest("hex")}function
|
|
116
|
+
`).update(n).digest("hex")}function it(e){return sn.map(t=>`${t}=${e(t)??""}`).join(`
|
|
112
117
|
`)}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=[],
|
|
113
|
-
s=0,i=false;return {capturar:a=>{if(!i){if(s+=a.length,s>
|
|
118
|
+
s=0,i=false;return {capturar:a=>{if(!i){if(s+=a.length,s>ye){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),
|
|
114
119
|
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+=
|
|
115
|
-
1),r}tieneEnVuelo(t){return this.enVuelo.has(t)}};var
|
|
116
|
-
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=>
|
|
120
|
+
1),r}tieneEnVuelo(t){return this.enVuelo.has(t)}};var ln=["content-encoding","content-length","transfer-encoding"];async function at(e={}){let t=(e.upstream??"https://api.anthropic.com").replace(/\/+$/,""),n=e.fetchImpl??fetch,r=e.log??(c=>console.log(
|
|
121
|
+
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=>C(
|
|
117
122
|
"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\
|
|
118
|
-
E_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let c=
|
|
119
|
-
-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.
|
|
120
|
-
coalescer?new se:null,i=e.sombra&&o?new
|
|
121
|
-
serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},log:r}):null,u=c=>c==="/v1/messages"?new $:c.endsWith("/responses")?new
|
|
122
|
-
V=h,S=
|
|
123
|
-
S,h);T?(o.record(b?
|
|
123
|
+
E_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let c=ee();e.seatId?o.setSeat(e.seatId,c):te(e.serviceAccountKey).then(d=>o?.setSeat(d,c)).catch(()=>{}),o.start();}else C("gateway-si\
|
|
124
|
+
n-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.
|
|
125
|
+
coalescer?new se:null,i=e.sombra&&o?new oe:null,a=e.elision!==false&&e.serviceAccountKey?new re({url:new URL("/api/org/entitlements",e.meteringUrl??"https://savings.bivelio.com/api/metering/usage").toString(),
|
|
126
|
+
serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},log:r}):null,u=c=>c==="/v1/messages"?new $:c.endsWith("/responses")?new ne:null,p=(c,d,h,b,v,f,y,R)=>{if(!o||!h)return;let W=o,
|
|
127
|
+
V=h,S=Je(d,f);if(!S){C(`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=He(
|
|
128
|
+
S,h);T?(o.record(b?Ye(c,S,T,y):Ge(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.
|
|
124
129
|
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}\
|
|
125
|
-
tok limpiados por el proveedor`:"")),i&&!b&&v==="/v1/messages"&&setImmediate(()=>{try{let L=
|
|
126
|
-
void 0?{sessionId:y.sessionId}:{},...y?.agentId!==void 0?{agentId:y.agentId}:{}});if(!_)return;W.record(
|
|
127
|
-
baselineUsd.toFixed(6)} \u2192 v0 $${_.politicaUsd.toFixed(6)}`);}catch{}})):
|
|
130
|
+
tok limpiados por el proveedor`:"")),i&&!b&&v==="/v1/messages"&&setImmediate(()=>{try{let L=ge(d,f);if(!L||typeof L!="object")return;let _=i.observar({cuerpo:L,uso:V,model:S,at:Date.now(),...y?.sessionId!==
|
|
131
|
+
void 0?{sessionId:y.sessionId}:{},...y?.agentId!==void 0?{agentId:y.agentId}:{}});if(!_)return;W.record(Qe(`${c}:shadow`,S,_.baselineUsd,_.politicaUsd,y)),r(`[gateway] sombra \xB7 ${S} \xB7 baseline $${_.
|
|
132
|
+
baselineUsd.toFixed(6)} \u2192 v0 $${_.politicaUsd.toFixed(6)}`);}catch{}})):C(`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 \
|
|
128
133
|
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\
|
|
129
134
|
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\
|
|
130
135
|
-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??
|
|
131
|
-
"/",t);let Y=s!==null&&c.method==="POST"&&w.length>0,
|
|
132
|
-
esperar(
|
|
133
|
-
chunks)):null);p(h,w,
|
|
134
|
-
", "):x);let Oe=w;if(a!==null&&c.method==="POST"&&f.pathname==="/v1/messages"&&a.tiene("context_elision"))try{let g=
|
|
135
|
-
|
|
136
|
-
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
|
|
137
|
-
fromEntries(
|
|
138
|
-
y=
|
|
139
|
-
body){let x=Buffer.from(g);d.write(x),y?.observar(x),F&&(Le+=x.length,Le>
|
|
140
|
-
w,y.usage(),!1,f.pathname,S,G,g);}else if(F){let g=Buffer.concat(F);p(h,w,
|
|
136
|
+
"/",t);let Y=s!==null&&c.method==="POST"&&w.length>0,Rt=it(g=>{let x=c.headers[g];return Array.isArray(x)?x.join(", "):x}),ue=Y?st("POST",f.pathname+f.search,w,Rt):"";if(Y)if(s.tieneEnVuelo(ue)){let g=await s.
|
|
137
|
+
esperar(ue);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 _t=x.usage()??(f.pathname==="/v1/messages"?ve(Buffer.concat(g.
|
|
138
|
+
chunks)):null);p(h,w,_t,!0,f.pathname,S,G);return}}else v=s.registrar(ue);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(
|
|
139
|
+
", "):x);let Oe=w;if(a!==null&&c.method==="POST"&&f.pathname==="/v1/messages"&&a.tiene("context_elision"))try{let g=je(w,S);g!==null&&(Oe=g,Q["anthropic-beta"]=Be(Q["anthropic-beta"]));}catch{}let E;try{
|
|
140
|
+
E=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\
|
|
141
|
+
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 de=Object.
|
|
142
|
+
fromEntries(E.headers.entries());for(let g of ln)delete de[g];d.writeHead(E.status,de);let De=E.headers.get("content-type")??"",pe=De.includes("text/event-stream")||De===""&&E.ok&&u(f.pathname)!==null;
|
|
143
|
+
y=pe?u(f.pathname):null;let F=!pe&&E.ok&&o!==void 0&&c.method==="POST"&&f.pathname==="/v1/messages"&&(E.headers.get("content-type")??"").includes("application/json")?[]:null,Le=0;if(E.body)for await(let g of E.
|
|
144
|
+
body){let x=Buffer.from(g);d.write(x),y?.observar(x),F&&(Le+=x.length,Le>ye?F=null:F.push(x)),v?.capturar(x);}if(d.end(),v?.terminar(E.status,de),y&&E.ok){W=!0;let g=y instanceof $?y.elision():null;p(h,
|
|
145
|
+
w,y.usage(),!1,f.pathname,S,G,g);}else if(F){let g=Buffer.concat(F);p(h,w,ve(g),!1,f.pathname,S,G,Ke(g));}else pe||r(`[gateway] ${c.method} ${f.pathname} \u2192 ${E.status}`);}catch(I){if(v?.abortar(),b.
|
|
141
146
|
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,
|
|
142
147
|
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)}`),
|
|
143
148
|
!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(
|
|
@@ -146,17 +151,17 @@ d.end(`HTTP/1.1 426 Upgrade Required\r
|
|
|
146
151
|
connection: close\r
|
|
147
152
|
content-length: 0\r
|
|
148
153
|
\r
|
|
149
|
-
`);}),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
|
|
154
|
+
`);}),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 ke=["claude","codex","goose","qwen"];function lt(e){return ke.includes(e??"")}function ut(e,t={}){let n=t.path??process.env.PATH??"",r=t.
|
|
150
155
|
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+
|
|
151
|
-
i);if(r(a)){o=a;break}}}return o!==null?{tipo:"solo-shim",ruta:o}:{tipo:"no-encontrado"}}function
|
|
156
|
+
i);if(r(a)){o=a;break}}}return o!==null?{tipo:"solo-shim",ruta:o}:{tipo:"no-encontrado"}}function dt(e={}){let n=(e.env??process.env).BVSALA_CODEX_AUTH?.toLowerCase();if(n==="api-key"||n==="apikey")return "\
|
|
152
157
|
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.
|
|
153
|
-
toLowerCase().replace(/[^a-z]/g,"")==="apikey"?"api-key":"chatgpt":o.tokens!==void 0&&o.tokens!==null?"chatgpt":"api-key"}catch{return "api-key"}}var
|
|
154
|
-
/v1"},chatgpt:{upstream:"https://chatgpt.com",prefijo:"/backend-api/codex"}};function
|
|
158
|
+
toLowerCase().replace(/[^a-z]/g,"")==="apikey"?"api-key":"chatgpt":o.tokens!==void 0&&o.tokens!==null?"chatgpt":"api-key"}catch{return "api-key"}}var dn={"api-key":{upstream:"https://api.openai.com",prefijo:"\
|
|
159
|
+
/v1"},chatgpt:{upstream:"https://chatgpt.com",prefijo:"/backend-api/codex"}};function xe(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 "\
|
|
155
160
|
goose":return {bin:"goose",args:n,env:{ANTHROPIC_HOST:o}};case "qwen":return {bin:"qwen",args:n,env:{ANTHROPIC_BASE_URL:o},nota:'Qwen Code solo enruta por aqu\xED con `security.auth.selectedType: "anthropic\
|
|
156
|
-
"` en ~/.qwen/settings.json (ver `bvsala doctor`).'};case "codex":{let s=r.modoCodex??"api-key",i=
|
|
161
|
+
"` en ~/.qwen/settings.json (ver `bvsala doctor`).'};case "codex":{let s=r.modoCodex??"api-key",i=dn[s];return {bin:"codex",args:["-c",`openai_base_url="${o}${i.prefijo}"`,...n],env:{},upstream:i.upstream,
|
|
157
162
|
nota:s==="chatgpt"?"Auth ChatGPT detectada: el gateway enruta a chatgpt.com/backend-api/codex. El tr\xE1fico de suscripci\xF3n se mide (equivalente a precio de lista) pero no se monetiza: no hay factura por\
|
|
158
|
-
tokens.":"Auth por API key: el gateway enruta a api.openai.com/v1."}}}}var
|
|
159
|
-
s `/v1/v1/messages`, sobra un /v1; si ves `POST /messages` a secas, falta uno.",
|
|
163
|
+
tokens.":"Auth por API key: el gateway enruta a api.openai.com/v1."}}}}var hn="comprobar: en el log del gateway debe aparecer `[gateway] POST /v1/messages \u2026`; si ve\
|
|
164
|
+
s `/v1/v1/messages`, sobra un /v1; si ves `POST /messages` a secas, falta uno.",gn=[{id:"claude",nombre:"Claude Code",binario:"claude",configs:[],detectable:true,receta:({base:e})=>["usa `bvsala claude`\
|
|
160
165
|
\u2014 arranca el gateway en un puerto ef\xEDmero, lanza `claude` apunt\xE1ndole y lo apaga al salir.",`a mano: ANTHROPIC_BASE_URL=${e} claude (sin /v1: el cliente a\xF1ade /v1/messages)`]},{id:"co\
|
|
161
166
|
dex",nombre:"Codex CLI",binario:"codex",configs:[join(".codex","config.toml"),join(".codex","auth.json")],detectable:true,receta:({base:e,rutas:t})=>["usa `bvsala codex` \u2014 el prefijo del base URL depende del \
|
|
162
167
|
modo de auth y lo resuelve el envoltorio:",` API key \u2192 openai_base_url=${e}/v1`,` suscripci\xF3n ChatGPT \u2192 openai_base_url=${e}/backend-api/codex (tiene que terminar exactament\
|
|
@@ -172,40 +177,40 @@ Droid (Factory)",binario:"droid",configs:[join(".factory","settings.json")],dete
|
|
|
172
177
|
idar en mano contra el log del gateway].`,"{",' "customModels": ['," {",' "model": "<id de modelo Anthropic>",',' "displayName": "<nombre visible>",',' "provider": "anthropic",',` \
|
|
173
178
|
"baseUrl": "${e}",`,' "apiKey": "<tu API key de Anthropic>"'," }"," ]","}"]},{id:"cline",nombre:"Cline",configs:[],detectable:false,receta:({baseV1:e})=>["mecanismo: UI \u2192 proveedor Anthropic\
|
|
174
179
|
\u2192 marca \xABUse custom base URL\xBB. CON /v1 (Cline fija https://api.anthropic.com/v1 y solo normaliza la URL oficial exacta).",`Base URL: ${e}`]},{id:"kilo",nombre:"Kilo Code",configs:[],detectable:false,
|
|
175
|
-
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
|
|
176
|
-
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
|
|
177
|
-
e>65535)throw new RangeError(`[bvsala doctor] puerto inv\xE1lido: ${String(e)}`);let n=t.home??homedir(),r=t.existe??existsSync,o=t.enPath??
|
|
180
|
+
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 bn(e,t){
|
|
181
|
+
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 pt(e,t={}){if(!Number.isInteger(e)||e<1||
|
|
182
|
+
e>65535)throw new RangeError(`[bvsala doctor] puerto inv\xE1lido: ${String(e)}`);let n=t.home??homedir(),r=t.existe??existsSync,o=t.enPath??bn(t.path??process.env.PATH??"",r),s=`http://127.0.0.1:${e}`,i=`${s}/v1`,
|
|
178
183
|
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 \
|
|
179
|
-
se lee el contenido de ning\xFAn archivo.",""];for(let p of
|
|
184
|
+
se lee el contenido de ning\xFAn archivo.",""];for(let p of gn){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?
|
|
180
185
|
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.
|
|
181
|
-
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(` ${
|
|
186
|
+
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(` ${hn}`),u.push("");}return u.push("Regla BYOK: las recetas del anillo Anth\
|
|
182
187
|
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 \
|
|
183
188
|
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(`
|
|
184
|
-
`),detectados:a}}var
|
|
185
|
-
<!-- bvsala:savings-mode:fin -->";function
|
|
189
|
+
`),detectados:a}}var mt="savings-mode";function ft(e,t){for(let n of e){let r=join(n,"skills",mt,"SKILL.md");if(t.existe(r))return r}return null}var ht="<!-- bvsala:savings-mode:inicio -->",ie="\
|
|
190
|
+
<!-- bvsala:savings-mode:fin -->";function vn(e){let t=e.replace(/^---\n[\s\S]*?\n---\n*/,"").trim();return `${ht}
|
|
186
191
|
${t}
|
|
187
192
|
|
|
188
193
|
_Always on (AGENTS.md has no activation step). Delete this block to turn it off; \`bvsala skill --codex --forzar\` restores it._
|
|
189
|
-
${ie}`}function
|
|
194
|
+
${ie}`}function gt(e){let t=ft(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=vn(e.fs.
|
|
190
195
|
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+`
|
|
191
|
-
`),{ok:true,destino:o,mensaje:
|
|
196
|
+
`),{ok:true,destino:o,mensaje:Se(o,"instalado")};let s=e.fs.leer(o),i=s.indexOf(ht),a=s.indexOf(ie);return i===-1||a===-1||a<i?(e.fs.escribir(o,s.trimEnd()+`
|
|
192
197
|
|
|
193
198
|
`+n+`
|
|
194
|
-
`),{ok:true,destino:o,mensaje:
|
|
195
|
-
slice(0,i)+n+s.slice(a+ie.length)),{ok:true,destino:o,mensaje:
|
|
196
|
-
usa --forzar para actualizarlo`}}function
|
|
199
|
+
`),{ok:true,destino:o,mensaje:Se(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.
|
|
200
|
+
slice(0,i)+n+s.slice(a+ie.length)),{ok:true,destino:o,mensaje:Se(o,"bloque actualizado")}):{ok:false,destino:o,mensaje:`[bvsala skill] el bloque savings-mode de ${o} tiene contenido DISTINTO \u2014 no lo piso; \
|
|
201
|
+
usa --forzar para actualizarlo`}}function Se(e,t){return `[bvsala skill] ${t}: ${e}
|
|
197
202
|
[bvsala skill] AGENTS.md va SIEMPRE activo en Codex (no hay paso de activaci\xF3n); borra el bloque para apagarlo.
|
|
198
|
-
[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
|
|
199
|
-
mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${e.origenes.join(", ")})`};let n=e.proyecto?join(e.cwd,".claude","skills"):join(e.home,".claude","skills"),r=join(n,
|
|
203
|
+
[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 bt(e){let t=ft(e.origenes,e.fs);if(!t)return {ok:false,destino:"",
|
|
204
|
+
mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${e.origenes.join(", ")})`};let n=e.proyecto?join(e.cwd,".claude","skills"):join(e.home,".claude","skills"),r=join(n,mt),o=join(r,
|
|
200
205
|
"SKILL.md"),s=e.fs.leer(t);if(e.fs.existe(o)&&!e.forzar){let i=e.fs.leer(o)===s;return {ok:i,destino:o,mensaje:i?`[bvsala skill] ya instalado y al d\xEDa: ${o}`:`[bvsala skill] ya existe ${o} con conte\
|
|
201
206
|
nido DISTINTO \u2014 no lo piso; usa --forzar para sobrescribir`}}return e.fs.crearDir(r),e.fs.escribir(o,s),{ok:true,destino:o,mensaje:`[bvsala skill] instalado: ${o}
|
|
202
207
|
[bvsala skill] arranca (o reinicia) Claude Code y p\xEDdele \xABsavings mode\xBB \u2014 o deja que se active solo al hablar de l\xEDmites.
|
|
203
|
-
[bvsala skill] para medir su efecto de verdad: trabaja unos d\xEDas con \xE9l y otros sin \xE9l bajo \`bvsala claude\`, y compara en el panel.`}}var
|
|
208
|
+
[bvsala skill] para medir su efecto de verdad: trabaja unos d\xEDas con \xE9l y otros sin \xE9l bajo \`bvsala claude\`, y compara en el panel.`}}var we=class{id;exact=false;constructor(t="heuristic"){this.id=t;}count(t){if(t.length===0)return 0;let n=t.match(/[A-Za-z]+|\d+|\s+|[^\sA-Za-z\d]/g)??[],r=0;for(let o of n){let s=o[0];if(/\s/.test(s)){let i=(o.
|
|
204
209
|
match(/\n/g)??[]).length;r+=i+Math.floor(Math.max(0,o.length-1)/2);}else /[A-Za-z]/.test(s)?r+=Math.max(1,Math.ceil(o.length/4)):/\d/.test(s)?r+=Math.max(1,Math.ceil(o.length/2)):r+=1;}return Math.max(r,
|
|
205
|
-
Math.ceil(t.length/4))}},
|
|
210
|
+
Math.ceil(t.length/4))}},Te=new we;var Ee=class{estimators=new Map;modelToTokenizer=new Map;fallbackId;constructor(t=Te){this.fallbackId=t.id,this.estimators.set(t.id,t);}register(t){return this.estimators.set(t.id,t),this}mapModel(t,n){
|
|
206
211
|
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.
|
|
207
|
-
get(r);if(o)return o}}return this.estimators.get(this.fallbackId)}count(t,n){return this.resolve(n).count(t)}};new
|
|
208
|
-
|
|
212
|
+
get(r);if(o)return o}}return this.estimators.get(this.fallbackId)}count(t,n){return this.resolve(n).count(t)}};new Ee;new TextEncoder;new TextDecoder;new TextDecoder;var Ln={"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}};
|
|
213
|
+
fe(Ln);var Ie="0.4.15";var[,,k,...O]=process.argv;function Un(){console.log(`bvsala ${Ie} \u2014 BiVelio Savings Layer
|
|
209
214
|
|
|
210
215
|
Comandos:
|
|
211
216
|
gateway [--puerto N] Proxy local medidor (por defecto 8402) para terminales que
|
|
@@ -233,34 +238,36 @@ Entorno:
|
|
|
233
238
|
BVSALA_GATEWAY_SHADOW =1 enciende el carril sombra de la elisi\xF3n (S2): calcula qu\xE9
|
|
234
239
|
habr\xEDa ahorrado la pol\xEDtica v0 SIN tocar el tr\xE1fico y lo
|
|
235
240
|
reporta aparte (jam\xE1s entra en la comisi\xF3n).
|
|
236
|
-
BVSALA_GATEWAY_ELISION =
|
|
237
|
-
enciende de verdad si
|
|
238
|
-
trae el feature context_elision (consulta
|
|
239
|
-
SOLO el bloque context_management de cada
|
|
240
|
-
y el borrado lo hace el propio proveedor.
|
|
241
|
-
la petici\xF3n viaja intacta.
|
|
241
|
+
BVSALA_GATEWAY_ELISION =0 APAGA la palanca de diales del proveedor (S4a), que va
|
|
242
|
+
armada por defecto. Solo se enciende de verdad si la licencia
|
|
243
|
+
de tu organizaci\xF3n trae el feature context_elision (consulta
|
|
244
|
+
fail-closed): ajusta SOLO el bloque context_management de cada
|
|
245
|
+
petici\xF3n /v1/messages y el borrado lo hace el propio proveedor.
|
|
246
|
+
Ante cualquier duda, la petici\xF3n viaja intacta. (Hasta 0.4.13
|
|
247
|
+
la bandera era al rev\xE9s: \xAB=1 arma\xBB; en un A/B p\xE1sala SIEMPRE
|
|
248
|
+
expl\xEDcita, =1 o =0, y no depender\xE1s de la versi\xF3n instalada.)
|
|
242
249
|
BVSALA_CODEX_AUTH api-key | chatgpt \u2014 fuerza el modo de auth de Codex.
|
|
243
250
|
BVSALA_GATEWAY_LOG =1 ense\xF1a el log por petici\xF3n tambi\xE9n dentro de los envoltorios
|
|
244
251
|
(por defecto va silenciado para no pisar el TUI; mira el panel).
|
|
245
252
|
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 (Claude Code, solo API key) tus modelos en /model.
|
|
246
253
|
|
|
247
254
|
El gateway nunca corta el tr\xE1fico: sin clave o con la ingesta ca\xEDda, reenv\xEDa y avisa.
|
|
248
|
-
Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}var J=
|
|
255
|
+
Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}var J=lt(k);k!=="gateway"&&k!=="doctor"&&k!=="skill"&&!J&&(Un(),process.exit(k===void 0||k==="hel\
|
|
249
256
|
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"),
|
|
250
|
-
fs:{existe:existsSync,leer:r=>readFileSync(r,"utf8"),escribir:(r,o)=>writeFileSync(r,o),crearDir:r=>mkdirSync(r,{recursive:true})}},n=O.includes("--codex")?
|
|
251
|
-
to"),U=J?0:
|
|
252
|
-
"--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
|
|
253
|
-
|
|
254
|
-
...
|
|
257
|
+
fs:{existe:existsSync,leer:r=>readFileSync(r,"utf8"),escribir:(r,o)=>writeFileSync(r,o),crearDir:r=>mkdirSync(r,{recursive:true})}},n=O.includes("--codex")?gt(t):bt(t);console.log(n.mensaje),process.exit(n.ok?0:1);}var Pe=O.indexOf("--puer\
|
|
258
|
+
to"),U=J?0:Pe>=0?Number(O[Pe+1]):8402;(!Number.isInteger(U)||(k==="doctor"?U<1:U<0)||U>65535)&&(console.error(`[bvsala ${k}] puerto inv\xE1lido: ${O[Pe+1]}`),process.exit(1));if(k==="doctor"){O.includes(
|
|
259
|
+
"--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 pt(U);console.log(e.texto),process.exit(0);}var D=J?
|
|
260
|
+
xe(k,0,O,{modoCodex:k==="codex"?dt({leerAuth:()=>readFileSync(join(homedir(),".codex","auth.json"),"utf8")}):void 0}):null,le=process.env.BIVELIO_SERVICE_KEY,Vn=J&&process.env.BVSALA_GATEWAY_LOG!=="1",j=await at({puerto:U,
|
|
261
|
+
...Vn?{log:()=>{}}:{},...le?{serviceAccountKey:le}:{},...process.env.BVSALA_SEAT_ID?{seatId:process.env.BVSALA_SEAT_ID}:{},...process.env.BVSALA_GATEWAY_UPSTREAM?{upstream:process.env.BVSALA_GATEWAY_UPSTREAM}:
|
|
255
262
|
D?.upstream?{upstream:D.upstream}:{},...process.env.BVSALA_GATEWAY_COALESCE==="1"?{coalescer:true}:{},...process.env.BVSALA_GATEWAY_SHADOW==="1"?{sombra:true}:{},elision:process.env.BVSALA_GATEWAY_ELISION!==
|
|
256
|
-
"0",...process.env.BVSALA_METERING_URL?{meteringUrl:process.env.BVSALA_METERING_URL}:{}}),
|
|
257
|
-
v${
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
{}});e.nota&&console.log(`[bvsala ${k}] ${e.nota}`);let t=e.bin;if(process.platform==="
|
|
262
|
-
|
|
263
|
-
la receta manual de docs/terminales/.`),await j.cerrar(),process.exit(127));}let n=spawn(
|
|
264
|
-
lanzar \`${e.bin}\`: ${String(r)}. \xBFEst\xE1 instalado y en el PATH?`),j.cerrar().then(
|
|
265
|
-
`[bvsala gateway] apunta tu terminal (o usa \`bvsala ${
|
|
266
|
-
process.exit(0);};process.on("SIGINT",()=>{
|
|
263
|
+
"0",...process.env.BVSALA_METERING_URL?{meteringUrl:process.env.BVSALA_METERING_URL}:{}}),Fn=process.env.BVSALA_GATEWAY_UPSTREAM??D?.upstream??"https://api.anthropic.com";console.log(`[bvsala gateway]\
|
|
264
|
+
v${Ie} escuchando en http://127.0.0.1:${j.puerto} \u2192 ${Fn}`);console.log(`[bvsala gateway] medici\xF3n: ${le?"ACTIVA (clave de servicio presente)":"APAGADA (falta BIVELIO_SERVICE_KEY)"}`);{let e=ze(
|
|
265
|
+
process.env.BVSALA_GATEWAY_ELISION,le!==void 0);(e.aviso?console.error:console.log)(`[bvsala gateway] ${e.linea}`);}process.env.BVSALA_GATEWAY_UPSTREAM&&D?.upstream&&process.env.BVSALA_GATEWAY_UPSTREAM!==
|
|
266
|
+
D.upstream&&console.error(`[bvsala ${k}] AVISO: BVSALA_GATEWAY_UPSTREAM=${process.env.BVSALA_GATEWAY_UPSTREAM} pisa el upstream de este terminal (${D.upstream}). Si no es lo que quieres, quita la vari\
|
|
267
|
+
able.`);k==="codex"&&!We()&&console.error(`[bvsala codex] AVISO: este Node (${process.version}) no descomprime zstd y Codex manda el cuerpo en zstd: el tr\xE1fico pasa pero NO se mide. Usa Node \u2265 22.15.`);
|
|
268
|
+
if(D&&J){let e=xe(k,j.puerto,O,{...D.upstream?{modoCodex:D.upstream.includes("chatgpt.com")?"chatgpt":"api-key"}:{}});e.nota&&console.log(`[bvsala ${k}] ${e.nota}`);let t=e.bin;if(process.platform==="\
|
|
269
|
+
win32"){let r=ut(e.bin);r.tipo==="exe"?t=r.ruta:r.tipo==="solo-shim"&&(console.error(`[bvsala ${k}] \`${e.bin}\` est\xE1 instalado como shim de npm (${r.ruta}) y Windows no puede lanzarlo de forma seg\
|
|
270
|
+
ura con argumentos (CVE-2024-27980). Inst\xE1lalo con su instalador nativo (deja un ${e.bin}.exe en el PATH) o usa la receta manual de docs/terminales/.`),await j.cerrar(),process.exit(127));}let n=spawn(
|
|
271
|
+
t,e.args,{stdio:"inherit",env:{...process.env,...e.env}});n.on("error",r=>{console.error(`[bvsala ${k}] no se pudo lanzar \`${e.bin}\`: ${String(r)}. \xBFEst\xE1 instalado y en el PATH?`),j.cerrar().then(
|
|
272
|
+
()=>process.exit(127));}),n.on("exit",(r,o)=>{j.cerrar().then(()=>process.exit(r??(o?1:0)));});}else console.log(`[bvsala gateway] apunta tu terminal (o usa \`bvsala ${ke.join("|")}\`): ANTHROPIC_BASE_UR\
|
|
273
|
+
L=http://127.0.0.1:${j.puerto} claude \xB7 bvsala doctor para el resto`);var Ct=async()=>{await j.cerrar(),process.exit(0);};process.on("SIGINT",()=>{Ct();});process.on("SIGTERM",()=>{Ct();});
|
package/dist/index.d.ts
CHANGED
|
@@ -3319,6 +3319,6 @@ declare function createSavingsLayer(config: Omit<SavingsLayerConfig, "tokenizer"
|
|
|
3319
3319
|
* constant to package.json so the two can never drift.
|
|
3320
3320
|
*/
|
|
3321
3321
|
|
|
3322
|
-
declare const BV_SALA_VERSION = "0.4.
|
|
3322
|
+
declare const BV_SALA_VERSION = "0.4.15";
|
|
3323
3323
|
|
|
3324
3324
|
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
|
@@ -792,7 +792,7 @@ ng/usage`:void 0);if(a){i=new dt({url:a,serviceAccountKey:t.serviceAccountKey,..
|
|
|
792
792
|
{},...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.
|
|
793
793
|
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??lo();if(t.metering?.seatId)
|
|
794
794
|
i.setSeat(t.metering.seatId,c);else {let l=i;uo(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{}
|
|
795
|
-
return c},close:()=>{o?.stop(),r?.stop(),i?.stop();}}}var yf="0.4.
|
|
795
|
+
return c},close:()=>{o?.stop(),r?.stop(),i?.stop();}}}var yf="0.4.15";/*! Bundled license information:
|
|
796
796
|
|
|
797
797
|
@noble/curves/utils.js:
|
|
798
798
|
@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.15",
|
|
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",
|