@bivelio/savings-layer 0.4.20 → 0.4.21
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 +266 -253
- package/dist/index.d.ts +84 -3
- package/dist/index.js +544 -539
- package/package.json +1 -1
package/dist/gateway/bin.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
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 {randomUUID,createHash}from'crypto';import {createServer}from'http';import*as
|
|
3
|
-
n.messages))return null;let o
|
|
4
|
-
return null}}function
|
|
5
|
-
n)!==
|
|
6
|
-
|
|
7
|
-
s.value>0?s.value:1e5;a<o&&(o=a);}return o}function
|
|
8
|
-
clear_tool_uses_20250919",
|
|
9
|
-
null&&typeof a=="object"&&!Array.isArray(a)&&a.type!==
|
|
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 {randomUUID,createHash}from'crypto';import {createServer}from'http';import*as z from'zlib';import {connect}from'net';var ve="context-management-2025-06-27";function Be(){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 Et(t,e){if(e!==void 0&&e!==""&&e!=="identity")return null;try{let n=JSON.parse(t.toString("utf8"));if(n===null||typeof n!="object"||Array.isArray(n)||typeof n.model!="string"||!Array.isArray(
|
|
3
|
+
n.messages))return null;let o=$n(n.context_management),r=jn(n.context_management);return n.context_management=Nn(n.context_management),{cuerpo:Buffer.from(JSON.stringify(n),"utf8"),nuestros:o,triggerDelCliente:r}}catch{
|
|
4
|
+
return null}}function $n(t){let e=t!==null&&typeof t=="object"&&!Array.isArray(t)?t.edits:void 0,n=(Array.isArray(e)?e:[]).filter(o=>o!==null&&typeof o=="object"&&!Array.isArray(o)&&o.type===Ue);return xt(
|
|
5
|
+
n)!==xt([Be().edits[0]])}function jn(t){let e=t!==null&&typeof t=="object"&&!Array.isArray(t)?t.edits:void 0,n=(Array.isArray(e)?e:[]).filter(r=>r!==null&&typeof r=="object"&&!Array.isArray(r)&&r.type===
|
|
6
|
+
Ue);if(n.length===0)return null;let o=Number.POSITIVE_INFINITY;for(let r of n){let s=r.trigger,a=s!==null&&typeof s=="object"&&s.type==="input_tokens"&&typeof s.value=="number"&&Number.isFinite(s.value)&&
|
|
7
|
+
s.value>0?s.value:1e5;a<o&&(o=a);}return o}function xt(t){return JSON.stringify(t,(e,n)=>n!==null&&typeof n=="object"&&!Array.isArray(n)?Object.fromEntries(Object.keys(n).sort().map(o=>[o,n[o]])):n)}var Ue="\
|
|
8
|
+
clear_tool_uses_20250919",St="clear_thinking_20251015";function Nn(t){let e=Be().edits[0],n=t!==null&&typeof t=="object"&&!Array.isArray(t)?{...t}:{},o=(Array.isArray(n.edits)?n.edits:[]).filter(a=>a!==
|
|
9
|
+
null&&typeof a=="object"&&!Array.isArray(a)&&a.type!==Ue),r=o.filter(a=>a.type===St),s=o.filter(a=>a.type!==St);return {...n,edits:[...r,...s,e]}}function wt(t,e,n=false){let o=" (rebaja de TTL activa si \
|
|
10
10
|
la licencia trae cache_ttl_tuning; fail-closed)",r=n?" \xB7 DIALES DE ELISI\xD3N ARMADOS A MANO (BVSALA_GATEWAY_DIALES_ELISION=1): miden p\xE9rdida, R=4,05 vs R*=0,0127":" \xB7 diales de elisi\xF3n APAGADOS";
|
|
11
|
-
return
|
|
12
|
-
RTO por defecto (=0 lo cierra)")+o+r,aviso:n}:{linea:"canal S4a: NO SE ABRE \u2014 falta BIVELIO_SERVICE_KEY (sin clave no hay org que consultar); ni rebaja de TTL ni diales"+(
|
|
13
|
-
nal nuevo o exporta la clave y relanza":""),aviso:
|
|
14
|
-
toLowerCase();return
|
|
15
|
-
|
|
16
|
-
tf8"));if(n===null||typeof n!="object"||Array.isArray(n))return null;let o=n;return typeof o.model!="string"||!Array.isArray(o.messages)?null:o}catch{return null}}function
|
|
17
|
-
|
|
18
|
-
bytesFijos:Buffer.byteLength(
|
|
19
|
-
return 1;let o=0;for(;o<
|
|
20
|
-
umbral:n=
|
|
21
|
-
isArray(o)){let r=o;r.ttl==="1h"?(r.ttl="5m",
|
|
22
|
-
let n=Buffer.isBuffer(
|
|
23
|
-
n),"utf8"),rebajadas:o.rebajadas,yaEran5m:o.yaEran5m}}catch{return null}}var
|
|
24
|
-
visto.delete(
|
|
25
|
-
this.visto.delete(r.value);}}get tamano(){return this.visto.size}};var
|
|
26
|
-
return
|
|
27
|
-
return Array.isArray(
|
|
28
|
-
messages;return Array.isArray(r)?(o.messages=[...r,
|
|
29
|
-
includes(
|
|
30
|
-
esfuerzo por turno (D): ARMADO a "${
|
|
11
|
+
return t==="0"?{linea:"canal S4a: CERRADO (BVSALA_GATEWAY_ELISION=0) \u2014 sin rebaja de TTL y sin diales",aviso:false}:e?{linea:(t==="1"?"canal S4a: ABIERTO (BVSALA_GATEWAY_ELISION=1)":"canal S4a: ABIE\
|
|
12
|
+
RTO por defecto (=0 lo cierra)")+o+r,aviso:n}:{linea:"canal S4a: NO SE ABRE \u2014 falta BIVELIO_SERVICE_KEY (sin clave no hay org que consultar); ni rebaja de TTL ni diales"+(t==="1"?". Abre un termi\
|
|
13
|
+
nal nuevo o exporta la clave y relanza":""),aviso:t==="1"}}function At(t){return t===void 0||t.trim()===""?ve:t.split(",").map(n=>n.trim()).filter(n=>n.length>0).includes(ve)?t:`${t},${ve}`}function N(t){let e=t.toLowerCase();return e.startsWith("gpt-")||e.startsWith("o1")||e.startsWith("o3")||e.startsWith("o4")?/^gpt-5\.6/.test(e)?1.25:1:e.startsWith("gemini")?1:1.25}function Ve(t){let e=t.
|
|
14
|
+
toLowerCase();return e.startsWith("claude")||e.startsWith("anthropic/")?2:N(t)}var Bn=.3,Un=4096,Vn=(t,e)=>t==="cache_control"?void 0:e;function Fe(t){return t===void 0?"":JSON.stringify(t,Vn)??""}function Fn(t){return Array.isArray(t)?t.filter(e=>!(e!==null&&typeof e=="object"&&
|
|
15
|
+
e.defer_loading===true)):t}function He(t){return createHash("sha1").update(t).digest("base64url").slice(0,16)}function J(t,e){if(e!==void 0&&e!==""&&e!=="identity")return null;try{let n=JSON.parse(t.toString("u\
|
|
16
|
+
tf8"));if(n===null||typeof n!="object"||Array.isArray(n))return null;let o=n;return typeof o.model!="string"||!Array.isArray(o.messages)?null:o}catch{return null}}function Tt(t){let e=Fe(t.system),n=Fe(
|
|
17
|
+
Fn(t.tools)),o=Array.isArray(t.messages)?t.messages.slice(0,Un):[],r=[],s=[];for(let a of o){let i=Fe(a);r.push(He(i)),s.push(Buffer.byteLength(i,"utf8"));}return {system:He(e),tools:He(n),mensajes:r,bytes:s,
|
|
18
|
+
bytesFijos:Buffer.byteLength(e,"utf8")+Buffer.byteLength(n,"utf8")}}function _t(t,e){if(t===void 0||t.system!==e.system||t.tools!==e.tools)return 1;let n=e.bytesFijos;for(let s of e.bytes)n+=s;if(n<=0)
|
|
19
|
+
return 1;let o=0;for(;o<t.mensajes.length&&o<e.mensajes.length&&t.mensajes[o]===e.mensajes[o];)o++;let r=0;for(let s=o;s<e.bytes.length;s++)r+=e.bytes[s]??0;return r/n}function Ct(t){let{fraccionNueva:e,
|
|
20
|
+
umbral:n=Bn}=t;return e>=n}function qe(t,e){if(t===null||typeof t!="object")return;if(Array.isArray(t)){for(let r of t)qe(r,e);return}let n=t,o=n.cache_control;if(o!==null&&typeof o=="object"&&!Array.
|
|
21
|
+
isArray(o)){let r=o;r.ttl==="1h"?(r.ttl="5m",e.rebajadas++):(r.ttl==="5m"||r.ttl===void 0)&&e.yaEran5m++;}for(let[r,s]of Object.entries(n))r!=="cache_control"&&s!==null&&typeof s=="object"&&qe(s,e);}function Rt(t,e){
|
|
22
|
+
let n=Buffer.isBuffer(t)?J(t,e):t;if(n===null)return null;try{let o={rebajadas:0,yaEran5m:0};for(let r of ["system","messages","tools"])qe(n[r],o);return o.rebajadas===0?null:{cuerpo:Buffer.from(JSON.stringify(
|
|
23
|
+
n),"utf8"),rebajadas:o.rebajadas,yaEran5m:o.yaEran5m}}catch{return null}}var ye=class{constructor(e=512,n=3600*1e3){this.maxEntradas=e;this.maxEdadMs=n;}maxEntradas;maxEdadMs;visto=new Map;ultima(e,n){let o=this.visto.get(e);if(o!==void 0){if(n-o.vistoMs>this.maxEdadMs){this.
|
|
24
|
+
visto.delete(e);return}return o.huella}}anotar(e,n,o){for(this.visto.delete(e),this.visto.set(e,{huella:n,vistoMs:o});this.visto.size>this.maxEntradas;){let r=this.visto.keys().next();if(r.done===true)break;
|
|
25
|
+
this.visto.delete(r.value);}}get tamano(){return this.visto.size}};var It="mid-conversation-output-config-2026-07-01",Je=["low","medium","high","xhigh","max"],Hn=new Set(["claude-fable-5-1","claude-mythos-5-1","claude-opus-5"]);function qn(t){return Hn.has(t)}function Ge(t){
|
|
26
|
+
return t!==void 0&&Je.includes(t)}function Kn(t){return {role:"system",content:[],output_config:{effort:t}}}function Jn(t){if(t.output_config!==void 0&&t.output_config!==null)return true;let e=t.messages;
|
|
27
|
+
return Array.isArray(e)?e.some(n=>typeof n=="object"&&n!==null&&n.output_config!==void 0):false}function Pt(t,e,n){let o=J(t,n);if(o===null||typeof o.model!="string"||!qn(o.model)||Jn(o))return null;let r=o.
|
|
28
|
+
messages;return Array.isArray(r)?(o.messages=[...r,Kn(e)],{cuerpo:Buffer.from(JSON.stringify(o),"utf8"),nivel:e}):null}function Ot(t){let e=(t??"").split(",").map(n=>n.trim()).filter(Boolean);return e.
|
|
29
|
+
includes(It)||e.push(It),e.join(",")}function Dt(t,e,n){return t===void 0||t===""?{linea:`esfuerzo por turno (D): APAGADO (BVSALA_GATEWAY_ESFUERZO=${Je.join("|")} lo arma)`,aviso:false}:Ge(t)?e?n?{linea:`\
|
|
30
|
+
esfuerzo por turno (D): ARMADO a "${t}" (activo si la licencia trae per_turn_effort; fail-closed). Solo fable-5-1, mythos-5-1 y opus-5; el resto pasa intacto. NO reinicia la cach\xE9 de prefijo: el dial \
|
|
31
31
|
se a\xF1ade al final, no reescribe nada anterior`,aviso:false}:{linea:"esfuerzo por turno (D): NO SE ARMA \u2014 el canal S4a est\xE1 CERRADO (BVSALA_GATEWAY_ELISION=0 apaga las palancas)",aviso:true}:{linea:"\
|
|
32
32
|
esfuerzo por turno (D): NO SE ARMA \u2014 falta BIVELIO_SERVICE_KEY (sin clave no hay org que consultar). Abre un terminal nuevo o exporta la clave y relanza",aviso:true}:{linea:`esfuerzo por turno (D):\
|
|
33
|
-
NO SE ARMA \u2014 "${
|
|
33
|
+
NO SE ARMA \u2014 "${t}" no es un nivel. Usa uno de: ${Je.join(", ")}`,aviso:true}}var xe={"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},
|
|
34
34
|
"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,
|
|
35
35
|
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},
|
|
36
36
|
"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},
|
|
@@ -47,245 +47,255 @@ able-5":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:.001},"claude-fable-5-1
|
|
|
47
47
|
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,
|
|
48
48
|
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\
|
|
49
49
|
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,
|
|
50
|
-
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
|
|
51
|
-
if(!n)return;let o=
|
|
52
|
-
"."&&c!=="_")continue;let m=s.slice(i.length+1);if(!(/^\d/.test(m)&&!/^\d{4}/.test(m)))return
|
|
53
|
-
|
|
54
|
-
n.inputPer1k;return (o.cachedInputPer1k??o.inputPer1k)<r}function
|
|
55
|
-
function
|
|
56
|
-
|
|
57
|
-
s])=>`${r}\u2192${s}`).join(", ");return
|
|
50
|
+
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 We(t,e,n){
|
|
51
|
+
if(!n)return;let o=t[n];if(o)return o;let r=n.lastIndexOf("/"),s=r>=0?n.slice(r+1):n,a=t[s];if(a)return a;for(let i of e){if(!s.startsWith(i))continue;let c=s.charAt(i.length);if(c!==""&&c!=="-"&&c!==
|
|
52
|
+
"."&&c!=="_")continue;let m=s.slice(i.length+1);if(!(/^\d/.test(m)&&!/^\d{4}/.test(m)))return t[i]}}function Ye(t){return Object.keys(t).sort((e,n)=>n.length-e.length)}var Mt=Ye(xe);function L(t){return We(
|
|
53
|
+
xe,Mt,t)}var Gn=Object.fromEntries(Object.keys(xe).map(t=>[t,t]));function Lt(t){return We(Gn,Mt,t)}var $t={"claude-fable-5":"claude-fable-5-1"};function Wn(t,e){let n=L(t),o=L(e);if(n===void 0||o===void 0||n.inputPer1k!==o.inputPer1k||n.outputPer1k!==o.outputPer1k||N(t)!==N(e))return false;let r=n.cachedInputPer1k??
|
|
54
|
+
n.inputPer1k;return (o.cachedInputPer1k??o.inputPer1k)<r}function Yn(t){let e=Lt(t);if(e===void 0||e!==t)return null;let n=$t[e];return n===void 0||n===e||!Wn(e,n)?null:{solicitado:t,servido:n}}var Qn=/(^|,)\s*context-1m/i;
|
|
55
|
+
function Xn(t){let e=t.tool_choice;if(e===null||typeof e!="object")return false;let n=e.type;return n==="any"||n==="tool"}function jt(t,e,n={}){if(n.betas!==void 0&&Qn.test(n.betas))return null;let o=J(t,
|
|
56
|
+
e);if(o===null||Xn(o))return null;let r=Yn(o.model);return r===null?null:(o.model=r.servido,{cuerpo:Buffer.from(JSON.stringify(o),"utf8"),cambio:r})}function Nt(t,e,n){let o=Object.entries($t).map(([r,
|
|
57
|
+
s])=>`${r}\u2192${s}`).join(", ");return t!=="1"?{linea:"modelo hermano (C): APAGADO (BVSALA_GATEWAY_MODELO_HERMANO=1 lo arma)",aviso:false}:e?n?{linea:`modelo hermano (C): ARMADO (${o}; activo si la lic\
|
|
58
58
|
encia trae sibling_model_routing; fail-closed). Cambia el model que ves en la respuesta; lectura de cach\xE9 a 0,025\xD7 en vez de 0,1\xD7 (cat\xE1logo). Encendido a mitad de un hilo paga una escritura fr\xEDa del p\
|
|
59
59
|
refijo una vez. Si el proveedor rechaza (400) la petici\xF3n reescrita, se reenv\xEDa intacta una vez`,aviso:false}:{linea:"modelo hermano (C): NO SE ARMA \u2014 el canal S4a est\xE1 CERRADO (BVSALA_GATEWAY_ELIS\
|
|
60
60
|
ION=0 apaga las tres palancas)",aviso:true}:{linea:"modelo hermano (C): NO SE ARMA \u2014 falta BIVELIO_SERVICE_KEY (sin clave no hay org que consultar). Abre un terminal nuevo o exporta la clave y relanza",
|
|
61
|
-
aviso:true}}var
|
|
62
|
-
|
|
61
|
+
aviso:true}}var zt=new Set;function O(t,e){zt.has(t)||(zt.add(t),console.warn(e));}var G="0.4.21",Bt="x-bvsala-version";var ee=class{options;now;flushIntervalMs;maxBatch;maxBuffer;buffer=[];seatId;ci;timer;inflight=null;fallosSeguidos=0;constructor(e){this.options=e,this.now=e.now??(()=>Date.now()),this.flushIntervalMs=
|
|
62
|
+
e.flushIntervalMs??15e3,this.maxBatch=e.maxBatch??50,this.maxBuffer=e.maxBuffer??1e3,this.ci=e.ci??false;}setSeat(e,n){e&&(this.seatId=e),this.ci=n;}record(e){this.buffer.push({report:e,at:this.now()}),this.
|
|
63
63
|
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.
|
|
64
|
-
flushIntervalMs),this.timer.unref?.());}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0),this.flush();}async stopAndDrain(
|
|
64
|
+
flushIntervalMs),this.timer.unref?.());}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0),this.flush();}async stopAndDrain(e){this.timer&&(clearInterval(this.timer),this.timer=void 0);let n=e??
|
|
65
65
|
Math.ceil(this.maxBuffer/this.maxBatch)+4,o=0;for(let r=0;r<n&&this.buffer.length>0;r++){let s=this.buffer.length;if(await this.flush(),o=this.buffer.length>=s?o+1:0,o>=2)break}}async flush(){if(this.
|
|
66
|
-
inflight)return this.inflight;if(this.buffer.length!==0){this.inflight=this.hacerFlush();try{await this.inflight;}finally{this.inflight=null;}}}async hacerFlush(){let
|
|
67
|
-
fetch;if(!
|
|
68
|
-
er ${this.options.serviceAccountKey}`,[
|
|
69
|
-
`el servidor respondi\xF3 ${r.status}`)):r.status===401||r.status===403?(
|
|
66
|
+
inflight)return this.inflight;if(this.buffer.length!==0){this.inflight=this.hacerFlush();try{await this.inflight;}finally{this.inflight=null;}}}async hacerFlush(){let e=this.options.fetchImpl??globalThis.
|
|
67
|
+
fetch;if(!e)return;let n=this.buffer.splice(0,this.maxBatch);try{let o=n.map(s=>this.toWire(s)),r=await e(this.options.url,{method:"POST",headers:{"content-type":"application/json",authorization:`Bear\
|
|
68
|
+
er ${this.options.serviceAccountKey}`,[Bt]:`${this.options.surface??"sdk"}/${G}`},body:JSON.stringify(o)});r.ok?this.fallosSeguidos=0:r.status>=500?(this.fallosSeguidos++,this.requeue(n),this.avisarDeFallo(
|
|
69
|
+
`el servidor respondi\xF3 ${r.status}`)):r.status===401||r.status===403?(O(`metering-auth-${r.status}`,`[bv-sala] el env\xEDo de uso est\xE1 siendo rechazado con HTTP ${r.status} en ${this.options.url}\
|
|
70
70
|
. Revisa 'serviceAccountKey' (\xBFrotada? \xBFrevocada? \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.`),
|
|
71
71
|
this.options.onAuthError?.(r.status)):(this.fallosSeguidos++,this.avisarDeFallo(r.status===404||r.status===405?`HTTP ${r.status}: la URL de env\xEDo parece equivocada`:`el servidor rechaz\xF3 el lote con\
|
|
72
|
-
HTTP ${r.status}`));}catch(o){this.fallosSeguidos++,this.requeue(n),this.avisarDeFallo(o instanceof Error?o.message:"error de red");}}avisarDeFallo(
|
|
73
|
-
fallosSeguidos;n<3||(n-3)%12!==0||console.warn(`[bv-sala] el env\xEDo de uso lleva ${n} intentos seguidos fallando contra ${this.options.url} (${
|
|
74
|
-
est\xE1 llegando: el panel dir\xE1 que no ve tr\xE1fico y los asientos facturables saldr\xE1n a cero. Comprueba 'meteringUrl' \u2014 por defecto es \`\${licenseServerUrl}/api/metering/usage\`.`);}requeue(
|
|
75
|
-
this.buffer=[...
|
|
76
|
-
{},...this.ci?{ci:true}:{},requestId:n.requestId,model:n.model,at:
|
|
72
|
+
HTTP ${r.status}`));}catch(o){this.fallosSeguidos++,this.requeue(n),this.avisarDeFallo(o instanceof Error?o.message:"error de red");}}avisarDeFallo(e){if(this.options.silenceWarnings)return;let n=this.
|
|
73
|
+
fallosSeguidos;n<3||(n-3)%12!==0||console.warn(`[bv-sala] el env\xEDo de uso lleva ${n} intentos seguidos fallando contra ${this.options.url} (${e}). Las peticiones SIGUEN funcionando, pero el uso no \
|
|
74
|
+
est\xE1 llegando: el panel dir\xE1 que no ve tr\xE1fico y los asientos facturables saldr\xE1n a cero. Comprueba 'meteringUrl' \u2014 por defecto es \`\${licenseServerUrl}/api/metering/usage\`.`);}requeue(e){
|
|
75
|
+
this.buffer=[...e,...this.buffer],this.buffer.length>this.maxBuffer&&(this.buffer.length=this.maxBuffer);}toWire(e){let n=e.report;return {orgId:this.options.orgId??"self",...this.seatId?{seatId:this.seatId}:
|
|
76
|
+
{},...this.ci?{ci:true}:{},requestId:n.requestId,model:n.model,at:e.at,avoidedLlm:n.calls.avoidedLlm,actualLlm:n.calls.actualLlm,baselineInputTokens:n.tokens.baselineInput,actualInputTokens:n.tokens.actualInput,
|
|
77
77
|
eliminatedInputTokens:n.tokens.eliminatedInput,compressedInputTokens:n.tokens.compressedInput,baselineOutputTokens:n.tokens.baselineOutput,actualOutputTokens:n.tokens.actualOutput,providerCachedInputTokens:n.
|
|
78
78
|
tokens.providerCachedInput??0,cacheResult:n.cache.result,...n.cost.eliminatedInputFloorCost!==void 0&&Number.isFinite(n.cost.eliminatedInputFloorCost)&&n.cost.eliminatedInputFloorCost>0&&n.tokens.eliminatedInput>
|
|
79
79
|
0?{eliminatedInputFloorCost:n.cost.eliminatedInputFloorCost}:{},baselineCost:n.cost.baselineEstimate,actualCost:n.cost.actual,netSavings:n.cost.netSavings,...n.cost.basis?{basis:n.cost.basis}:{},...n.
|
|
80
|
-
attribution?.sessionId?{sessionId:n.attribution.sessionId}:{},...n.attribution?.agentId?{agentId:n.attribution.agentId}:{}}}};function
|
|
81
|
-
]";return new RegExp(`-${
|
|
82
|
-
|
|
83
|
-
if(
|
|
84
|
-
|
|
85
|
-
ONS","GITLAB_CI","CIRCLECI","TRAVIS","JENKINS_URL","BUILDKITE","TF_BUILD","TEAMCITY_VERSION","BITBUCKET_BUILD_NUMBER","CODEBUILD_BUILD_ID","HEROKU_TEST_RUN_ID","DRONE"];function
|
|
86
|
-
return false;for(let
|
|
87
|
-
o.encode(
|
|
88
|
-
|${
|
|
89
|
-
if(!o)return;let r=await
|
|
80
|
+
attribution?.sessionId?{sessionId:n.attribution.sessionId}:{},...n.attribution?.agentId?{agentId:n.attribution.agentId}:{}}}};function Se(){return globalThis.process}function Zn(t){if(/^[0-9a-f]{12}$/.test(t)||/^\d{1,3}(\.\d{1,3}){3}$/.test(t)||/^ip-\d{1,3}(-\d{1,3}){3}$/i.test(t))return true;let e="[bcdfghjklmnpqrstvwxz2456789\
|
|
81
|
+
]";return new RegExp(`-${e}{8,10}-${e}{5}$`).test(t)}function eo(t){return !!(t.AWS_LAMBDA_FUNCTION_NAME??t.LAMBDA_TASK_ROOT??t.VERCEL??t.VERCEL_ENV??t.K_SERVICE??t.FUNCTION_TARGET??t.FUNCTIONS_WORKER_RUNTIME??
|
|
82
|
+
t.NETLIFY)}async function to(){if(Se()?.execPath)try{let e=await import(["node","os"].join(":")),n=typeof e.hostname=="function"?e.hostname():"";return n.length>0?n:void 0}catch{return}}async function no(t,e=to){
|
|
83
|
+
if(t.KUBERNETES_SERVICE_HOST||eo(t))return;let n=t.HOSTNAME??t.COMPUTERNAME??await e();if(!(!n||Zn(n)))return n}async function oo(){let t=Se();if(!t||!t.env)return;let e=t.env,n=await no(e),o=[t.platform,
|
|
84
|
+
t.arch,t.execPath,n,e.USER??e.USERNAME??e.LOGNAME,e.HOME??e.USERPROFILE].filter(r=>typeof r=="string"&&r.length>0);return o.length?o.join("|"):void 0}var ro=["CI","CONTINUOUS_INTEGRATION","GITHUB_ACTI\
|
|
85
|
+
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 t=Se()?.env;if(!t)
|
|
86
|
+
return false;for(let e of ro){let n=t[e];if(n&&n!=="false"&&n!=="0")return true}return false}async function so(t,e){let n=globalThis.crypto,o=new TextEncoder;if(n?.subtle)try{let a=await n.subtle.importKey("raw",
|
|
87
|
+
o.encode(t),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),i=await n.subtle.sign("HMAC",a,o.encode(e));return [...new Uint8Array(i)].map(c=>c.toString(16).padStart(2,"0")).join("")}catch{}let r=2166136261,s=`${t}\
|
|
88
|
+
|${e}`;for(let a=0;a<s.length;a++)r^=s.charCodeAt(a),r=Math.imul(r,16777619);return (r>>>0).toString(16).padStart(8,"0")}async function we(t){let n=Se()?.env?.BVSALA_SEAT_ID;if(n&&ao.test(n))return n;let o=await oo();
|
|
89
|
+
if(!o)return;let r=await so(t,o);if(r)return `m-${r.slice(0,32)}`}var ao=/^[A-Za-z0-9._:/-]{1,128}$/;var W=class{resto="";uso=null;elisionObservada=null;eventos={};observar(e){this.resto+=typeof e=="string"?e:e.toString("utf8");let n;for(;(n=this.resto.indexOf(`
|
|
90
90
|
|
|
91
91
|
`))>=0;){let o=this.resto.slice(0,n);this.resto=this.resto.slice(n+2);let r=/^event: (.+)$/m.exec(o)?.[1];if(r&&(this.eventos[r]=(this.eventos[r]??0)+1),r!=="message_start"&&r!=="message_delta")continue;
|
|
92
|
-
let s=/^data: (.+)$/m.exec(o)?.[1];if(s)try{let a=JSON.parse(s),i=
|
|
92
|
+
let s=/^data: (.+)$/m.exec(o)?.[1];if(s)try{let a=JSON.parse(s),i=Ut(a.context_management);i&&(this.elisionObservada=i);let c=a.usage??a.message?.usage;if(c){let m=c.cache_creation||this.uso?.cache_creation?
|
|
93
93
|
{...this.uso?.cache_creation,...c.cache_creation}:void 0;this.uso={...this.uso,...c,...m?{cache_creation:m}:{}};}}catch{}}}usage(){return this.uso}usageFinal(){return (this.eventos.message_delta??0)>0?this.
|
|
94
|
-
uso:null}elision(){return this.elisionObservada}};function
|
|
95
|
-
n)||n<=0?0:
|
|
96
|
-
cleared_input_tokens;typeof s=="number"&&Number.isFinite(s)&&s>0&&(n+=s,r.type==="clear_tool_uses_20250919"&&(o+=s));}return {borrados:
|
|
97
|
-
try{let
|
|
98
|
-
|
|
94
|
+
uso:null}elision(){return this.elisionObservada}};function io(t,e){if(!e||e.atribuible!==true||!(e.tokensLimpiadosToolUses>0))return 0;let n=t.cachedInputPer1k;return typeof n!="number"||!Number.isFinite(
|
|
95
|
+
n)||n<=0?0:e.tokensLimpiadosToolUses/1e3*n}function Ut(t){if(t===null||typeof t!="object")return null;let e=t.applied_edits;if(!Array.isArray(e)||e.length===0)return null;let n=0,o=0;for(let r of e){let s=r.
|
|
96
|
+
cleared_input_tokens;typeof s=="number"&&Number.isFinite(s)&&s>0&&(n+=s,r.type==="clear_tool_uses_20250919"&&(o+=s));}return {borrados:e.length,tokensLimpiados:n,tokensLimpiadosToolUses:o}}function Vt(t){
|
|
97
|
+
try{let e=JSON.parse(typeof t=="string"?t:t.toString("utf8"));return Ut(e.context_management)}catch{return null}}var Ae=class{resto="";uso=null;eventos={};observar(e){this.resto+=typeof e=="string"?e:
|
|
98
|
+
e.toString("utf8");let n;for(;(n=this.resto.indexOf(`
|
|
99
99
|
|
|
100
100
|
`))>=0;){let o=this.resto.slice(0,n);this.resto=this.resto.slice(n+2);let r=/^event: (.+)$/m.exec(o)?.[1];r&&(this.eventos[r]=(this.eventos[r]??0)+1);let s=/^data: (.+)$/m.exec(o)?.[1];if(s)try{let a=JSON.
|
|
101
|
-
parse(s);if((r??a.type)!=="response.completed")continue;let i=a.response?.usage;i&&(this.uso=
|
|
102
|
-
0),n=Math.min(Math.max(0,
|
|
103
|
-
0),cache_read_input_tokens:n,cache_creation_input_tokens:o}}function
|
|
104
|
-
1e3*
|
|
105
|
-
0,a=
|
|
106
|
-
cacheEscrita:i,cacheEscrita1h:c};return {costeUsd
|
|
107
|
-
"").trim().toLowerCase()){case "gzip":case "x-gzip":n=
|
|
108
|
-
if(typeof r!="function")return null;n=r(
|
|
109
|
-
function
|
|
110
|
-
true,o)}function
|
|
111
|
-
baselineOutput:0,actualOutput:0,providerCachedInput:0},cache:{result:"miss"},cost:{baselineEstimate:n,actual:o,netSavings:n>0?Math.max(-100,Math.min(1,(n-o)/n)):0,basis:"shadow"}}}function
|
|
112
|
-
|
|
113
|
-
n.tokens.cacheEscrita1h,
|
|
101
|
+
parse(s);if((r??a.type)!=="response.completed")continue;let i=a.response?.usage;i&&(this.uso=co(i));}catch{}}}usage(){return this.uso}usageFinal(){return this.uso}};function co(t){let e=Math.max(0,t.input_tokens??
|
|
102
|
+
0),n=Math.min(Math.max(0,t.input_tokens_details?.cached_tokens??0),e),o=Math.min(Math.max(0,t.input_tokens_details?.cache_write_tokens??0),e-n);return {input_tokens:e-n-o,output_tokens:Math.max(0,t.output_tokens??
|
|
103
|
+
0),cache_read_input_tokens:n,cache_creation_input_tokens:o}}function Ft(t,e,n){let o=t.cachedInputPer1k??t.inputPer1k;return e.entrada/1e3*t.inputPer1k+e.cacheLeida/1e3*o+(e.cacheEscrita-e.cacheEscrita1h)/
|
|
104
|
+
1e3*t.inputPer1k*N(n)+e.cacheEscrita1h/1e3*t.inputPer1k*2+e.salida/1e3*t.outputPer1k}function Ht(t,e){let n=L(t);if(!n)return null;let o=e.input_tokens??0,r=e.output_tokens??0,s=e.cache_read_input_tokens??
|
|
105
|
+
0,a=e.cache_creation,i=e.cache_creation_input_tokens??(a?.ephemeral_5m_input_tokens??0)+(a?.ephemeral_1h_input_tokens??0),c=Math.min(a?.ephemeral_1h_input_tokens??0,i),m={entrada:o,salida:r,cacheLeida:s,
|
|
106
|
+
cacheEscrita:i,cacheEscrita1h:c};return {costeUsd:Ft(n,m,t),precio:n,tokens:m}}function qt(t,e){let o=Qe(t,e)?.model;return typeof o=="string"?o:""}function Qe(t,e){try{let n=t,o={maxOutputLength:lo};switch((e??
|
|
107
|
+
"").trim().toLowerCase()){case "gzip":case "x-gzip":n=z.gunzipSync(t,o);break;case "deflate":n=z.inflateSync(t,o);break;case "br":n=z.brotliDecompressSync(t,o);break;case "zstd":{let r=z.zstdDecompressSync;
|
|
108
|
+
if(typeof r!="function")return null;n=r(t,o);break}default:break}return JSON.parse(n.toString("utf8"))}catch{return null}}var lo=5*1024*1024;function Kt(){return typeof z.zstdDecompressSync=="function"}
|
|
109
|
+
function Xe(t){try{return JSON.parse(typeof t=="string"?t:t.toString("utf8")).usage??null}catch{return null}}function Jt(t,e,n,o,r,s,a){return Yt(t,e,n,false,o,r,s,a)}function Gt(t,e,n,o){return Yt(t,e,n,
|
|
110
|
+
true,o)}function Wt(t,e,n,o,r){return {requestId:t,model:e,...r&&(r.sessionId||r.agentId)?{attribution:r}:{},calls:{avoidedLlm:0,actualLlm:0},tokens:{baselineInput:0,actualInput:0,eliminatedInput:0,compressedInput:0,
|
|
111
|
+
baselineOutput:0,actualOutput:0,providerCachedInput:0},cache:{result:"miss"},cost:{baselineEstimate:n,actual:o,netSavings:n>0?Math.max(-100,Math.min(1,(n-o)/n)):0,basis:"shadow"}}}function uo(t,e){let n=L(
|
|
112
|
+
t.solicitado);return n===void 0?0:Math.max(0,Ft(n,e.tokens,t.solicitado)-e.costeUsd)}function Yt(t,e,n,o,r,s,a,i){let c=n.tokens.entrada+n.tokens.cacheLeida+n.tokens.cacheEscrita,m=n.tokens.cacheEscrita-
|
|
113
|
+
n.tokens.cacheEscrita1h,g=!o&&a&&a.rebajadas>0&&a.yaEran5m===0&&m>0?m/1e3*n.precio.inputPer1k*(2-1.25):0,u=!o&&i?uo(i,n):0,h=n.costeUsd+g+u,k=g+u,l=o?0:io(n.precio,s);return {requestId:t,model:e,...r&&
|
|
114
114
|
(r.sessionId||r.agentId)?{attribution:r}:{},calls:o?{avoidedLlm:1,actualLlm:0}:{avoidedLlm:0,actualLlm:1},tokens:{baselineInput:c,actualInput:o?0:c,eliminatedInput:o?0:s?.tokensLimpiados??0,compressedInput:0,
|
|
115
115
|
baselineOutput:n.tokens.salida,actualOutput:o?0:n.tokens.salida,providerCachedInput:o?0:n.tokens.cacheLeida},cache:{result:o?"singleflight":"miss"},cost:o?{baselineEstimate:n.costeUsd,actual:0,netSavings:1,
|
|
116
|
-
basis:"estimated"}:{baselineEstimate:h,actual:n.costeUsd,netSavings:h>0?Math.max(-100,Math.min(1,
|
|
117
|
-
function
|
|
118
|
-
|
|
119
|
-
`):""}var
|
|
120
|
-
`),n=Math.max(1,
|
|
121
|
-
test(i)||/\b(INFO|DEBUG|TRACE|WARN|ERROR)\b/.test(i))&&(s+=1);}return o/n>.25?"diff":s/n>.3?"log":r/n>.08?"codigo":"otro"}function
|
|
116
|
+
basis:"estimated"}:{baselineEstimate:h,actual:n.costeUsd,netSavings:h>0?Math.max(-100,Math.min(1,k/h)):0,basis:"measured",...l>0?{eliminatedInputFloorCost:l}:{}}}}var po=1024,de=120,mo=8,fo=256*1024,ho=/error|exception|traceback|warn|fatal|fail|panic|assert|denied|refused|timeout|\bat\s+\S+:\d+/i,Zt=/^\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)/;
|
|
117
|
+
function go(t){return Buffer.byteLength(typeof t=="string"?t:JSON.stringify(t??""))}function bo(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?
|
|
118
|
+
e.text:"").join(`
|
|
119
|
+
`):""}var vo=/^\s*\d+[\t→]/;function en(t){return t.replace(vo,"")}function yo(t){if(!t)return "otro";let e=t.split(`
|
|
120
|
+
`),n=Math.max(1,e.length),o=0,r=0,s=0;for(let a of e){let i=en(a);(/^[+-](?![+-])/.test(i)||i.startsWith("@@")||i.startsWith("diff --git"))&&(o+=1),Zt.test(i)&&(r+=1),(/^\s*(\d{4}-\d{2}-\d{2}|\[\d|\d{2}:\d{2}:\d{2})/.
|
|
121
|
+
test(i)||/\b(INFO|DEBUG|TRACE|WARN|ERROR)\b/.test(i))&&(s+=1);}return o/n>.25?"diff":s/n>.3?"log":r/n>.08?"codigo":"otro"}function ko(t,e){if(e==="diff"||e==="otro")return Buffer.byteLength(t);let n=t.
|
|
122
122
|
split(`
|
|
123
|
-
`),o=new Set;for(let s=0;s<n.length;s++){let a=
|
|
124
|
-
n[s])+1;return Math.min(r,Buffer.byteLength(
|
|
125
|
-
n:${JSON.stringify(
|
|
126
|
-
function
|
|
127
|
-
|
|
128
|
-
let i=r;a.esError=i.is_error===true;let c=
|
|
129
|
-
n("tools",o);if(Array.isArray(
|
|
123
|
+
`),o=new Set;for(let s=0;s<n.length;s++){let a=en(n[s]);(e==="log"?ho.test(a):Zt.test(a))&&(o.add(s),e==="log"&&(s>0&&o.add(s-1),s<n.length-1&&o.add(s+1)));}let r=de;for(let s of o)r+=Buffer.byteLength(
|
|
124
|
+
n[s])+1;return Math.min(r,Buffer.byteLength(t))}var xo=(t,e)=>t==="cache_control"?void 0:e;function So(t){if(typeof t=="string")return `text:${t}`;if(!t||typeof t!="object"||Array.isArray(t))return `jso\
|
|
125
|
+
n:${JSON.stringify(t??"")}`;let e=t;return e.type==="text"&&typeof e.text=="string"&&Object.keys(e).every(n=>n==="type"||n==="text"||n==="cache_control")?`text:${e.text}`:`json:${JSON.stringify(e,xo)}`}
|
|
126
|
+
function Eo(t){return createHash("sha256").update(So(t)).digest("hex").slice(0,16)}function wo(t){if(!t||typeof t!="object"||Array.isArray(t))return null;let e=t.cache_control;return !e||typeof e!="object"?null:
|
|
127
|
+
e.ttl==="1h"?"1h":"5m"}function tn(t){let e=[],n=(o,r)=>{let s=go(r),a={clave:Eo(r),tipo:o,marca:wo(r),bytes:s,bytesV1:s,clase:"otro",esError:false};if(o.endsWith(":tool_result")&&r&&typeof r=="object"){
|
|
128
|
+
let i=r;a.esError=i.is_error===true;let c=bo(i.content);a.clase=yo(c);let m=s-Buffer.byteLength(c);a.bytesV1=Math.min(s,Math.max(0,m)+ko(c,a.clase));}e.push(a);};if(Array.isArray(t.tools))for(let o of t.tools)
|
|
129
|
+
n("tools",o);if(Array.isArray(t.system))for(let o of t.system)n("system",o);else (t.system??void 0)!==void 0&&n("system",t.system);for(let o of Array.isArray(t.messages)?t.messages:[]){if(!o||typeof o!=
|
|
130
130
|
"object"){n("?:invalido",o);continue}let r=o,s=typeof r.role=="string"?r.role:"?";if(typeof r.content=="string")n(`${s}:text`,r.content);else if(Array.isArray(r.content))for(let a of r.content)n(`${s}\
|
|
131
|
-
:${a?.type??"?"}`,a);}return
|
|
132
|
-
return n}function
|
|
133
|
-
h))return {clave:
|
|
134
|
-
|
|
135
|
-
var
|
|
136
|
-
o:null}escribir(
|
|
137
|
-
|
|
138
|
-
value;if(n===void 0)break;this.entradas.delete(n);}}};function
|
|
139
|
-
"|").update(
|
|
140
|
-
t");a&&s===o||(n+=1),o=a?s:"",
|
|
141
|
-
5m";hayPrevio=false;atPrevio=0;acumulado=
|
|
142
|
-
s,this.previoUltimoBp=-1,this.previoTtl="5m",this.hayPrevio=true,this.atPrevio=
|
|
143
|
-
|
|
144
|
-
n.tokensEntrada+=
|
|
145
|
-
n.tokensEntrada,this.acumulado.entradaUsd+=n.entradaUsd,this.acumulado.totalUsd+=n.totalUsd,n}let
|
|
146
|
-
|
|
147
|
-
[]:this.previo.slice(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
atPrevio=
|
|
131
|
+
:${a?.type??"?"}`,a);}return e}function Ao(){return {nacimiento:new Map,turno:0,elididosV2m:new Set}}function To(t,e){let n=t.turno++;for(let o of e)t.nacimiento.has(o.clave)||t.nacimiento.set(o.clave,n);
|
|
132
|
+
return n}function nn(t,e,n,o,r=fo){let s=e.reduce((u,h,k)=>h.tipo.endsWith(":tool_result")?k:u,-1),a=(u,h)=>u.tipo.endsWith(":tool_result")&&u.bytes>=po&&h!==s;return e.map((u,h)=>{if(!a(u,
|
|
133
|
+
h))return {clave:u.clave,bytes:u.bytes};let k=o-(n.nacimiento.get(u.clave)??o);return k>=2&&k*u.bytes/1024>=mo?{clave:`${u.clave}:e`,bytes:de}:{clave:u.clave,bytes:u.bytes}});}function _o(t){let e=L(t);return e?{inputPer1k:e.inputPer1k,lecturaPer1k:e.cachedInputPer1k??e.inputPer1k,escrituraPer1k:e.inputPer1k*
|
|
134
|
+
N(t),escritura1hPer1k:e.inputPer1k*Ve(t)}:null}function Qt(){return {lecturaUsd:0,escrituraUsd:0,entradaUsd:0,totalUsd:0,tokensLeidos:0,tokensEscritos:0,tokensEntrada:0,tokensInvalidados:0,invalidacionUsd:0}}
|
|
135
|
+
var et={"1h":36e5,"5m":3e5},Co=20,Ro=6e3,Io=2e4,te=class{constructor(e=Io){this.tope=e;}tope;entradas=new Map;get size(){return this.entradas.size}viva(e,n){let o=this.entradas.get(e);return o&&n<=o.expira?
|
|
136
|
+
o:null}escribir(e,n,o){this.entradas.delete(e),this.entradas.set(e,{expira:n+et[o],ttl:o}),this.entradas.size>this.tope&&this.podar(n);}refrescar(e,n){let o=this.entradas.get(e);o&&(this.entradas.delete(
|
|
137
|
+
e),this.entradas.set(e,{expira:n+et[o.ttl],ttl:o.ttl}));}podar(e){for(let[n,o]of this.entradas)e>o.expira&&this.entradas.delete(n);for(;this.entradas.size>this.tope;){let n=this.entradas.keys().next().
|
|
138
|
+
value;if(n===void 0)break;this.entradas.delete(n);}}};function Po(t,e){let n=new Array(e.length),o=createHash("sha256").update(`model:${t}`).digest("hex");for(let r=0;r<e.length;r++)o=createHash("sha256").update(o).update(
|
|
139
|
+
"|").update(e[r]).digest("hex").slice(0,32),n[r]=o;return n}function Oo(t){let e=new Array(t.length),n=-1,o="";for(let r=0;r<t.length;r++){let s=t[r],a=s.endsWith(":tool_use")||s.endsWith(":tool_resul\
|
|
140
|
+
t");a&&s===o||(n+=1),o=a?s:"",e[r]=n;}return e}function Xt(t,e){return t.endsWith(":image")?Math.min(e,Ro):e}var pe=class{constructor(e,n){this.transformar=e;this.cache=n??new te;}transformar;estado=Ao();cache;previo=[];previoUltimoBp=-1;previoTtl="\
|
|
141
|
+
5m";hayPrevio=false;atPrevio=0;acumulado=Qt();paso(e){let n=Qt(),o=To(this.estado,e.bloques),r=_o(e.model),s=this.transformar(e.bloques,this.estado,o);if(!r||e.entradaReal<=0||s.length===0)return this.previo=
|
|
142
|
+
s,this.previoUltimoBp=-1,this.previoTtl="5m",this.hayPrevio=true,this.atPrevio=e.at,n;let a=s.map((d,b)=>e.bloques[b]?.tipo??""),i=s.map((d,b)=>e.bloques[b]?.marca??null),c=e.bloques.reduce((d,b)=>d+Xt(
|
|
143
|
+
b.tipo,b.bytes),0),m=c>0?e.entradaReal/c:0,g=s.map((d,b)=>Xt(a[b],d.bytes)*m),u=Po(e.model,s.map(d=>d.clave)),h=Oo(a),k=i.map((d,b)=>d?b:-1).filter(d=>d>=0);if(k.length===0){for(let d=0;d<s.length;d++)
|
|
144
|
+
n.tokensEntrada+=g[d],n.entradaUsd+=g[d]/1e3*r.inputPer1k;return n.totalUsd=n.entradaUsd,this.previo=s,this.previoUltimoBp=-1,this.previoTtl="5m",this.hayPrevio=true,this.atPrevio=e.at,this.acumulado.tokensEntrada+=
|
|
145
|
+
n.tokensEntrada,this.acumulado.entradaUsd+=n.entradaUsd,this.acumulado.totalUsd+=n.totalUsd,n}let l=-1;for(let d of k){let b=h[d]-(Co-1);for(let x=d;x>=0&&h[x]>=b;x--)if(this.cache.viva(u[x],e.at)){x>
|
|
146
|
+
l&&(l=x);break}}for(let d=0;d<=l;d++)this.cache.refrescar(u[d],e.at);let p=k[k.length-1];for(let d of k)d>l&&this.cache.escribir(u[d],e.at,i[d]);let S=0,w=this.hayPrevio&&e.at-this.atPrevio>et[this.previoTtl]?
|
|
147
|
+
[]:this.previo.slice(l+1,this.previoUltimoBp+1),C=0;for(let d=0;d<s.length;d++){let b=s[d],x=g[d];if(d<=l){n.tokensLeidos+=x,n.lecturaUsd+=x/1e3*r.lecturaPer1k;continue}if(d>p){n.tokensEntrada+=x,n.entradaUsd+=
|
|
148
|
+
x/1e3*r.inputPer1k;continue}for(;k[S]<d;)S+=1;let H=i[k[S]]==="1h"?r.escritura1hPer1k:r.escrituraPer1k;n.tokensEscritos+=x,n.escrituraUsd+=x/1e3*H;let A=C;for(;A<w.length&&w[A].clave!==b.clave;)A+=1;A<
|
|
149
|
+
w.length&&(w[A].bytes===b.bytes&&(n.tokensInvalidados+=x,n.invalidacionUsd+=x/1e3*(H-r.lecturaPer1k)),C=A+1);}return this.previo=s,this.previoUltimoBp=p,this.previoTtl=i[p]??"5m",this.hayPrevio=true,this.
|
|
150
|
+
atPrevio=e.at,n.totalUsd=n.lecturaUsd+n.escrituraUsd+n.entradaUsd,this.acumulado.lecturaUsd+=n.lecturaUsd,this.acumulado.escrituraUsd+=n.escrituraUsd,this.acumulado.entradaUsd+=n.entradaUsd,this.acumulado.
|
|
151
151
|
totalUsd+=n.totalUsd,this.acumulado.tokensLeidos+=n.tokensLeidos,this.acumulado.tokensEscritos+=n.tokensEscritos,this.acumulado.tokensEntrada+=n.tokensEntrada,this.acumulado.tokensInvalidados+=n.tokensInvalidados,
|
|
152
|
-
this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function
|
|
153
|
-
0),o=(
|
|
154
|
-
0)>0};if(r.bloques.length===0)return null;let s=this.cadenaPara(this.clave(
|
|
155
|
-
if(
|
|
156
|
-
"hex").slice(0,16)}\xB7${
|
|
157
|
-
cachesDe(n);if(o={base:new
|
|
158
|
-
a&&(a=c.ultimoUso,s=i);s!==null&&this.cadenas.delete(s);}}return o.ultimoUso=Date.now(),o}};var
|
|
159
|
-
fetchImpl??fetch,this.log=
|
|
160
|
-
enVuelo:(this.enVuelo=this.pedir().finally(()=>{this.enVuelo=null;}),this.enVuelo)}async pedir(){try{let
|
|
161
|
-
timeout(1e4)});if(!
|
|
152
|
+
this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function on(t){return t.map(e=>({clave:e.clave,bytes:e.bytes}))}var Mo=64,Te=class{cadenas=new Map;cachesPorModelo=new Map;observar(e){let n=e.uso.cache_creation_input_tokens??(e.uso.cache_creation?.ephemeral_5m_input_tokens??0)+(e.uso.cache_creation?.ephemeral_1h_input_tokens??
|
|
153
|
+
0),o=(e.uso.input_tokens??0)+(e.uso.cache_read_input_tokens??0)+n;if(o<=0)return null;let r={bloques:tn(e.cuerpo),at:e.at,model:e.model,entradaReal:o,escritura1h:(e.uso.cache_creation?.ephemeral_1h_input_tokens??
|
|
154
|
+
0)>0};if(r.bloques.length===0)return null;let s=this.cadenaPara(this.clave(e),e.model),a=s.base.paso(r),i=s.v0.paso(r);return a.totalUsd<=0&&i.totalUsd<=0?null:{baselineUsd:a.totalUsd,politicaUsd:i.totalUsd}}clave(e){
|
|
155
|
+
if(e.sessionId)return `s:${e.sessionId}\xB7a:${e.agentId??""}\xB7${e.model}`;let n=Array.isArray(e.cuerpo.messages)?e.cuerpo.messages[0]:void 0;return `m:${createHash("sha256").update(JSON.stringify(n??null)).digest(
|
|
156
|
+
"hex").slice(0,16)}\xB7${e.model}`}cachesDe(e){let n=this.cachesPorModelo.get(e);return n||(n={base:new te,v0:new te},this.cachesPorModelo.set(e,n)),n}cadenaPara(e,n){let o=this.cadenas.get(e);if(!o){
|
|
157
|
+
let r=this.cachesDe(n);if(o={base:new pe(s=>on(s),r.base),v0:new pe((s,a,i)=>nn("v0",s,a,i),r.v0),ultimoUso:0},this.cadenas.set(e,o),this.cadenas.size>Mo){let s=null,a=1/0;for(let[i,c]of this.cadenas)
|
|
158
|
+
c.ultimoUso<a&&(a=c.ultimoUso,s=i);s!==null&&this.cadenas.delete(s);}}return o.ultimoUso=Date.now(),o}};var _e=class{url;clave;ttlMs;fetchImpl;log;features=new Set;validoHasta=0;enVuelo=null;avisado=false;constructor(e){this.url=e.url,this.clave=e.serviceAccountKey,this.ttlMs=e.ttlMs??3e5,this.fetchImpl=e.
|
|
159
|
+
fetchImpl??fetch,this.log=e.log??(()=>{}),this.refrescar();}tiene(e){return Date.now()>this.validoHasta&&this.enVuelo===null&&this.refrescar(),this.features.has(e)}refrescar(){return this.enVuelo?this.
|
|
160
|
+
enVuelo:(this.enVuelo=this.pedir().finally(()=>{this.enVuelo=null;}),this.enVuelo)}async pedir(){try{let e=await this.fetchImpl(this.url,{method:"GET",headers:{authorization:`Bearer ${this.clave}`},signal:AbortSignal.
|
|
161
|
+
timeout(1e4)});if(!e.ok){this.cerrar(`entitlements HTTP ${e.status}`);return}let n=await e.json();if(!Array.isArray(n.features)||!n.features.every(r=>typeof r=="string")){this.cerrar("entitlements con\
|
|
162
162
|
forma inesperada");return}this.features=new Set(n.features);let o=typeof n.refreshAfterSeconds=="number"&&n.refreshAfterSeconds>0?Math.min(n.refreshAfterSeconds*1e3,this.ttlMs):this.ttlMs;this.validoHasta=
|
|
163
|
-
Date.now()+o,this.avisado=!1;}catch(
|
|
164
|
-
titlements no disponibles (${
|
|
165
|
-
referencias:o}}var
|
|
163
|
+
Date.now()+o,this.avisado=!1;}catch(e){this.cerrar(String(e));}}cerrar(e){this.features=new Set,this.validoHasta=Date.now()+Math.min(6e4,this.ttlMs),this.avisado||(this.avisado=true,this.log(`[gateway] en\
|
|
164
|
+
titlements no disponibles (${e}) \u2014 palanca apagada (fail-closed)`));}};function rn(t){let e=0,n=0;for(;;){let r=t.indexOf('"input_schema"',n);if(r<0)break;e+=1,n=r+14;}let o=0;for(n=0;;){let r=t.indexOf('"tool_reference"',n);if(r<0)break;o+=1,n=r+16;}return {definiciones:e,
|
|
165
|
+
referencias:o}}var Lo=40;function sn(t){return t.referencias>0||t.definiciones<Lo?null:`[bvsala gateway] tu cliente manda ${t.definiciones} definiciones de herramientas ENTERAS en cada petici\xF3n y no u\
|
|
166
166
|
sa la b\xFAsqueda de herramientas. Con un proxy delante, Claude Code la apaga por defecto: \`bvsala claude\` la reactiva, pero solo en una VENTANA NUEVA. Si lanzaste el terminal a mano, exporta ENABLE_TOOL\
|
|
167
|
-
_SEARCH=true. En el corpus de la casa ese bloque era el 24,5 % del dinero de entrada.`}var
|
|
168
|
-
`).update(
|
|
167
|
+
_SEARCH=true. En el corpus de la casa ese bloque era el 24,5 % del dinero de entrada.`}var tt=5*1024*1024,jo=["authorization","x-api-key","anthropic-version","anthropic-beta"];function an(t,e,n,o=""){return createHash("sha256").update(t).update(`
|
|
168
|
+
`).update(e).update(`
|
|
169
169
|
`).update(o).update(`
|
|
170
|
-
`).update(n).digest("hex")}function
|
|
171
|
-
`)}var
|
|
172
|
-
s=0,a=false;return {capturar:i=>{if(!a){if(s+=i.length,s>
|
|
173
|
-
this.enVuelo.delete(
|
|
174
|
-
1),o}tieneEnVuelo(
|
|
175
|
-
|
|
176
|
-
{},
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
"
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
\
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
(d.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
"
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
170
|
+
`).update(n).digest("hex")}function cn(t){return jo.map(e=>`${e}=${t(e)??""}`).join(`
|
|
171
|
+
`)}var Ce=class{enVuelo=new Map;primarias=0;gemelas=0;registrar(e){if(this.enVuelo.has(e))return null;this.primarias+=1;let n,o=new Promise(i=>n=i);this.enVuelo.set(e,{promesa:o,resolver:n});let r=[],
|
|
172
|
+
s=0,a=false;return {capturar:i=>{if(!a){if(s+=i.length,s>tt){a=true,r.length=0;return}r.push(i);}},terminar:(i,c)=>{let m=!a&&i>=200&&i<300;this.enVuelo.get(e)?.resolver(m?{status:i,headers:c,chunks:r}:null),
|
|
173
|
+
this.enVuelo.delete(e);},abortar:()=>{this.enVuelo.get(e)?.resolver(null),this.enVuelo.delete(e);}}}async esperar(e){let n=this.enVuelo.get(e);if(!n)return null;let o=await n.promesa;return o&&(this.gemelas+=
|
|
174
|
+
1),o}tieneEnVuelo(e){return this.enVuelo.has(e)}};var Bo=["content-encoding","content-length","transfer-encoding"],Uo=new Set(["connection","keep-alive","proxy-connection","proxy-authenticate","proxy-authorization","te","trailer","transfer-encoding",
|
|
175
|
+
"upgrade","expect"]);function ne(t){let e=t?.cause;if(e==null)return String(t);let n=e instanceof AggregateError&&e.errors.length>0?e.errors.map(o=>String(o)).join("; "):String(e);return `${String(t)} \
|
|
176
|
+
\xB7 causa: ${n}`}var nt=class extends Error{code;puerto;constructor(e,n,o){super(e==="EADDRINUSE"?`el puerto ${n} ya est\xE1 en uso: no se pudo arrancar el gateway`:e==="EACCES"?`el puerto ${n} no se\
|
|
177
|
+
puede abrir: puerto sin permiso`:`no se pudo escuchar en 127.0.0.1:${n} (${e})`,{cause:o}),this.name="ErrorDeEscucha",this.code=e,this.puerto=n;}};async function ln(t={}){let e=(t.upstream??"https://a\
|
|
178
|
+
pi.anthropic.com").replace(/\/+$/,""),n=t.fetchImpl??fetch,o=t.log??(l=>console.log(l)),r;if(t.serviceAccountKey){r=new ee({url:t.meteringUrl??"https://savings.bivelio.com/api/metering/usage",serviceAccountKey:t.
|
|
179
|
+
serviceAccountKey,surface:"gateway",...t.fetchImpl?{fetchImpl:t.fetchImpl}:{},onAuthError:p=>O("gateway-ingest-auth",`[bvsala gateway] la ingesta de uso rechaza la credencial (${p}). El tr\xE1fico sigue \
|
|
180
|
+
fluyendo (avisar, nunca romper), pero este uso no est\xE1 llegando al panel. Revisa BIVELIO_SERVICE_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let l=Ee();t.seatId?r.setSeat(t.seatId,
|
|
181
|
+
l):we(t.serviceAccountKey).then(p=>r?.setSeat(p,l)).catch(()=>{}),r.start();}else O("gateway-sin-clave","[bvsala gateway] sin BIVELIO_SERVICE_KEY: el gateway reenv\xEDa el tr\xE1fico pero NO mide. Consigue t\
|
|
182
|
+
u clave en savings.bivelio.com/dashboard/install para ver el gasto en tu panel.");let s=t.coalescer?new Ce:null,a=t.sombra&&r?new Te:null,i=new ye,c=t.elision!==false&&t.serviceAccountKey?new _e({url:new URL(
|
|
183
|
+
"/api/org/entitlements",t.meteringUrl??"https://savings.bivelio.com/api/metering/usage").toString(),serviceAccountKey:t.serviceAccountKey,...t.fetchImpl?{fetchImpl:t.fetchImpl}:{},log:o}):null,m=l=>l===
|
|
184
|
+
"/v1/messages"?new W:l.endsWith("/responses")?new Ae:null,g=(l,p,S,D,w,C,d,b,x,H,A)=>{if(!r||!S)return;let $=r,se=S,T=qt(p,C);if(!T){O(`gateway-sin-modelo:${w}`,`[bvsala gateway] no se pudo leer el mo\
|
|
185
|
+
delo del cuerpo de ${w} (content-encoding: ${C??"ninguno"}); su uso se reenv\xEDa pero no se mide.`);return}let I=!D&&A?A.servido:T,P=Ht(I,S);if(P){let X=D?Gt(l,T,P,d):Jt(l,I,P,d,b,x,A);r.record(X);let Z=X.
|
|
186
|
+
cost.eliminatedInputFloorCost;o(`[gateway] POST ${w} ${D?"\xB7 COALESCIDA (llamada evitada)":""} \xB7 ${I!==T?`${T}\u2192${I} (modelo hermano)`:T} \xB7 $${P.costeUsd.toFixed(6)} (in ${P.tokens.entrada}\
|
|
187
|
+
, cache\u2191${P.tokens.cacheEscrita}${P.tokens.cacheEscrita1h?` (1h ${P.tokens.cacheEscrita1h})`:""} cache\u2193${P.tokens.cacheLeida}, out ${P.tokens.salida})`+(b?` \xB7 elisi\xF3n: ${b.borrados} bo\
|
|
188
|
+
rrado(s), ${b.tokensLimpiados} tok limpiados por el proveedor`+(Z!==void 0?` \xB7 suelo $${Z.toFixed(6)} (lectura de cach\xE9)`:b.tokensLimpiadosToolUses>0?b.atribuible?" \xB7 sin precio de lectura en el\
|
|
189
|
+
cat\xE1logo: sin suelo":" \xB7 diales del cliente: se cuenta, no se acredita":b.tokensLimpiados>0?" \xB7 solo thinking (config del cliente): se cuenta, no se acredita":""):""));let q=b?.atribuible===
|
|
190
|
+
true&&b.tokensLimpiadosToolUses>0;a&&!D&&w==="/v1/messages"&&setImmediate(()=>{try{let E=Qe(p,C);if(!E||typeof E!="object")return;let y=a.observar({cuerpo:E,uso:se,model:T,at:H??Date.now(),...d?.sessionId!==
|
|
191
|
+
void 0?{sessionId:d.sessionId}:{},...d?.agentId!==void 0?{agentId:d.agentId}:{}});if(!y)return;if(q){o(`[gateway] sombra \xB7 ${T} \xB7 el proveedor ya borr\xF3 por nuestros diales: la cadena avanza, no se \
|
|
192
|
+
emite`);return}$.record(Wt(`${l}:shadow`,T,y.baselineUsd,y.politicaUsd,d)),o(`[gateway] sombra \xB7 ${T} \xB7 baseline $${y.baselineUsd.toFixed(6)} \u2192 v0 $${y.politicaUsd.toFixed(6)}`);}catch{}});}else
|
|
193
|
+
O(`gateway-sin-precio:${T}`,`[bvsala gateway] el modelo "${T}" no est\xE1 en el cat\xE1logo de precios; su uso se reenv\xEDa pero no se mide.`);},u=createServer(async(l,p)=>{let S=randomUUID(),D=Date.now(),w=new AbortController;
|
|
194
|
+
p.on("close",()=>{p.writableEnded||w.abort();});let C=null,d=new URL(l.url??"/",e),b=null,x=Buffer.alloc(0),H=false,A=null,$=null,se=(E,y)=>{if(E===null||A===null||!A.nuestros)return E;let K=y?.cache_creation,
|
|
195
|
+
je=y?.cache_creation_input_tokens??(K?.ephemeral_5m_input_tokens??0)+(K?.ephemeral_1h_input_tokens??0),ae=(y?.input_tokens??0)+(y?.cache_read_input_tokens??0)+je+E.tokensLimpiados,ie=A.triggerDelCliente!==
|
|
196
|
+
null&&ae>=A.triggerDelCliente;return {...E,atribuible:!ie}},T=l.headers["content-encoding"],I=Array.isArray(T)?T[0]:T,P=E=>{let y=Array.isArray(E)?E[0]:E;return y!==void 0&&/^[A-Za-z0-9._:/-]{1,128}$/.
|
|
197
|
+
test(y)?y:void 0},X=P(l.headers["x-claude-code-session-id"]),Z=P(l.headers["x-claude-code-agent-id"]),q=X!==void 0||Z!==void 0?{...X!==void 0?{sessionId:X}:{},...Z!==void 0?{agentId:Z}:{}}:void 0;try{
|
|
198
|
+
let E=[];for await(let f of l)E.push(f);let y=Buffer.concat(E);x=y,d=new URL(l.url??"/",e);let K=s!==null&&l.method==="POST"&&y.length>0,je=cn(f=>{let v=l.headers[f];return Array.isArray(v)?v.join(", "):
|
|
199
|
+
v}),ae=K?an("POST",d.pathname+d.search,y,je):"";if(K)if(s.tieneEnVuelo(ae)){let f=await s.esperar(ae);if(f){p.writeHead(f.status,f.headers);let v=m(d.pathname)??new W;for(let ue of f.chunks)p.write(ue),
|
|
200
|
+
v.observar(ue);p.end();let le=v.usage()??(d.pathname==="/v1/messages"?Xe(Buffer.concat(f.chunks)):null);g(S,y,le,!0,d.pathname,I,q);return}}else C=s.registrar(ae);let ie=l.headers.connection,On=new Set(
|
|
201
|
+
(Array.isArray(ie)?ie.join(","):ie??"").split(",").map(f=>f.trim().toLowerCase()).filter(f=>f!=="")),V={};for(let[f,v]of Object.entries(l.headers))f==="host"||f==="content-length"||v===void 0||Uo.has(
|
|
202
|
+
f)||On.has(f)||(V[f]=Array.isArray(v)?v.join(", "):v);let Dn={...V},M=y;if(c!==null&&t.dialesElision===!0&&l.method==="POST"&&d.pathname==="/v1/messages"&&c.tiene("context_elision"))try{let f=Et(y,I);
|
|
203
|
+
f!==null&&(M=f.cuerpo,A={nuestros:f.nuestros,triggerDelCliente:f.triggerDelCliente},V["anthropic-beta"]=At(V["anthropic-beta"]));}catch{}if(l.method==="POST"&&d.pathname==="/v1/messages"&&(I??"")==="")
|
|
204
|
+
try{let f=sn(rn(y.toString("utf8")));f&&O("gateway-busqueda-herramientas",f);}catch{}let bt=c!==null&&t.modeloHermano===!0&&l.method==="POST"&&(d.pathname==="/v1/messages"||d.pathname==="/v1/messages/c\
|
|
205
|
+
ount_tokens");if(bt&&!c.tiene("sibling_model_routing")&&O("gateway-hermano-sin-feature","[bvsala gateway] modelo hermano (C): la bandera est\xE1 puesta pero la licencia de la org NO trae sibling_model_ro\
|
|
206
|
+
uting; la petici\xF3n se reenv\xEDa intacta (fail-closed)."),bt&&c.tiene("sibling_model_routing"))try{let v=jt(M,M===y?I:"identity",{betas:V["anthropic-beta"]});v!==null&&(M=v.cuerpo,$=v.cambio);}catch{}
|
|
207
|
+
let he=!1;if(c!==null&&Ge(t.esfuerzo)&&l.method==="POST"&&d.pathname==="/v1/messages"&&c.tiene("per_turn_effort"))try{let f=M===y?I:"identity",v=Pt(M,t.esfuerzo,f);v!==null&&(M=v.cuerpo,V["anthropic-b\
|
|
208
|
+
eta"]=Ot(V["anthropic-beta"]),he=!0);}catch{}let ge=null;if(c!==null&&l.method==="POST"&&d.pathname==="/v1/messages"&&c.tiene("cache_ttl_tuning"))try{let v=J(M,M===y?I:"identity");if(v!==null){let le=Tt(
|
|
209
|
+
v),ue=`${q?.sessionId??"sin-sesion"}:${le.system}`,kt=Date.now(),Mn=i.ultima(ue,kt);if(i.anotar(ue,le,kt),Ct({fraccionNueva:_t(Mn,le)})){let be=Rt(v);be!==null&&(M=be.cuerpo,ge={rebajadas:be.rebajadas,
|
|
210
|
+
yaEran5m:be.yaEran5m});}}}catch{}let _;try{_=await n(d,{method:l.method,headers:V,body:["GET","HEAD"].includes(l.method??"")?void 0:M,redirect:"manual",signal:w.signal});}catch(f){C?.abortar(),p.headersSent||
|
|
211
|
+
(p.writeHead(502,{"content-type":"application/json"}),p.end(JSON.stringify({error:"bvsala gateway: upstream unreachable",detail:ne(f)}))),o(`[gateway] ${l.method} ${d.pathname} \u2192 upstream inalcanzable\
|
|
212
|
+
: ${ne(f)}`);return}if(($!==null||he)&&_.status===400&&!w.signal.aborted){let f="";try{f=(await _.text()).slice(0,300).replace(/\s+/g," ");}catch{}o(`[gateway] el upstream rechaz\xF3 (400) la petici\xF3n ree\
|
|
213
|
+
scrita${$?` a ${$.servido}`:""}${he?" (esfuerzo por turno)":""}; se reenv\xEDa intacta \xB7 ${f}`),$=null,he=!1,ge=null,A=null;try{_=await n(d,{method:l.method,headers:Dn,body:y,redirect:"manual",signal:w.
|
|
214
|
+
signal});}catch(v){C?.abortar(),p.headersSent||(p.writeHead(502,{"content-type":"application/json"}),p.end(JSON.stringify({error:"bvsala gateway: upstream unreachable",detail:ne(v)}))),o(`[gateway] ${l.
|
|
215
|
+
method} ${d.pathname} \u2192 upstream inalcanzable en el reintento: ${ne(v)}`);return}}let Ne=Object.fromEntries(_.headers.entries());for(let f of Bo)delete Ne[f];p.writeHead(_.status,Ne);let vt=_.headers.
|
|
216
|
+
get("content-type")??"",ze=vt.includes("text/event-stream")||vt===""&&_.ok&&m(d.pathname)!==null;b=ze?m(d.pathname):null;let ce=!ze&&_.ok&&r!==void 0&&l.method==="POST"&&d.pathname==="/v1/messages"&&(_.
|
|
217
|
+
headers.get("content-type")??"").includes("application/json")?[]:null,yt=0;if(_.body)for await(let f of _.body){let v=Buffer.from(f);p.write(v),b?.observar(v),ce&&(yt+=v.length,yt>tt?ce=null:ce.push(v)),
|
|
218
|
+
C?.capturar(v);}if(p.end(),C?.terminar(_.status,Ne),b&&_.ok){H=!0;let f=b.usage(),v=se(b instanceof W?b.elision():null,f);g(S,y,f,!1,d.pathname,I,q,v,ge,D,$),r||o(`[gateway] ${l.method} ${d.pathname} \u2192\
|
|
219
|
+
${_.status} (stream) \xB7 no medido: sin BIVELIO_SERVICE_KEY`);}else if(ce){let f=Buffer.concat(ce),v=Xe(f);g(S,y,v,!1,d.pathname,I,q,se(Vt(f),v),ge,D,$);}else o(`[gateway] ${l.method} ${d.pathname} \u2192 ${_.
|
|
220
|
+
status}${ze?" (stream)":""}`);}catch(E){if(C?.abortar(),w.signal.aborted){let y=!H&&b?b.usageFinal():null;if(y){o(`[gateway] ${l.method} ${d.pathname} \u2192 el cliente cerr\xF3 tras el usage final; se mide ig\
|
|
221
|
+
ual`);let K=se(b instanceof W?b.elision():null,y);g(S,x,y,false,d.pathname,I,q,K,void 0,D,$);}else o(`[gateway] ${l.method} ${d.pathname} \u2192 el cliente abort\xF3; upstream cancelado`);}else if(o(`[gate\
|
|
222
|
+
way] ${l.method} ${d.pathname} \u2192 error sirviendo: ${ne(E)}`),!p.headersSent){p.writeHead(502,{"content-type":"application/json"}),p.end(JSON.stringify({error:"bvsala gateway: stream interrupted",
|
|
223
|
+
detail:ne(E)}));return}p.writableEnded||p.end();}});u.on("upgrade",(l,p)=>{o(`[gateway] ${l.method} ${new URL(l.url??"/","http://x").pathname} \u2192 426 (WebSocket no soportado; el cliente cae a HTTP)`),
|
|
224
|
+
p.once("error",()=>{}),p.once("finish",()=>p.destroy()),p.end(`HTTP/1.1 426 Upgrade Required\r
|
|
220
225
|
connection: close\r
|
|
221
226
|
content-length: 0\r
|
|
222
227
|
\r
|
|
223
|
-
`);})
|
|
224
|
-
|
|
225
|
-
a);if(o(i))
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
/
|
|
228
|
+
`);});let h=t.puerto??8402;try{await new Promise((l,p)=>{u.once("error",p),u.listen(h,"127.0.0.1",()=>l());});}catch(l){r?.stop();let p=l?.code;throw new nt(typeof p=="string"?p:"EUNKNOWN",h,l)}return {puerto:u.
|
|
229
|
+
address().port,cerrar:async()=>{await r?.stopAndDrain(),await new Promise(l=>u.close(()=>l()));}}}var ot=["claude","codex","goose","qwen"];function Re(t){return ot.includes(t??"")}function dn(t,e={}){let n=e.path??process.env.PATH??"",o=e.
|
|
230
|
+
existe??existsSync,r=null;for(let s of n.split(";").filter(a=>a.length>0)){for(let a of [".exe",".com"]){let i=join(s,t+a);if(o(i))return {tipo:"exe",ruta:i}}if(r===null)for(let a of [".cmd",".bat"]){let i=join(s,t+
|
|
231
|
+
a);if(o(i)){r=i;break}}}return r!==null?{tipo:"solo-shim",ruta:r}:{tipo:"no-encontrado"}}function pn(t={}){let n=(t.env??process.env).BVSALA_CODEX_AUTH?.toLowerCase();if(n==="api-key"||n==="apikey")return "\
|
|
232
|
+
api-key";if(n==="chatgpt")return "chatgpt";let o=null;try{o=t.leerAuth?t.leerAuth():null;}catch{o=null;}if(o===null)return "api-key";try{let r=JSON.parse(o);return typeof r.auth_mode=="string"?r.auth_mode.
|
|
233
|
+
toLowerCase().replace(/[^a-z]/g,"")==="apikey"?"api-key":"chatgpt":r.tokens!==void 0&&r.tokens!==null?"chatgpt":"api-key"}catch{return "api-key"}}var Fo={"api-key":{upstream:"https://api.openai.com",prefijo:"\
|
|
234
|
+
/v1"},chatgpt:{upstream:"https://chatgpt.com",prefijo:"/backend-api/codex"}};function rt(t,e,n,o={},r=process.env){let s=`http://127.0.0.1:${e}`;switch(t){case "claude":return {bin:"claude",args:n,env:{
|
|
229
235
|
ANTHROPIC_BASE_URL:s,ENABLE_TOOL_SEARCH:r.ENABLE_TOOL_SEARCH??"true"}};case "goose":return {bin:"goose",args:n,env:{ANTHROPIC_HOST:s}};case "qwen":return {bin:"qwen",args:n,env:{ANTHROPIC_BASE_URL:s},nota:'\
|
|
230
|
-
Qwen Code solo enruta por aqu\xED con `security.auth.selectedType: "anthropic"` en ~/.qwen/settings.json (ver `bvsala doctor`).'};case "codex":{let a=o.modoCodex??"api-key",i=
|
|
236
|
+
Qwen Code solo enruta por aqu\xED con `security.auth.selectedType: "anthropic"` en ~/.qwen/settings.json (ver `bvsala doctor`).'};case "codex":{let a=o.modoCodex??"api-key",i=Fo[a];return {bin:"codex",args:[
|
|
231
237
|
"-c",`openai_base_url="${s}${i.prefijo}"`,...n],env:{},upstream:i.upstream,nota:a==="chatgpt"?"Auth ChatGPT detectada: el gateway enruta a chatgpt.com/backend-api/codex. El tr\xE1fico de suscripci\xF3n se m\
|
|
232
|
-
ide (equivalente a precio de lista) pero no se monetiza: no hay factura por tokens.":"Auth por API key: el gateway enruta a api.openai.com/v1."}}}}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
238
|
+
ide (equivalente a precio de lista) pero no se monetiza: no hay factura por tokens.":"Auth por API key: el gateway enruta a api.openai.com/v1."}}}}var Ho=["gateway","doctor","skill"],mn=new Set(["help","--help","-h"]),fn=new Set(["version","--version","-v"]);function hn(t){let[e,...n]=t;return e===void 0||mn.has(e)?{tipo:"ayuda",salida:0}:fn.has(
|
|
239
|
+
e)?{tipo:"version"}:Re(e)?{tipo:"arrancar",comando:e,resto:n}:Ho.includes(e)?n.some(o=>mn.has(o))?{tipo:"ayuda",salida:0}:n.some(o=>fn.has(o))?{tipo:"version"}:{tipo:"arrancar",comando:e,resto:n}:{tipo:"\
|
|
240
|
+
ayuda",salida:1}}function gn(t,e,n){let o=t??{},r=typeof o.puerto=="number"?o.puerto:n;if(o.code==="EADDRINUSE")return `el puerto ${r} ya est\xE1 en uso (\xBFotro gateway o un terminal lanzado antes?): usa -\
|
|
241
|
+
-puerto ${r+1} o apaga el otro proceso`;if(o.code==="EACCES")return `el puerto ${r} no se puede abrir: puerto sin permiso (EACCES; los puertos por debajo de 1024 piden privilegios): usa --puerto ${Math.
|
|
242
|
+
max(1024,r)} o superior`;let s=t instanceof Error?t.message:String(t);return `no se pudo arrancar el gateway de \`bvsala ${e}\`: ${s}`}function qo(t){let e=Number.parseInt(t.slice(8,10),10);return Number.isFinite(e)&&e%2===0?"palanca":"control"}function bn(t){let e;try{e=JSON.parse(t());}catch{return null}if(typeof e!="object"||e===null)return null;let n=e,o=n.espia;return typeof o!="number"||!Number.isInteger(o)||o<1||o>65535?null:{activo:n.
|
|
243
|
+
activo!==false,espia:o}}function vn(t){let{enrolamiento:e,espiaVivo:n,upstreamEnv:o,elisionEnv:r,hoyUtcIso:s}=t;if(!e)return {linea:"",aviso:false};if(!e.activo)return {linea:"anillo 2: enrolamiento en pausa \
|
|
244
|
+
(activo:false)",aviso:false};if(!n)return {linea:`anillo 2: enrolado pero el esp\xEDa NO escucha en :${e.espia} \u2014 NO encadeno (el tr\xE1fico de hoy no entra en el corpus). Arr\xE1ncalo con \`pnpm anillo2:espia\`.`,
|
|
245
|
+
aviso:true};let a=qo(s),i=`http://127.0.0.1:${e.espia}`,c=o!==void 0&&o!=="",m=r!==void 0&&r!=="",g=[];return g.push(`anillo 2: ${s} UTC \u2192 brazo ${a.toUpperCase()}`),g.push(c?`upstream respetado de\
|
|
246
|
+
l entorno (${o})`:`encadenado a :${e.espia}`),m&&g.push(`elisi\xF3n respetada del entorno (=${r})`),g.push("diales de elisi\xF3n APAGADOS (2026-09-09): el brazo ya no los arma"),g.push("asignaci\xF3n POR\
|
|
247
|
+
SESI\xD3N desde el 2026-09-10 (brazoDeSesion), no por paridad del d\xEDa"),{...c?{}:{upstream:i},brazo:a,linea:g.join(", "),aviso:false}}var Wo="comprobar: en el log del gateway debe aparecer `[gateway] POST /v1/messages \u2026`; si ve\
|
|
248
|
+
s `/v1/v1/messages`, sobra un /v1; si ves `POST /messages` a secas, falta uno.",Yo=[{id:"claude",nombre:"Claude Code",binario:"claude",configs:[],detectable:true,receta:({base:t})=>["usa `bvsala claude`\
|
|
249
|
+
\u2014 arranca el gateway en un puerto ef\xEDmero, lanza `claude` apunt\xE1ndole y lo apaga al salir.",`a mano: ANTHROPIC_BASE_URL=${t} claude (sin /v1: el cliente a\xF1ade /v1/messages)`]},{id:"co\
|
|
250
|
+
dex",nombre:"Codex CLI",binario:"codex",configs:[join(".codex","config.toml"),join(".codex","auth.json")],detectable:true,receta:({base:t,rutas:e})=>["usa `bvsala codex` \u2014 el prefijo del base URL depende del \
|
|
251
|
+
modo de auth y lo resuelve el envoltorio:",` API key \u2192 openai_base_url=${t}/v1`,` suscripci\xF3n ChatGPT \u2192 openai_base_url=${t}/backend-api/codex (tiene que terminar exactament\
|
|
252
|
+
e ah\xED)`,`${e[1]}: solo se comprueba que exista; nunca se lee.`]},{id:"opencode",nombre:"opencode",binario:"opencode",configs:[join(".config","opencode","opencode.json")],detectable:true,receta:({baseV1:t,
|
|
253
|
+
rutas:e})=>[`mecanismo: ${e[0]} \u2192 provider.anthropic.options.baseURL (el opencode.json del proyecto pisa al global). CON /v1.`,"{",' "provider": {',' "anthropic": {',` "options": { "base\
|
|
254
|
+
URL": "${t}" }`," }"," }","}",'alternativa: "baseURL": "{env:BVSALA_BASE_URL}" y exportar la variable; trampa: sin la variable, baseURL queda vac\xEDo.']},{id:"goose",nombre:"Goose",binario:"goose",
|
|
255
|
+
configs:[join(".config","goose","config.yaml")],detectable:true,receta:({base:t,rutas:e})=>[`mecanismo: variable de entorno ANTHROPIC_HOST (pisa ${e[0]}). SIN /v1.`,`ANTHROPIC_HOST=${t} ANTHROPIC_API_KEY=\u2026\
|
|
256
|
+
goose`]},{id:"crush",nombre:"Crush",binario:"crush",configs:[join(".config","crush","crushrc")],detectable:true,receta:({baseV1:t,rutas:e})=>[`mecanismo: ${e[0]} (Bash); crush.json est\xE1 deprecado. CON /v1\
|
|
257
|
+
y SIN barra final (el SDK Go resuelve relativo: /v1/ \u2192 /v1/v1/messages).`,`provider add bvsala --type anthropic --base-url ${t} --api-key "$ANTHROPIC_API_KEY"`]},{id:"qwen",nombre:"Qwen Code",binario:"\
|
|
258
|
+
qwen",configs:[join(".qwen","settings.json")],detectable:true,receta:({base:t,rutas:e})=>[`mecanismo: variable de entorno ANTHROPIC_BASE_URL + ${e[0]} con selectedType = anthropic. SIN /v1 (el SDK TS ofici\
|
|
259
|
+
al a\xF1ade /v1/messages).`,`ANTHROPIC_BASE_URL=${t} ANTHROPIC_API_KEY=\u2026 qwen`,`comprueba a mano que ${e[0]} lleve selectedType: anthropic \u2014 el doctor no lee el archivo.`]},{id:"droid",nombre:"\
|
|
260
|
+
Droid (Factory)",binario:"droid",configs:[join(".factory","settings.json")],detectable:true,receta:({base:t,rutas:e})=>[`mecanismo: ${e[0]} \u2192 customModels[] con provider "anthropic". SIN /v1 [inferido: val\
|
|
251
261
|
idar en mano contra el log del gateway].`,"{",' "customModels": ['," {",' "model": "<id de modelo Anthropic>",',' "displayName": "<nombre visible>",',' "provider": "anthropic",',` \
|
|
252
|
-
"baseUrl": "${
|
|
253
|
-
\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: ${
|
|
254
|
-
receta:({baseV1:
|
|
255
|
-
let n=
|
|
256
|
-
|
|
262
|
+
"baseUrl": "${t}",`,' "apiKey": "<tu API key de Anthropic>"'," }"," ]","}"]},{id:"cline",nombre:"Cline",configs:[],detectable:false,receta:({baseV1:t})=>["mecanismo: UI \u2192 proveedor Anthropic\
|
|
263
|
+
\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: ${t}`]},{id:"kilo",nombre:"Kilo Code",configs:[],detectable:false,
|
|
264
|
+
receta:({baseV1:t})=>["mecanismo: UI \u2192 proveedor custom, Provider API \xABAnthropic Messages\xBB. Probar CON /v1 primero (linaje Cline) [inferido: validar en mano].",`Base URL: ${t}`]}];function Qo(t,e){
|
|
265
|
+
let n=t.split(delimiter).filter(r=>r.length>0),o=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return r=>n.some(s=>o.some(a=>e(join(s,r+a))))}async function yn(t,e={}){if(!Number.isInteger(t)||t<1||
|
|
266
|
+
t>65535)throw new RangeError(`[bvsala doctor] puerto inv\xE1lido: ${String(t)}`);let n=e.home??homedir(),o=e.existe??existsSync,r=e.enPath??Qo(e.path??process.env.PATH??"",o),s=`http://127.0.0.1:${t}`,a=`${s}/v1`,
|
|
257
267
|
i=[],c=[`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 \
|
|
258
|
-
se lee el contenido de ning\xFAn archivo.",""];for(let m of
|
|
259
|
-
|
|
260
|
-
push(`\xBB ${m.id}: ${
|
|
268
|
+
se lee el contenido de ning\xFAn archivo.",""];for(let m of Yo){let g=m.configs.map(p=>join(n,p)),u=m.binario!==void 0&&r(m.binario),h=g.filter(p=>o(p)),k=u||h.length>0;k&&i.push(m.id);let l;m.detectable?
|
|
269
|
+
k?l=`detectado \u2014 ${[...u?[`binario \`${m.binario}\` en PATH`]:[],...h.map(S=>`config presente: ${S}`)].join("; ")}`:l="no detectado":l="sin detecci\xF3n autom\xE1tica (extensi\xF3n de editor)",c.
|
|
270
|
+
push(`\xBB ${m.id}: ${l}`),c.push(` ${m.nombre}`);for(let p of m.receta({base:s,baseV1:a,rutas:g}))c.push(` ${p}`);c.push(` ${Wo}`),c.push("");}return c.push("Regla BYOK: las recetas del anillo Anth\
|
|
261
271
|
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 \
|
|
262
272
|
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:c.join(`
|
|
263
|
-
`),detectados:i}}var
|
|
264
|
-
<!-- bvsala:savings-mode:fin -->";function
|
|
265
|
-
${
|
|
273
|
+
`),detectados:i}}var kn="savings-mode";function xn(t,e){for(let n of t){let o=join(n,"skills",kn,"SKILL.md");if(e.existe(o))return o}return null}var Sn="<!-- bvsala:savings-mode:inicio -->",Ie="\
|
|
274
|
+
<!-- bvsala:savings-mode:fin -->";function Xo(t){let e=t.replace(/^---\n[\s\S]*?\n---\n*/,"").trim();return `${Sn}
|
|
275
|
+
${e}
|
|
266
276
|
|
|
267
277
|
_Always on (AGENTS.md has no activation step). Delete this block to turn it off; \`bvsala skill --codex --forzar\` restores it._
|
|
268
|
-
${
|
|
269
|
-
leer(
|
|
270
|
-
`),{ok:true,destino:r,mensaje:
|
|
278
|
+
${Ie}`}function En(t){let e=xn(t.origenes,t.fs);if(!e)return {ok:false,destino:"",mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${t.origenes.join(", ")})`};let n=Xo(t.fs.
|
|
279
|
+
leer(e)),o=t.proyecto?t.cwd:join(t.home,".codex"),r=join(o,"AGENTS.md");if(!t.fs.existe(r))return t.fs.crearDir(o),t.fs.escribir(r,n+`
|
|
280
|
+
`),{ok:true,destino:r,mensaje:st(r,"instalado")};let s=t.fs.leer(r),a=s.indexOf(Sn),i=s.indexOf(Ie);return a===-1||i===-1||i<a?(t.fs.escribir(r,s.trimEnd()+`
|
|
271
281
|
|
|
272
282
|
`+n+`
|
|
273
|
-
`),{ok:true,destino:r,mensaje:
|
|
274
|
-
slice(0,a)+n+s.slice(i+
|
|
275
|
-
usa --forzar para actualizarlo`}}function
|
|
283
|
+
`),{ok:true,destino:r,mensaje:st(r,"a\xF1adido al AGENTS.md existente")}):s.slice(a,i+Ie.length)===n?{ok:true,destino:r,mensaje:`[bvsala skill] ya instalado y al d\xEDa: ${r}`}:t.forzar?(t.fs.escribir(r,s.
|
|
284
|
+
slice(0,a)+n+s.slice(i+Ie.length)),{ok:true,destino:r,mensaje:st(r,"bloque actualizado")}):{ok:false,destino:r,mensaje:`[bvsala skill] el bloque savings-mode de ${r} tiene contenido DISTINTO \u2014 no lo piso; \
|
|
285
|
+
usa --forzar para actualizarlo`}}function st(t,e){return `[bvsala skill] ${e}: ${t}
|
|
276
286
|
[bvsala skill] AGENTS.md va SIEMPRE activo en Codex (no hay paso de activaci\xF3n); borra el bloque para apagarlo.
|
|
277
|
-
[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
|
|
278
|
-
mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${
|
|
279
|
-
"SKILL.md"),s=
|
|
280
|
-
nido DISTINTO \u2014 no lo piso; usa --forzar para sobrescribir`}}return
|
|
287
|
+
[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 wn(t){let e=xn(t.origenes,t.fs);if(!e)return {ok:false,destino:"",
|
|
288
|
+
mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${t.origenes.join(", ")})`};let n=t.proyecto?join(t.cwd,".claude","skills"):join(t.home,".claude","skills"),o=join(n,kn),r=join(o,
|
|
289
|
+
"SKILL.md"),s=t.fs.leer(e);if(t.fs.existe(r)&&!t.forzar){let a=t.fs.leer(r)===s;return {ok:a,destino:r,mensaje:a?`[bvsala skill] ya instalado y al d\xEDa: ${r}`:`[bvsala skill] ya existe ${r} con conte\
|
|
290
|
+
nido DISTINTO \u2014 no lo piso; usa --forzar para sobrescribir`}}return t.fs.crearDir(o),t.fs.escribir(r,s),{ok:true,destino:r,mensaje:`[bvsala skill] instalado: ${r}
|
|
281
291
|
[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.
|
|
282
|
-
[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
|
|
292
|
+
[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 at=class{id;exact=false;constructor(e="heuristic"){this.id=e;}count(e){if(e.length===0)return 0;let n=e.match(/[A-Za-z]+|\d+|\s+|[^\sA-Za-z\d]/g)??[],o=0;for(let r of n){let s=r[0];if(/\s/.test(s)){let a=(r.
|
|
283
293
|
match(/\n/g)??[]).length;o+=a+Math.floor(Math.max(0,r.length-1)/2);}else /[A-Za-z]/.test(s)?o+=Math.max(1,Math.ceil(r.length/4)):/\d/.test(s)?o+=Math.max(1,Math.ceil(r.length/2)):o+=1;}return Math.max(o,
|
|
284
|
-
Math.ceil(
|
|
285
|
-
return this.modelToTokenizer.set(
|
|
286
|
-
get(o);if(r)return r}}return this.estimators.get(this.fallbackId)}count(
|
|
287
|
-
|
|
288
|
-
argv;function
|
|
294
|
+
Math.ceil(e.length/4))}},it=new at;var ct=class{estimators=new Map;modelToTokenizer=new Map;fallbackId;constructor(e=it){this.fallbackId=e.id,this.estimators.set(e.id,e);}register(e){return this.estimators.set(e.id,e),this}mapModel(e,n){
|
|
295
|
+
return this.modelToTokenizer.set(e,n),this}resolve(e){let n=e.tokenizer?this.estimators.get(e.tokenizer):void 0;if(n)return n;if(e.model){let o=this.modelToTokenizer.get(e.model);if(o){let r=this.estimators.
|
|
296
|
+
get(o);if(r)return r}}return this.estimators.get(this.fallbackId)}count(e,n){return this.resolve(n).count(e)}};new ct;new TextEncoder;new TextDecoder;new TextDecoder;var hr={"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}};
|
|
297
|
+
Ye(hr);function Er(t,e=300){return new Promise(n=>{let o=connect({port:t,host:"127.0.0.1"}),r=s=>{o.destroy(),n(s);};o.setTimeout(e,()=>r(false)),o.once("connect",()=>r(true)),o.once("error",()=>r(false));})}var Le=hn(process.
|
|
298
|
+
argv.slice(2));function wr(){console.log(`bvsala ${G} \u2014 BiVelio Savings Layer
|
|
289
299
|
|
|
290
300
|
Comandos:
|
|
291
301
|
gateway [--puerto N] Proxy local medidor (por defecto 8402) para terminales que
|
|
@@ -304,6 +314,9 @@ Comandos:
|
|
|
304
314
|
de AGENTS.md (~/.codex; con --proyecto, ./AGENTS.md) \u2014 Codex no
|
|
305
315
|
tiene skills y AGENTS.md va siempre activo. Su efecto se mide con
|
|
306
316
|
el gateway, no se promete.
|
|
317
|
+
--version | -v Imprime solo la versi\xF3n.
|
|
318
|
+
--help | -h Esta ayuda; tambi\xE9n detr\xE1s de gateway, doctor o skill
|
|
319
|
+
(\`bvsala gateway --help\` no arranca nada).
|
|
307
320
|
|
|
308
321
|
Entorno:
|
|
309
322
|
BIVELIO_SERVICE_KEY Clave de servicio (bvk_\u2026): habilita metering + asiento.
|
|
@@ -353,27 +366,27 @@ Entorno:
|
|
|
353
366
|
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 (Claude Code, solo API key) tus modelos en /model.
|
|
354
367
|
|
|
355
368
|
El gateway nunca corta el tr\xE1fico: sin clave o con la ingesta ca\xEDda, reenv\xEDa y avisa.
|
|
356
|
-
Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
puerto"),
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
elisionEnv:process.env.BVSALA_GATEWAY_ELISION,hoyUtcIso:new Date().toISOString().slice(0,10)}),
|
|
364
|
-
{puerto:
|
|
365
|
-
env.BVSALA_GATEWAY_COALESCE==="1"?{coalescer
|
|
366
|
-
|
|
367
|
-
env.BVSALA_METERING_URL}:{}})
|
|
368
|
-
] medici\xF3n: ${
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
upstream}). Si no es lo que quieres, quita la variable.`);
|
|
373
|
-
|
|
374
|
-
[bvsala ${
|
|
375
|
-
npm (${o.ruta}) y Windows no puede lanzarlo de forma segura con argumentos (CVE-2024-
|
|
376
|
-
|
|
377
|
-
o)}. \xBFEst\xE1 instalado y en el PATH?`),
|
|
378
|
-
|
|
379
|
-
SIGINT",()=>{
|
|
369
|
+
Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}Le.tipo==="ayuda"&&(wr(),process.exit(Le.salida));Le.tipo==="version"&&(console.log(G),process.exit(
|
|
370
|
+
0));var{comando:R,resto:U}=Le,$e=Re(R);if(R==="skill"){let t=dirname(fileURLToPath(import.meta.url)),e={origenes:[join(t,"..",".."),join(t,"..")],home:homedir(),cwd:process.cwd(),proyecto:U.includes("--proyecto"),forzar:U.includes(
|
|
371
|
+
"--forzar"),fs:{existe:existsSync,leer:o=>readFileSync(o,"utf8"),escribir:(o,r)=>writeFileSync(o,r),crearDir:o=>mkdirSync(o,{recursive:true})}},n=U.includes("--codex")?En(e):wn(e);console.log(n.mensaje),process.exit(n.ok?0:1);}var mt=U.indexOf(
|
|
372
|
+
"--puerto"),Q=$e?0:mt>=0?Number(U[mt+1]):8402;(!Number.isInteger(Q)||(R==="doctor"?Q<1:Q<0)||Q>65535)&&(console.error(`[bvsala ${R}] puerto inv\xE1lido: ${U[mt+1]}`),process.exit(1));if(R==="doctor"){
|
|
373
|
+
U.includes("--write")&&(console.error("[bvsala doctor] --write todav\xEDa no existe: el doctor solo imprime; copia el bloque a mano."),process.exit(1));let t=await yn(Q);console.log(t.texto),process.exit(
|
|
374
|
+
0);}var j=$e?rt(R,0,U,{modoCodex:R==="codex"?pn({leerAuth:()=>readFileSync(join(homedir(),".codex","auth.json"),"utf8")}):void 0}):null,re=process.env.BIVELIO_SERVICE_KEY,Ar=$e&&process.env.BVSALA_GATEWAY_LOG!=="1",pt=j?.
|
|
375
|
+
upstream?null:bn(()=>readFileSync(process.env.BVSALA_ANILLO2_FICHERO??join(homedir(),".bvsala","anillo2.json"),"utf8")),fe=vn({enrolamiento:pt,espiaVivo:pt!==null&&await Er(pt.espia),upstreamEnv:process.env.BVSALA_GATEWAY_UPSTREAM,
|
|
376
|
+
elisionEnv:process.env.BVSALA_GATEWAY_ELISION,hoyUtcIso:new Date().toISOString().slice(0,10)}),ft=process.env.BVSALA_GATEWAY_UPSTREAM??fe.upstream,De=process.env.BVSALA_GATEWAY_ELISION??fe.elision,F;try{
|
|
377
|
+
F=await ln({puerto:Q,...Ar?{log:()=>{}}:{},...re?{serviceAccountKey:re}:{},...process.env.BVSALA_SEAT_ID?{seatId:process.env.BVSALA_SEAT_ID}:{},...ft?{upstream:ft}:j?.upstream?{upstream:j.upstream}:{},
|
|
378
|
+
...process.env.BVSALA_GATEWAY_COALESCE==="1"?{coalescer:!0}:{},...process.env.BVSALA_GATEWAY_SHADOW==="1"?{sombra:!0}:{},elision:De!=="0",...process.env.BVSALA_GATEWAY_DIALES_ELISION==="1"?{dialesElision:!0}:
|
|
379
|
+
{},...process.env.BVSALA_GATEWAY_MODELO_HERMANO==="1"?{modeloHermano:!0}:{},...process.env.BVSALA_GATEWAY_ESFUERZO?{esfuerzo:process.env.BVSALA_GATEWAY_ESFUERZO}:{},...process.env.BVSALA_METERING_URL?
|
|
380
|
+
{meteringUrl:process.env.BVSALA_METERING_URL}:{}});}catch(t){console.error(`[bvsala ${R}] ${gn(t,R,Q)}`),process.exit(1);}var Tr=ft??j?.upstream??"https://api.anthropic.com";console.log(`[bvsala gateway\
|
|
381
|
+
] v${G} escuchando en http://127.0.0.1:${F.puerto} \u2192 ${Tr}`);console.log(`[bvsala gateway] medici\xF3n: ${re?"ACTIVA (clave de servicio presente)":"APAGADA (falta BIVELIO_SERVICE_KEY)"}`);{let t=wt(
|
|
382
|
+
De,re!==void 0,process.env.BVSALA_GATEWAY_DIALES_ELISION==="1");(t.aviso?console.error:console.log)(`[bvsala gateway] ${t.linea}`);let e=Nt(process.env.BVSALA_GATEWAY_MODELO_HERMANO,re!==void 0,De!=="\
|
|
383
|
+
0");(e.aviso?console.error:console.log)(`[bvsala gateway] ${e.linea}`);let n=Dt(process.env.BVSALA_GATEWAY_ESFUERZO,re!==void 0,De!=="0");(n.aviso?console.error:console.log)(`[bvsala gateway] ${n.linea}`),
|
|
384
|
+
fe.linea&&(fe.aviso?console.error:console.log)(`[bvsala gateway] ${fe.linea}`);}process.env.BVSALA_GATEWAY_UPSTREAM&&j?.upstream&&process.env.BVSALA_GATEWAY_UPSTREAM!==j.upstream&&console.error(`[bvsal\
|
|
385
|
+
a ${R}] AVISO: BVSALA_GATEWAY_UPSTREAM=${process.env.BVSALA_GATEWAY_UPSTREAM} pisa el upstream de este terminal (${j.upstream}). Si no es lo que quieres, quita la variable.`);R==="codex"&&!Kt()&&console.
|
|
386
|
+
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.`);if(j&&$e){let t=rt(R,F.puerto,
|
|
387
|
+
U,{...j.upstream?{modoCodex:j.upstream.includes("chatgpt.com")?"chatgpt":"api-key"}:{}});t.nota&&console.log(`[bvsala ${R}] ${t.nota}`);let e=t.bin;if(process.platform==="win32"){let o=dn(t.bin);o.tipo===
|
|
388
|
+
"exe"?e=o.ruta:o.tipo==="solo-shim"&&(console.error(`[bvsala ${R}] \`${t.bin}\` est\xE1 instalado como shim de npm (${o.ruta}) y Windows no puede lanzarlo de forma segura con argumentos (CVE-2024-2798\
|
|
389
|
+
0). Inst\xE1lalo con su instalador nativo (deja un ${t.bin}.exe en el PATH) o usa la receta manual de docs/terminales/.`),await F.cerrar(),process.exit(127));}let n=spawn(e,t.args,{stdio:"inherit",env:{...process.
|
|
390
|
+
env,...t.env}});n.on("error",o=>{console.error(`[bvsala ${R}] no se pudo lanzar \`${t.bin}\`: ${String(o)}. \xBFEst\xE1 instalado y en el PATH?`),F.cerrar().then(()=>process.exit(127));}),n.on("exit",(o,r)=>{
|
|
391
|
+
F.cerrar().then(()=>process.exit(o??(r?1:0)));});}else console.log(`[bvsala gateway] apunta tu terminal (o usa \`bvsala ${ot.join("|")}\`): ANTHROPIC_BASE_URL=http://127.0.0.1:${F.puerto} claude \xB7 \
|
|
392
|
+
bvsala doctor para el resto`);var Pn=async()=>{await F.cerrar(),process.exit(0);};process.on("SIGINT",()=>{Pn();});process.on("SIGTERM",()=>{Pn();});
|