@bivelio/savings-layer 0.4.16 → 0.4.17

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.
@@ -1,39 +1,44 @@
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 P from'zlib';import {connect}from'net';var re="context-management-2025-06-27";function Xe(){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(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=Yt(n.context_management),Buffer.from(JSON.stringify(n),"utf8"))}catch{return null}}var Gt="clear_tool_uses_20250919",Ze="clear_thinking_20251015";function Yt(e){
4
- let t=Xe().edits[0],n=e!==null&&typeof e=="object"&&!Array.isArray(e)?{...e}:{},o=(Array.isArray(n.edits)?n.edits:[]).filter(i=>i!==null&&typeof i=="object"&&!Array.isArray(i)&&i.type!==Gt),r=o.filter(
5
- i=>i.type===Ze),s=o.filter(i=>i.type!==Ze);return {...n,edits:[...r,...s,t]}}function tt(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 nt(e){return e===void 0||e.trim()===""?re:e.split(",").map(n=>n.trim()).
9
- filter(n=>n.length>0).includes(re)?e:`${e},${re}`}var ot=new Set;function A(e,t){ot.has(e)||(ot.add(e),console.warn(t));}var U=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=
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.
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 j from'zlib';import {connect}from'net';var de="context-management-2025-06-27";function Pe(){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 ut(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=cn(n.context_management),r=ln(n.context_management);return n.context_management=un(n.context_management),{cuerpo:Buffer.from(JSON.stringify(n),"utf8"),nuestros:o,triggerDelCliente:r}}catch{
4
+ return null}}function cn(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===Oe);return ct(
5
+ n)!==ct([Pe().edits[0]])}function ln(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
+ Oe);if(n.length===0)return null;let o=Number.POSITIVE_INFINITY;for(let r of n){let s=r.trigger,i=s!==null&&typeof s=="object"&&s.type==="input_tokens"&&typeof s.value=="number"&&Number.isFinite(s.value)&&
7
+ s.value>0?s.value:1e5;i<o&&(o=i);}return o}function ct(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 Oe="\
8
+ clear_tool_uses_20250919",lt="clear_thinking_20251015";function un(t){let e=Pe().edits[0],n=t!==null&&typeof t=="object"&&!Array.isArray(t)?{...t}:{},o=(Array.isArray(n.edits)?n.edits:[]).filter(i=>i!==
9
+ null&&typeof i=="object"&&!Array.isArray(i)&&i.type!==Oe),r=o.filter(i=>i.type===lt),s=o.filter(i=>i.type!==lt);return {...n,edits:[...r,...s,e]}}function dt(t,e){let n=" (se enciende solo si la licenc\
10
+ ia de la org trae context_elision; fail-closed)";return t==="0"?{linea:"elisi\xF3n S4a: APAGADA (BVSALA_GATEWAY_ELISION=0) \u2014 brazo CONTROL",aviso:false}:e?t==="1"?{linea:"elisi\xF3n S4a: ARMADA (BVSALA\
11
+ _GATEWAY_ELISION=1) \u2014 brazo PALANCA"+n,aviso:false}:{linea:"elisi\xF3n S4a: ARMADA por defecto (sin bandera; =0 la apaga) \u2014 brazo PALANCA"+n,aviso:false}:{linea:"elisi\xF3n S4a: NO SE ARMA \u2014 falta BI\
12
+ VELIO_SERVICE_KEY (sin clave no hay org que consultar); este proceso es brazo CONTROL"+(t==="1"?" AUNQUE la bandera diga =1. Abre un terminal nuevo o exporta la clave y relanza":""),aviso:t==="1"}}function pt(t){
13
+ return t===void 0||t.trim()===""?de:t.split(",").map(n=>n.trim()).filter(n=>n.length>0).includes(de)?t:`${t},${de}`}var mt=new Set;function O(t,e){mt.has(t)||(mt.add(t),console.warn(e));}var K="0.4.17",ft="x-bvsala-version";var J=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=
14
+ 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.
11
15
  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.
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??
16
+ 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??
13
17
  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.
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.
15
- fetch;if(!t)return;let n=this.buffer.splice(0,this.maxBatch);try{let o=n.map(s=>this.toWire(s)),r=await t(this.options.url,{method:"POST",headers:{"content-type":"application/json",authorization:`Bear\
16
- er ${this.options.serviceAccountKey}`},body:JSON.stringify(o)});r.ok?this.fallosSeguidos=0:r.status>=500?(this.fallosSeguidos++,this.requeue(n),this.avisarDeFallo(`el servidor respondi\xF3 ${r.status}`)):
17
- r.status===401||r.status===403?(A(`metering-auth-${r.status}`,`[bv-sala] el env\xEDo de uso est\xE1 siendo rechazado con HTTP ${r.status} en ${this.options.url}. Revisa 'serviceAccountKey' (\xBFrotada? \xBF\
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?.(r.status)):
19
- (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 HTTP ${r.status}`));}catch(o){this.
20
- fallosSeguidos++,this.requeue(n),this.avisarDeFallo(o instanceof Error?o.message:"error de red");}}avisarDeFallo(t){if(this.options.silenceWarnings)return;let n=this.fallosSeguidos;n<3||(n-3)%12!==0||console.
21
- warn(`[bv-sala] el env\xEDo de uso lleva ${n} intentos seguidos fallando contra ${this.options.url} (${t}). Las peticiones SIGUEN funcionando, pero el uso no est\xE1 llegando: el panel dir\xE1 que no ve tr\xE1\
22
- fico y los asientos facturables saldr\xE1n a cero. Comprueba 'meteringUrl' \u2014 por defecto es \`\${licenseServerUrl}/api/metering/usage\`.`);}requeue(t){this.buffer=[...t,...this.buffer],this.buffer.
23
- length>this.maxBuffer&&(this.buffer.length=this.maxBuffer);}toWire(t){let n=t.report;return {orgId:this.options.orgId??"self",...this.seatId?{seatId:this.seatId}:{},...this.ci?{ci:true}:{},requestId:n.requestId,
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,
25
- compressedInputTokens:n.tokens.compressedInput,baselineOutputTokens:n.tokens.baselineOutput,actualOutputTokens:n.tokens.actualOutput,providerCachedInputTokens:n.tokens.providerCachedInput??0,cacheResult:n.
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}:
27
- {},...n.attribution?.agentId?{agentId:n.attribution.agentId}:{}}}};function se(){return globalThis.process}function Qt(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 Xt(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 Zt(){if(se()?.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 en(e,t=Zt){
30
- if(e.KUBERNETES_SERVICE_HOST||Xt(e))return;let n=e.HOSTNAME??e.COMPUTERNAME??await t();if(!(!n||Qt(n)))return n}async function tn(){let e=se();if(!e||!e.env)return;let t=e.env,n=await en(t),o=[e.platform,
31
- e.arch,e.execPath,n,t.USER??t.USERNAME??t.LOGNAME,t.HOME??t.USERPROFILE].filter(r=>typeof r=="string"&&r.length>0);return o.length?o.join("|"):void 0}var nn=["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 ie(){let e=se()?.env;if(!e)
33
- return false;for(let t of nn){let n=e[t];if(n&&n!=="false"&&n!=="0")return true}return false}async function on(e,t){let n=globalThis.crypto,o=new TextEncoder;if(n?.subtle)try{let i=await n.subtle.importKey("raw",
34
- o.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await n.subtle.sign("HMAC",i,o.encode(t));return [...new Uint8Array(a)].map(l=>l.toString(16).padStart(2,"0")).join("")}catch{}let r=2166136261,s=`${e}\
35
- |${t}`;for(let i=0;i<s.length;i++)r^=s.charCodeAt(i),r=Math.imul(r,16777619);return (r>>>0).toString(16).padStart(8,"0")}async function ae(e){let n=se()?.env?.BVSALA_SEAT_ID;if(n&&rn.test(n))return n;let o=await tn();
36
- if(!o)return;let r=await on(e,o);if(r)return `m-${r.slice(0,32)}`}var rn=/^[A-Za-z0-9._:/-]{1,128}$/;var we={"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},
18
+ 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.
19
+ 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\
20
+ er ${this.options.serviceAccountKey}`,[ft]:`${this.options.surface??"sdk"}/${K}`},body:JSON.stringify(o)});r.ok?this.fallosSeguidos=0:r.status>=500?(this.fallosSeguidos++,this.requeue(n),this.avisarDeFallo(
21
+ `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}\
22
+ . 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.`),
23
+ 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\
24
+ 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.
25
+ 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 \
26
+ 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){
27
+ 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}:
28
+ {},...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,
29
+ eliminatedInputTokens:n.tokens.eliminatedInput,compressedInputTokens:n.tokens.compressedInput,baselineOutputTokens:n.tokens.baselineOutput,actualOutputTokens:n.tokens.actualOutput,providerCachedInputTokens:n.
30
+ tokens.providerCachedInput??0,cacheResult:n.cache.result,...n.cost.eliminatedInputFloorCost!==void 0&&Number.isFinite(n.cost.eliminatedInputFloorCost)&&n.cost.eliminatedInputFloorCost>0&&n.tokens.eliminatedInput>
31
+ 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.
32
+ attribution?.sessionId?{sessionId:n.attribution.sessionId}:{},...n.attribution?.agentId?{agentId:n.attribution.agentId}:{}}}};function pe(){return globalThis.process}function dn(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\
33
+ ]";return new RegExp(`-${e}{8,10}-${e}{5}$`).test(t)}function pn(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??
34
+ t.NETLIFY)}async function mn(){if(pe()?.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 fn(t,e=mn){
35
+ if(t.KUBERNETES_SERVICE_HOST||pn(t))return;let n=t.HOSTNAME??t.COMPUTERNAME??await e();if(!(!n||dn(n)))return n}async function hn(){let t=pe();if(!t||!t.env)return;let e=t.env,n=await fn(e),o=[t.platform,
36
+ 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 gn=["CI","CONTINUOUS_INTEGRATION","GITHUB_ACTI\
37
+ ONS","GITLAB_CI","CIRCLECI","TRAVIS","JENKINS_URL","BUILDKITE","TF_BUILD","TEAMCITY_VERSION","BITBUCKET_BUILD_NUMBER","CODEBUILD_BUILD_ID","HEROKU_TEST_RUN_ID","DRONE"];function me(){let t=pe()?.env;if(!t)
38
+ return false;for(let e of gn){let n=t[e];if(n&&n!=="false"&&n!=="0")return true}return false}async function bn(t,e){let n=globalThis.crypto,o=new TextEncoder;if(n?.subtle)try{let i=await n.subtle.importKey("raw",
39
+ o.encode(t),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await n.subtle.sign("HMAC",i,o.encode(e));return [...new Uint8Array(a)].map(c=>c.toString(16).padStart(2,"0")).join("")}catch{}let r=2166136261,s=`${t}\
40
+ |${e}`;for(let i=0;i<s.length;i++)r^=s.charCodeAt(i),r=Math.imul(r,16777619);return (r>>>0).toString(16).padStart(8,"0")}async function fe(t){let n=pe()?.env?.BVSALA_SEAT_ID;if(n&&vn.test(n))return n;let o=await hn();
41
+ if(!o)return;let r=await bn(t,o);if(r)return `m-${r.slice(0,32)}`}var vn=/^[A-Za-z0-9._:/-]{1,128}$/;var he={"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},
37
42
  "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,
38
43
  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},
39
44
  "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},
@@ -50,186 +55,208 @@ able-5":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:.001},"claude-fable-5-1
50
55
  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,
51
56
  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\
52
57
  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,
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 rt(e,t,n){
54
- if(!n)return;let o=e[n];if(o)return o;let r=n.lastIndexOf("/"),s=r>=0?n.slice(r+1):n,i=e[s];if(i)return i;for(let a of t){if(!s.startsWith(a))continue;let l=s.charAt(a.length);if(l!==""&&l!=="-"&&l!==
55
- "."&&l!=="_")continue;let d=s.slice(a.length+1);if(!(/^\d/.test(d)&&!/^\d{4}/.test(d)))return e[a]}}function Te(e){return Object.keys(e).sort((t,n)=>n.length-t.length)}var sn=Te(we);function j(e){return rt(
56
- we,sn,e)}var N=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(`
58
+ 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 ht(t,e,n){
59
+ if(!n)return;let o=t[n];if(o)return o;let r=n.lastIndexOf("/"),s=r>=0?n.slice(r+1):n,i=t[s];if(i)return i;for(let a of e){if(!s.startsWith(a))continue;let c=s.charAt(a.length);if(c!==""&&c!=="-"&&c!==
60
+ "."&&c!=="_")continue;let p=s.slice(a.length+1);if(!(/^\d/.test(p)&&!/^\d{4}/.test(p)))return t[a]}}function De(t){return Object.keys(t).sort((e,n)=>n.length-e.length)}var yn=De(he);function B(t){return ht(
61
+ he,yn,t)}Object.fromEntries(Object.keys(he).map(t=>[t,t]));function W(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 Me(t){let e=t.
62
+ toLowerCase();return e.startsWith("claude")||e.startsWith("anthropic/")?2:W(t)}var U=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(`
57
63
 
58
64
  `))>=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;
59
- let s=/^data: (.+)$/m.exec(o)?.[1];if(s)try{let i=JSON.parse(s),a=st(i.context_management);a&&(this.elisionObservada=a);let l=i.usage??i.message?.usage;if(l){let d=l.cache_creation||this.uso?.cache_creation?
60
- {...this.uso?.cache_creation,...l.cache_creation}:void 0;this.uso={...this.uso,...l,...d?{cache_creation:d}:{}};}}catch{}}}usage(){return this.uso}usageFinal(){return (this.eventos.message_delta??0)>0?this.
61
- uso:null}elision(){return this.elisionObservada}};function st(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 o of t){
62
- let r=o.cleared_input_tokens;typeof r=="number"&&Number.isFinite(r)&&r>0&&(n+=r);}return {borrados:t.length,tokensLimpiados:n}}function it(e){try{let t=JSON.parse(typeof e=="string"?e:e.toString("utf8"));
63
- return st(t.context_management)}catch{return null}}var ce=class{resto="";uso=null;eventos={};observar(t){this.resto+=typeof t=="string"?t:t.toString("utf8");let n;for(;(n=this.resto.indexOf(`
65
+ let s=/^data: (.+)$/m.exec(o)?.[1];if(s)try{let i=JSON.parse(s),a=gt(i.context_management);a&&(this.elisionObservada=a);let c=i.usage??i.message?.usage;if(c){let p=c.cache_creation||this.uso?.cache_creation?
66
+ {...this.uso?.cache_creation,...c.cache_creation}:void 0;this.uso={...this.uso,...c,...p?{cache_creation:p}:{}};}}catch{}}}usage(){return this.uso}usageFinal(){return (this.eventos.message_delta??0)>0?this.
67
+ uso:null}elision(){return this.elisionObservada}};function kn(t,e){if(!e||e.atribuible!==true||!(e.tokensLimpiadosToolUses>0))return 0;let n=t.cachedInputPer1k;return typeof n!="number"||!Number.isFinite(
68
+ n)||n<=0?0:e.tokensLimpiadosToolUses/1e3*n}function gt(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.
69
+ 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 bt(t){
70
+ try{let e=JSON.parse(typeof t=="string"?t:t.toString("utf8"));return gt(e.context_management)}catch{return null}}var ge=class{resto="";uso=null;eventos={};observar(e){this.resto+=typeof e=="string"?e:
71
+ e.toString("utf8");let n;for(;(n=this.resto.indexOf(`
64
72
 
65
73
  `))>=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 i=JSON.
66
- parse(s);if((r??i.type)!=="response.completed")continue;let a=i.response?.usage;a&&(this.uso=an(a));}catch{}}}usage(){return this.uso}usageFinal(){return this.uso}};function an(e){let t=Math.max(0,e.input_tokens??
67
- 0),n=Math.min(Math.max(0,e.input_tokens_details?.cached_tokens??0),t),o=Math.min(Math.max(0,e.input_tokens_details?.cache_write_tokens??0),t-n);return {input_tokens:t-n-o,output_tokens:Math.max(0,e.output_tokens??
68
- 0),cache_read_input_tokens:n,cache_creation_input_tokens:o}}var Ee=1.25,le=2;function at(e,t){let n=j(e);if(!n)return null;let o=t.input_tokens??0,r=t.output_tokens??0,s=t.cache_read_input_tokens??0,i=t.
69
- cache_creation,a=t.cache_creation_input_tokens??(i?.ephemeral_5m_input_tokens??0)+(i?.ephemeral_1h_input_tokens??0),l=Math.min(i?.ephemeral_1h_input_tokens??0,a),d=n.cachedInputPer1k??n.inputPer1k;return {
70
- costeUsd:o/1e3*n.inputPer1k+s/1e3*d+(a-l)/1e3*n.inputPer1k*Re(e)+l/1e3*n.inputPer1k*le+r/1e3*n.outputPer1k,precio:n,tokens:{entrada:o,salida:r,cacheLeida:s,cacheEscrita:a,cacheEscrita1h:l}}}function ct(e,t){
71
- let o=Ce(e,t)?.model;return typeof o=="string"?o:""}function Ce(e,t){try{let n=e,o={maxOutputLength:cn};switch((t??"").trim().toLowerCase()){case "gzip":case "x-gzip":n=P.gunzipSync(e,o);break;case "defl\
72
- ate":n=P.inflateSync(e,o);break;case "br":n=P.brotliDecompressSync(e,o);break;case "zstd":{let r=P.zstdDecompressSync;if(typeof r!="function")return null;n=r(e,o);break}default:break}return JSON.parse(n.
73
- toString("utf8"))}catch{return null}}var cn=5*1024*1024;function lt(){return typeof P.zstdDecompressSync=="function"}function Re(e){let t=e.toLowerCase();return t.startsWith("gpt-")||t.startsWith("o1")||
74
- t.startsWith("o3")||t.startsWith("o4")?/^gpt-5\.6/.test(t)?Ee:1:t.startsWith("gemini")?1:Ee}function Ae(e){try{return JSON.parse(typeof e=="string"?e:e.toString("utf8")).usage??null}catch{return null}}
75
- function ut(e,t,n,o,r,s){return mt(e,t,n,false,o,r,s)}function dt(e,t,n,o){return mt(e,t,n,true,o)}function pt(e,t,n,o,r){return {requestId:e,model:t,...r&&(r.sessionId||r.agentId)?{attribution:r}:{},calls:{
74
+ parse(s);if((r??i.type)!=="response.completed")continue;let a=i.response?.usage;a&&(this.uso=xn(a));}catch{}}}usage(){return this.uso}usageFinal(){return this.uso}};function xn(t){let e=Math.max(0,t.input_tokens??
75
+ 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??
76
+ 0),cache_read_input_tokens:n,cache_creation_input_tokens:o}}function vt(t,e){let n=B(t);if(!n)return null;let o=e.input_tokens??0,r=e.output_tokens??0,s=e.cache_read_input_tokens??0,i=e.cache_creation,
77
+ a=e.cache_creation_input_tokens??(i?.ephemeral_5m_input_tokens??0)+(i?.ephemeral_1h_input_tokens??0),c=Math.min(i?.ephemeral_1h_input_tokens??0,a),p=n.cachedInputPer1k??n.inputPer1k;return {costeUsd:o/
78
+ 1e3*n.inputPer1k+s/1e3*p+(a-c)/1e3*n.inputPer1k*W(t)+c/1e3*n.inputPer1k*2+r/1e3*n.outputPer1k,precio:n,tokens:{entrada:o,salida:r,cacheLeida:s,cacheEscrita:a,cacheEscrita1h:c}}}function yt(t,e){let o=je(
79
+ t,e)?.model;return typeof o=="string"?o:""}function je(t,e){try{let n=t,o={maxOutputLength:Sn};switch((e??"").trim().toLowerCase()){case "gzip":case "x-gzip":n=j.gunzipSync(t,o);break;case "deflate":n=j.inflateSync(
80
+ t,o);break;case "br":n=j.brotliDecompressSync(t,o);break;case "zstd":{let r=j.zstdDecompressSync;if(typeof r!="function")return null;n=r(t,o);break}default:break}return JSON.parse(n.toString("utf8"))}catch{
81
+ return null}}var Sn=5*1024*1024;function kt(){return typeof j.zstdDecompressSync=="function"}function $e(t){try{return JSON.parse(typeof t=="string"?t:t.toString("utf8")).usage??null}catch{return null}}
82
+ function xt(t,e,n,o,r,s){return Tt(t,e,n,false,o,r,s)}function St(t,e,n,o){return Tt(t,e,n,true,o)}function wt(t,e,n,o,r){return {requestId:t,model:e,...r&&(r.sessionId||r.agentId)?{attribution:r}:{},calls:{
76
83
  avoidedLlm:0,actualLlm:0},tokens:{baselineInput:0,actualInput:0,eliminatedInput:0,compressedInput:0,baselineOutput:0,actualOutput:0,providerCachedInput:0},cache:{result:"miss"},cost:{baselineEstimate:n,
77
- actual:o,netSavings:n>0?Math.max(-100,Math.min(1,(n-o)/n)):0,basis:"shadow"}}}function mt(e,t,n,o,r,s,i){let a=n.tokens.entrada+n.tokens.cacheLeida+n.tokens.cacheEscrita,l=n.tokens.cacheEscrita-n.tokens.
78
- cacheEscrita1h,d=!o&&i&&i.rebajadas>0&&i.yaEran5m===0&&l>0?l/1e3*n.precio.inputPer1k*(le-Ee):0,m=n.costeUsd+d;return {requestId:e,model:t,...r&&(r.sessionId||r.agentId)?{attribution:r}:{},calls:o?{avoidedLlm:1,
79
- actualLlm:0}:{avoidedLlm:0,actualLlm:1},tokens:{baselineInput:a,actualInput:o?0:a,eliminatedInput:o?0:s?.tokensLimpiados??0,compressedInput:0,baselineOutput:n.tokens.salida,actualOutput:o?0:n.tokens.salida,
80
- providerCachedInput:o?0:n.tokens.cacheLeida},cache:{result:o?"singleflight":"miss"},cost:o?{baselineEstimate:n.costeUsd,actual:0,netSavings:1,basis:"estimated"}:{baselineEstimate:m,actual:n.costeUsd,netSavings:m>
81
- 0?Math.max(-100,Math.min(1,d/m)):0,basis:"measured"}}}var un=1024,G=120,dn=8,pn=256*1024,mn=/error|exception|traceback|warn|fatal|fail|panic|assert|denied|refused|timeout|\bat\s+\S+:\d+/i,ht=/^\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)/;
82
- function fn(e){return Buffer.byteLength(typeof e=="string"?e:JSON.stringify(e??""))}function hn(e){return typeof e=="string"?e:Array.isArray(e)?e.map(t=>t&&typeof t=="object"&&typeof t.text=="string"?
83
- t.text:"").join(`
84
- `):""}var gn=/^\s*\d+[\t→]/;function gt(e){return e.replace(gn,"")}function bn(e){if(!e)return "otro";let t=e.split(`
85
- `),n=Math.max(1,t.length),o=0,r=0,s=0;for(let i of t){let a=gt(i);(/^[+-](?![+-])/.test(a)||a.startsWith("@@")||a.startsWith("diff --git"))&&(o+=1),ht.test(a)&&(r+=1),(/^\s*(\d{4}-\d{2}-\d{2}|\[\d|\d{2}:\d{2}:\d{2})/.
86
- test(a)||/\b(INFO|DEBUG|TRACE|WARN|ERROR)\b/.test(a))&&(s+=1);}return o/n>.25?"diff":s/n>.3?"log":r/n>.08?"codigo":"otro"}function vn(e,t){if(t==="diff"||t==="otro")return Buffer.byteLength(e);let n=e.
84
+ actual:o,netSavings:n>0?Math.max(-100,Math.min(1,(n-o)/n)):0,basis:"shadow"}}}function Tt(t,e,n,o,r,s,i){let a=n.tokens.entrada+n.tokens.cacheLeida+n.tokens.cacheEscrita,c=n.tokens.cacheEscrita-n.tokens.
85
+ cacheEscrita1h,p=!o&&i&&i.rebajadas>0&&i.yaEran5m===0&&c>0?c/1e3*n.precio.inputPer1k*(2-1.25):0,f=n.costeUsd+p,l=o?0:kn(n.precio,s);return {requestId:t,model:e,...r&&(r.sessionId||r.agentId)?{attribution:r}:
86
+ {},calls:o?{avoidedLlm:1,actualLlm:0}:{avoidedLlm:0,actualLlm:1},tokens:{baselineInput:a,actualInput:o?0:a,eliminatedInput:o?0:s?.tokensLimpiados??0,compressedInput:0,baselineOutput:n.tokens.salida,actualOutput:o?
87
+ 0:n.tokens.salida,providerCachedInput:o?0:n.tokens.cacheLeida},cache:{result:o?"singleflight":"miss"},cost:o?{baselineEstimate:n.costeUsd,actual:0,netSavings:1,basis:"estimated"}:{baselineEstimate:f,actual:n.
88
+ costeUsd,netSavings:f>0?Math.max(-100,Math.min(1,p/f)):0,basis:"measured",...l>0?{eliminatedInputFloorCost:l}:{}}}}var wn=1024,se=120,Tn=8,En=256*1024,Cn=/error|exception|traceback|warn|fatal|fail|panic|assert|denied|refused|timeout|\bat\s+\S+:\d+/i,At=/^\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)/;
89
+ function An(t){return Buffer.byteLength(typeof t=="string"?t:JSON.stringify(t??""))}function _n(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&typeof e.text=="string"?
90
+ e.text:"").join(`
91
+ `):""}var Rn=/^\s*\d+[\t→]/;function _t(t){return t.replace(Rn,"")}function In(t){if(!t)return "otro";let e=t.split(`
92
+ `),n=Math.max(1,e.length),o=0,r=0,s=0;for(let i of e){let a=_t(i);(/^[+-](?![+-])/.test(a)||a.startsWith("@@")||a.startsWith("diff --git"))&&(o+=1),At.test(a)&&(r+=1),(/^\s*(\d{4}-\d{2}-\d{2}|\[\d|\d{2}:\d{2}:\d{2})/.
93
+ test(a)||/\b(INFO|DEBUG|TRACE|WARN|ERROR)\b/.test(a))&&(s+=1);}return o/n>.25?"diff":s/n>.3?"log":r/n>.08?"codigo":"otro"}function Pn(t,e){if(e==="diff"||e==="otro")return Buffer.byteLength(t);let n=t.
87
94
  split(`
88
- `),o=new Set;for(let s=0;s<n.length;s++){let i=gt(n[s]);(t==="log"?mn.test(i):ht.test(i))&&(o.add(s),t==="log"&&(s>0&&o.add(s-1),s<n.length-1&&o.add(s+1)));}let r=G;for(let s of o)r+=Buffer.byteLength(
89
- n[s])+1;return Math.min(r,Buffer.byteLength(e))}function bt(e){let t=[],n=(o,r)=>{let s=fn(r),i={clave:createHash("sha256").update(typeof r=="string"?r:JSON.stringify(r??"")).digest("hex").slice(0,16),tipo:o,
90
- bytes:s,bytesV1:s,clase:"otro",esError:false};if(o.endsWith(":tool_result")&&r&&typeof r=="object"){let a=r;i.esError=a.is_error===true;let l=hn(a.content);i.clase=bn(l);let d=s-Buffer.byteLength(l);i.bytesV1=
91
- Math.min(s,Math.max(0,d)+vn(l,i.clase));}t.push(i);};if((e.system??void 0)!==void 0&&n("system",e.system),Array.isArray(e.tools))for(let o of e.tools)n("tools",o);for(let o of Array.isArray(e.messages)?
92
- e.messages:[]){if(!o||typeof o!="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))
93
- for(let i of r.content)n(`${s}:${i?.type??"?"}`,i);}return t}function yn(){return {nacimiento:new Map,turno:0,elididosV2m:new Set}}function kn(e,t){let n=e.turno++;for(let o of t)e.nacimiento.has(o.clave)||
94
- e.nacimiento.set(o.clave,n);return n}function vt(e,t,n,o,r=pn){let s=t.reduce((c,f,u)=>f.tipo.endsWith(":tool_result")?u:c,-1),i=(c,f)=>c.tipo.endsWith(":tool_result")&&c.bytes>=un&&f!==s;return t.map((c,f)=>{if(!i(c,f))return {clave:c.clave,bytes:c.bytes};let u=o-(n.nacimiento.get(c.clave)??o);return u>=2&&u*c.bytes/1024>=dn?{clave:`${c.clave}:e`,bytes:G}:{clave:c.clave,bytes:c.bytes}});
95
- }function xn(e){let t=j(e);return t?{lecturaPer1k:t.cachedInputPer1k??t.inputPer1k,escrituraPer1k:t.
96
- inputPer1k*Re(e),escritura1hPer1k:t.inputPer1k*le}:null}function ft(){return {lecturaUsd:0,escrituraUsd:0,totalUsd:0,tokensLeidos:0,tokensEscritos:0,tokensInvalidados:0,invalidacionUsd:0}}var Sn={"1h":36e5,
97
- "5m":3e5},Y=class{constructor(t){this.transformar=t;}transformar;estado=yn();previo=[];hayPrevio=false;atPrevio=0;acumulado=ft();paso(t){let n=ft(),o=kn(this.estado,t.bloques),r=xn(t.model),s=this.transformar(
98
- t.bloques,this.estado,o);if(!r||t.entradaReal<=0)return this.previo=s,this.hayPrevio=true,this.atPrevio=t.at,n;let i=t.bloques.reduce((p,g)=>p+g.bytes,0),a=i>0?t.entradaReal/i:0,l=Sn[t.escritura1h?"1h":
99
- "5m"],d=this.hayPrevio&&t.at-this.atPrevio>l,m=0;if(!d)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 c=this.previo.slice(m),f=0,
100
- u=t.escritura1h?r.escritura1hPer1k:r.escrituraPer1k;for(let p=0;p<s.length;p++){let g=s[p],y=g.bytes*a;if(p<m){n.tokensLeidos+=y,n.lecturaUsd+=y/1e3*r.lecturaPer1k;continue}if(n.tokensEscritos+=y,n.escrituraUsd+=
101
- y/1e3*u,!d){let k=f;for(;k<c.length&&c[k].clave!==g.clave;)k+=1;k<c.length&&(c[k].bytes===g.bytes&&(n.tokensInvalidados+=y,n.invalidacionUsd+=y/1e3*(u-r.lecturaPer1k)),f=k+1);}}return this.previo=s,this.
102
- 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.
103
- tokensLeidos+=n.tokensLeidos,this.acumulado.tokensEscritos+=n.tokensEscritos,this.acumulado.tokensInvalidados+=n.tokensInvalidados,this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function yt(e){return e.map(t=>({clave:t.clave,bytes:t.bytes}))}var Tn=64,ue=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),o=(t.uso.
104
- input_tokens??0)+(t.uso.cache_read_input_tokens??0)+n;if(o<=0)return null;let r={bloques:bt(t.cuerpo),at:t.at,model:t.model,entradaReal:o,escritura1h:(t.uso.cache_creation?.ephemeral_1h_input_tokens??
105
- 0)>0};if(r.bloques.length===0)return null;let s=this.cadenaPara(this.clave(t)),i=s.base.paso(r),a=s.v0.paso(r);return i.totalUsd<=0&&a.totalUsd<=0?null:{baselineUsd:i.totalUsd,politicaUsd:a.totalUsd}}clave(t){
106
- 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(
107
- "hex").slice(0,16)}\xB7${t.model}`}cadenaPara(t){let n=this.cadenas.get(t);if(!n&&(n={base:new Y(o=>yt(o)),v0:new Y((o,r,s)=>vt("v0",o,r,s)),ultimoUso:0},this.cadenas.set(t,n),this.cadenas.size>Tn)){let o=null,
108
- r=1/0;for(let[s,i]of this.cadenas)i.ultimoUso<r&&(r=i.ultimoUso,o=s);o!==null&&this.cadenas.delete(o);}return n.ultimoUso=Date.now(),n}};var de=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.
109
- 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.
110
- 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.
111
- 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(r=>typeof r=="string")){this.cerrar("entitlements con\
95
+ `),o=new Set;for(let s=0;s<n.length;s++){let i=_t(n[s]);(e==="log"?Cn.test(i):At.test(i))&&(o.add(s),e==="log"&&(s>0&&o.add(s-1),s<n.length-1&&o.add(s+1)));}let r=se;for(let s of o)r+=Buffer.byteLength(
96
+ n[s])+1;return Math.min(r,Buffer.byteLength(t))}var On=(t,e)=>t==="cache_control"?void 0:e;function Dn(t){if(typeof t=="string")return `text:${t}`;if(!t||typeof t!="object"||Array.isArray(t))return `jso\
97
+ 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,On)}`}
98
+ function Mn(t){return createHash("sha256").update(Dn(t)).digest("hex").slice(0,16)}function Ln(t){if(!t||typeof t!="object"||Array.isArray(t))return null;let e=t.cache_control;return !e||typeof e!="object"?null:
99
+ e.ttl==="1h"?"1h":"5m"}function Rt(t){let e=[],n=(o,r)=>{let s=An(r),i={clave:Mn(r),tipo:o,marca:Ln(r),bytes:s,bytesV1:s,clase:"otro",esError:false};if(o.endsWith(":tool_result")&&r&&typeof r=="object"){
100
+ let a=r;i.esError=a.is_error===true;let c=_n(a.content);i.clase=In(c);let p=s-Buffer.byteLength(c);i.bytesV1=Math.min(s,Math.max(0,p)+Pn(c,i.clase));}e.push(i);};if(Array.isArray(t.tools))for(let o of t.tools)
101
+ 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!=
102
+ "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 i of r.content)n(`${s}\
103
+ :${i?.type??"?"}`,i);}return e}function jn(){return {nacimiento:new Map,turno:0,elididosV2m:new Set}}function $n(t,e){let n=t.turno++;for(let o of e)t.nacimiento.has(o.clave)||t.nacimiento.set(o.clave,n);
104
+ return n}function It(t,e,n,o,r=En){let s=e.reduce((l,h,u)=>h.tipo.endsWith(":tool_result")?u:l,-1),i=(l,h)=>l.tipo.endsWith(":tool_result")&&l.bytes>=wn&&h!==s;return e.map((l,h)=>{if(!i(l,
105
+ h))return {clave:l.clave,bytes:l.bytes};let u=o-(n.nacimiento.get(l.clave)??o);return u>=2&&u*l.bytes/1024>=Tn?{clave:`${l.clave}:e`,bytes:se}:{clave:l.clave,bytes:l.bytes}});}function Nn(t){let e=B(t);return e?{inputPer1k:e.inputPer1k,lecturaPer1k:e.cachedInputPer1k??e.inputPer1k,escrituraPer1k:e.inputPer1k*
106
+ W(t),escritura1hPer1k:e.inputPer1k*Me(t)}:null}function Et(){return {lecturaUsd:0,escrituraUsd:0,entradaUsd:0,totalUsd:0,tokensLeidos:0,tokensEscritos:0,tokensEntrada:0,tokensInvalidados:0,invalidacionUsd:0}}
107
+ var ze={"1h":36e5,"5m":3e5},zn=20,Bn=6e3,Un=2e4,G=class{constructor(e=Un){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?
108
+ o:null}escribir(e,n,o){this.entradas.delete(e),this.entradas.set(e,{expira:n+ze[o],ttl:o}),this.entradas.size>this.tope&&this.podar(n);}refrescar(e,n){let o=this.entradas.get(e);o&&(this.entradas.delete(
109
+ e),this.entradas.set(e,{expira:n+ze[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().
110
+ value;if(n===void 0)break;this.entradas.delete(n);}}};function Vn(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(
111
+ "|").update(e[r]).digest("hex").slice(0,32),n[r]=o;return n}function Fn(t){let e=new Array(t.length),n=-1,o="";for(let r=0;r<t.length;r++){let s=t[r],i=s.endsWith(":tool_use")||s.endsWith(":tool_resul\
112
+ t");i&&s===o||(n+=1),o=i?s:"",e[r]=n;}return e}function Ct(t,e){return t.endsWith(":image")?Math.min(e,Bn):e}var ie=class{constructor(e,n){this.transformar=e;this.cache=n??new G;}transformar;estado=jn();cache;previo=[];previoUltimoBp=-1;previoTtl="\
113
+ 5m";hayPrevio=false;atPrevio=0;acumulado=Et();paso(e){let n=Et(),o=$n(this.estado,e.bloques),r=Nn(e.model),s=this.transformar(e.bloques,this.estado,o);if(!r||e.entradaReal<=0||s.length===0)return this.previo=
114
+ s,this.previoUltimoBp=-1,this.previoTtl="5m",this.hayPrevio=true,this.atPrevio=e.at,n;let i=s.map((d,x)=>e.bloques[x]?.tipo??""),a=s.map((d,x)=>e.bloques[x]?.marca??null),c=e.bloques.reduce((d,x)=>d+Ct(
115
+ x.tipo,x.bytes),0),p=c>0?e.entradaReal/c:0,f=s.map((d,x)=>Ct(i[x],d.bytes)*p),l=Vn(e.model,s.map(d=>d.clave)),h=Fn(i),u=a.map((d,x)=>d?x:-1).filter(d=>d>=0);if(u.length===0){for(let d=0;d<s.length;d++)
116
+ n.tokensEntrada+=f[d],n.entradaUsd+=f[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+=
117
+ n.tokensEntrada,this.acumulado.entradaUsd+=n.entradaUsd,this.acumulado.totalUsd+=n.totalUsd,n}let m=-1;for(let d of u){let x=h[d]-(zn-1);for(let S=d;S>=0&&h[S]>=x;S--)if(this.cache.viva(l[S],e.at)){S>
118
+ m&&(m=S);break}}for(let d=0;d<=m;d++)this.cache.refrescar(l[d],e.at);let v=u[u.length-1];for(let d of u)d>m&&this.cache.escribir(l[d],e.at,a[d]);let E=0,A=this.hayPrevio&&e.at-this.atPrevio>ze[this.previoTtl]?
119
+ []:this.previo.slice(m+1,this.previoUltimoBp+1),g=0;for(let d=0;d<s.length;d++){let x=s[d],S=f[d];if(d<=m){n.tokensLeidos+=S,n.lecturaUsd+=S/1e3*r.lecturaPer1k;continue}if(d>v){n.tokensEntrada+=S,n.entradaUsd+=
120
+ S/1e3*r.inputPer1k;continue}for(;u[E]<d;)E+=1;let D=a[u[E]]==="1h"?r.escritura1hPer1k:r.escrituraPer1k;n.tokensEscritos+=S,n.escrituraUsd+=S/1e3*D;let I=g;for(;I<A.length&&A[I].clave!==x.clave;)I+=1;I<
121
+ A.length&&(A[I].bytes===x.bytes&&(n.tokensInvalidados+=S,n.invalidacionUsd+=S/1e3*(D-r.lecturaPer1k)),g=I+1);}return this.previo=s,this.previoUltimoBp=v,this.previoTtl=a[v]??"5m",this.hayPrevio=true,this.
122
+ 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.
123
+ totalUsd+=n.totalUsd,this.acumulado.tokensLeidos+=n.tokensLeidos,this.acumulado.tokensEscritos+=n.tokensEscritos,this.acumulado.tokensEntrada+=n.tokensEntrada,this.acumulado.tokensInvalidados+=n.tokensInvalidados,
124
+ this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function Pt(t){return t.map(e=>({clave:e.clave,bytes:e.bytes}))}var Hn=64,ve=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??
125
+ 0),o=(e.uso.input_tokens??0)+(e.uso.cache_read_input_tokens??0)+n;if(o<=0)return null;let r={bloques:Rt(e.cuerpo),at:e.at,model:e.model,entradaReal:o,escritura1h:(e.uso.cache_creation?.ephemeral_1h_input_tokens??
126
+ 0)>0};if(r.bloques.length===0)return null;let s=this.cadenaPara(this.clave(e),e.model),i=s.base.paso(r),a=s.v0.paso(r);return i.totalUsd<=0&&a.totalUsd<=0?null:{baselineUsd:i.totalUsd,politicaUsd:a.totalUsd}}clave(e){
127
+ 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(
128
+ "hex").slice(0,16)}\xB7${e.model}`}cachesDe(e){let n=this.cachesPorModelo.get(e);return n||(n={base:new G,v0:new G},this.cachesPorModelo.set(e,n)),n}cadenaPara(e,n){let o=this.cadenas.get(e);if(!o){let r=this.
129
+ cachesDe(n);if(o={base:new ie(s=>Pt(s),r.base),v0:new ie((s,i,a)=>It("v0",s,i,a),r.v0),ultimoUso:0},this.cadenas.set(e,o),this.cadenas.size>Hn){let s=null,i=1/0;for(let[a,c]of this.cadenas)c.ultimoUso<
130
+ i&&(i=c.ultimoUso,s=a);s!==null&&this.cadenas.delete(s);}}return o.ultimoUso=Date.now(),o}};var ye=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.
131
+ 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.
132
+ 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.
133
+ 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\
112
134
  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=
113
- Date.now()+o,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\
114
- titlements no disponibles (${t}) \u2014 palanca apagada (fail-closed)`));}};var Cn=.3,Rn=4096,An=(e,t)=>e==="cache_control"?void 0:t;function _e(e){return e===void 0?"":JSON.stringify(e,An)??""}function Ie(e){return createHash("sha1").update(e).digest("base64url").slice(0,16)}function Oe(e,t){
115
- if(t!==void 0&&t!==""&&t!=="identity")return null;try{let n=JSON.parse(e.toString("utf8"));if(n===null||typeof n!="object"||Array.isArray(n))return null;let o=n;return typeof o.model!="string"||!Array.
116
- isArray(o.messages)?null:o}catch{return null}}function kt(e){let t=_e(e.system),n=_e(e.tools),o=Array.isArray(e.messages)?e.messages.slice(0,Rn):[],r=[],s=[];for(let i of o){let a=_e(i);r.push(Ie(a)),
117
- s.push(Buffer.byteLength(a,"utf8"));}return {system:Ie(t),tools:Ie(n),mensajes:r,bytes:s,bytesFijos:Buffer.byteLength(t,"utf8")+Buffer.byteLength(n,"utf8")}}function xt(e,t){if(e===void 0||e.system!==t.
118
- system||e.tools!==t.tools)return 1;let n=t.bytesFijos;for(let s of t.bytes)n+=s;if(n<=0)return 1;let o=0;for(;o<e.mensajes.length&&o<t.mensajes.length&&e.mensajes[o]===t.mensajes[o];)o++;let r=0;for(let s=o;s<
119
- t.bytes.length;s++)r+=t.bytes[s]??0;return r/n}function St(e){let{fraccionNueva:t,umbral:n=Cn}=e;return t>=n}function Pe(e,t){if(e===null||typeof e!="object")return;if(Array.isArray(e)){for(let r of e)
120
- Pe(r,t);return}let n=e,o=n.cache_control;if(o!==null&&typeof o=="object"&&!Array.isArray(o)){let r=o;r.ttl==="1h"?(r.ttl="5m",t.rebajadas++):(r.ttl==="5m"||r.ttl===void 0)&&t.yaEran5m++;}for(let[r,s]of Object.
121
- entries(n))r!=="cache_control"&&s!==null&&typeof s=="object"&&Pe(s,t);}function wt(e,t){let n=Buffer.isBuffer(e)?Oe(e,t):e;if(n===null)return null;try{let o={rebajadas:0,yaEran5m:0};for(let r of ["syste\
122
- m","messages","tools"])Pe(n[r],o);return o.rebajadas===0?null:{cuerpo:Buffer.from(JSON.stringify(n),"utf8"),rebajadas:o.rebajadas,yaEran5m:o.yaEran5m}}catch{return null}}var pe=class{constructor(t=512,n=3600*1e3){this.maxEntradas=t;this.maxEdadMs=n;}maxEntradas;maxEdadMs;visto=new Map;ultima(t,n){let o=this.visto.get(t);if(o!==void 0){if(n-o.vistoMs>this.maxEdadMs){this.
123
- visto.delete(t);return}return o.huella}}anotar(t,n,o){for(this.visto.delete(t),this.visto.set(t,{huella:n,vistoMs:o});this.visto.size>this.maxEntradas;){let r=this.visto.keys().next();if(r.done===true)break;
124
- this.visto.delete(r.value);}}get tamano(){return this.visto.size}};var De=5*1024*1024,In=["authorization","x-api-key","anthropic-version","anthropic-beta"];function Tt(e,t,n,o=""){return createHash("sha256").update(e).update(`
125
- `).update(t).update(`
135
+ 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\
136
+ titlements no disponibles (${e}) \u2014 palanca apagada (fail-closed)`));}};var Jn=.3,Wn=4096,Gn=(t,e)=>t==="cache_control"?void 0:e;function Be(t){return t===void 0?"":JSON.stringify(t,Gn)??""}function Ue(t){return createHash("sha1").update(t).digest("base64url").slice(0,16)}function Fe(t,e){
137
+ 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))return null;let o=n;return typeof o.model!="string"||!Array.
138
+ isArray(o.messages)?null:o}catch{return null}}function Ot(t){let e=Be(t.system),n=Be(t.tools),o=Array.isArray(t.messages)?t.messages.slice(0,Wn):[],r=[],s=[];for(let i of o){let a=Be(i);r.push(Ue(a)),
139
+ s.push(Buffer.byteLength(a,"utf8"));}return {system:Ue(e),tools:Ue(n),mensajes:r,bytes:s,bytesFijos:Buffer.byteLength(e,"utf8")+Buffer.byteLength(n,"utf8")}}function Dt(t,e){if(t===void 0||t.system!==e.
140
+ system||t.tools!==e.tools)return 1;let n=e.bytesFijos;for(let s of e.bytes)n+=s;if(n<=0)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<
141
+ e.bytes.length;s++)r+=e.bytes[s]??0;return r/n}function Mt(t){let{fraccionNueva:e,umbral:n=Jn}=t;return e>=n}function Ve(t,e){if(t===null||typeof t!="object")return;if(Array.isArray(t)){for(let r of t)
142
+ Ve(r,e);return}let n=t,o=n.cache_control;if(o!==null&&typeof o=="object"&&!Array.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.
143
+ entries(n))r!=="cache_control"&&s!==null&&typeof s=="object"&&Ve(s,e);}function Lt(t,e){let n=Buffer.isBuffer(t)?Fe(t,e):t;if(n===null)return null;try{let o={rebajadas:0,yaEran5m:0};for(let r of ["syste\
144
+ m","messages","tools"])Ve(n[r],o);return o.rebajadas===0?null:{cuerpo:Buffer.from(JSON.stringify(n),"utf8"),rebajadas:o.rebajadas,yaEran5m:o.yaEran5m}}catch{return null}}var ke=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.
145
+ 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;
146
+ this.visto.delete(r.value);}}get tamano(){return this.visto.size}};var qe=5*1024*1024,Qn=["authorization","x-api-key","anthropic-version","anthropic-beta"];function jt(t,e,n,o=""){return createHash("sha256").update(t).update(`
147
+ `).update(e).update(`
126
148
  `).update(o).update(`
127
- `).update(n).digest("hex")}function Et(e){return In.map(t=>`${t}=${e(t)??""}`).join(`
128
- `)}var me=class{enVuelo=new Map;primarias=0;gemelas=0;registrar(t){if(this.enVuelo.has(t))return null;this.primarias+=1;let n,o=new Promise(a=>n=a);this.enVuelo.set(t,{promesa:o,resolver:n});let r=[],
129
- s=0,i=false;return {capturar:a=>{if(!i){if(s+=a.length,s>De){i=true,r.length=0;return}r.push(a);}},terminar:(a,l)=>{let d=!i&&a>=200&&a<300;this.enVuelo.get(t)?.resolver(d?{status:a,headers:l,chunks:r}:null),
130
- 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 o=await n.promesa;return o&&(this.gemelas+=
131
- 1),o}tieneEnVuelo(t){return this.enVuelo.has(t)}};var Dn=["content-encoding","content-length","transfer-encoding"];async function Ct(e={}){let t=(e.upstream??"https://api.anthropic.com").replace(/\/+$/,""),n=e.fetchImpl??fetch,o=e.log??(u=>console.log(
132
- u)),r;if(e.serviceAccountKey){r=new U({url:e.meteringUrl??"https://savings.bivelio.com/api/metering/usage",serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},onAuthError:p=>A(
133
- "gateway-ingest-auth",`[bvsala gateway] la ingesta de uso rechaza la credencial (${p}). El tr\xE1fico sigue fluyendo (avisar, nunca romper), pero este uso no est\xE1 llegando al panel. Revisa BIVELIO_SERVIC\
134
- E_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let u=ie();e.seatId?r.setSeat(e.seatId,u):ae(e.serviceAccountKey).then(p=>r?.setSeat(p,u)).catch(()=>{}),r.start();}else A("gateway-si\
135
- 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.
136
- coalescer?new me:null,i=e.sombra&&r?new ue:null,a=new pe,l=e.elision!==false&&e.serviceAccountKey?new de({url:new URL("/api/org/entitlements",e.meteringUrl??"https://savings.bivelio.com/api/metering/usag\
137
- e").toString(),serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},log:o}):null,d=u=>u==="/v1/messages"?new N:u.endsWith("/responses")?new ce:null,m=(u,p,g,y,k,b,x,M,ee)=>{
138
- if(!r||!g)return;let q=r,L=g,E=ct(p,b);if(!E){A(`gateway-sin-modelo:${k}`,`[bvsala gateway] no se pudo leer el modelo del cuerpo de ${k} (content-encoding: ${b??"ninguno"}); su uso se reenv\xEDa pero no \
139
- se mide.`);return}let T=at(E,g);T?(r.record(y?dt(u,E,T,x):ut(u,E,T,x,M,ee)),o(`[gateway] POST ${k} ${y?"\xB7 COALESCIDA (llamada evitada)":""} \xB7 ${E} \xB7 $${T.costeUsd.toFixed(6)} (in ${T.tokens.entrada}\
140
- , cache\u2191${T.tokens.cacheEscrita}${T.tokens.cacheEscrita1h?` (1h ${T.tokens.cacheEscrita1h})`:""} cache\u2193${T.tokens.cacheLeida}, out ${T.tokens.salida})`+(M?` \xB7 elisi\xF3n: ${M.borrados} bo\
141
- rrado(s), ${M.tokensLimpiados} tok limpiados por el proveedor`:"")),i&&!y&&k==="/v1/messages"&&setImmediate(()=>{try{let $=Ce(p,b);if(!$||typeof $!="object")return;let R=i.observar({cuerpo:$,uso:L,model:E,
142
- at:Date.now(),...x?.sessionId!==void 0?{sessionId:x.sessionId}:{},...x?.agentId!==void 0?{agentId:x.agentId}:{}});if(!R)return;q.record(pt(`${u}:shadow`,E,R.baselineUsd,R.politicaUsd,x)),o(`[gateway] \
143
- sombra \xB7 ${E} \xB7 baseline $${R.baselineUsd.toFixed(6)} \u2192 v0 $${R.politicaUsd.toFixed(6)}`);}catch{}})):A(`gateway-sin-precio:${E}`,`[bvsala gateway] el modelo "${E}" no est\xE1 en el cat\xE1logo de\
144
- precios; su uso se reenv\xEDa pero no se mide.`);},c=createServer(async(u,p)=>{let g=randomUUID(),y=new AbortController;p.on("close",()=>{p.writableEnded||y.abort();});let k=null,b=new URL(u.url??"/",t),x=null,M=Buffer.
145
- alloc(0),ee=false,q=u.headers["content-encoding"],L=Array.isArray(q)?q[0]:q,E=I=>{let w=Array.isArray(I)?I[0]:I;return w!==void 0&&/^[A-Za-z0-9._:/-]{1,128}$/.test(w)?w:void 0},T=E(u.headers["x-claude-co\
146
- de-session-id"]),$=E(u.headers["x-claude-code-agent-id"]),R=T!==void 0||$!==void 0?{...T!==void 0?{sessionId:T}:{},...$!==void 0?{agentId:$}:{}}:void 0;try{let I=[];for await(let h of u)I.push(h);let w=Buffer.
147
- concat(I);M=w,b=new URL(u.url??"/",t);let te=s!==null&&u.method==="POST"&&w.length>0,Jt=Et(h=>{let v=u.headers[h];return Array.isArray(v)?v.join(", "):v}),ye=te?Tt("POST",b.pathname+b.search,w,Jt):"";
148
- if(te)if(s.tieneEnVuelo(ye)){let h=await s.esperar(ye);if(h){p.writeHead(h.status,h.headers);let v=d(b.pathname)??new N;for(let W of h.chunks)p.write(W),v.observar(W);p.end();let J=v.usage()??(b.pathname===
149
- "/v1/messages"?Ae(Buffer.concat(h.chunks)):null);m(g,w,J,!0,b.pathname,L,R);return}}else k=s.registrar(ye);let ne={};for(let[h,v]of Object.entries(u.headers))h==="host"||h==="content-length"||v===void 0||
150
- (ne[h]=Array.isArray(v)?v.join(", "):v);let K=w;if(l!==null&&u.method==="POST"&&b.pathname==="/v1/messages"&&l.tiene("context_elision"))try{let h=et(w,L);h!==null&&(K=h,ne["anthropic-beta"]=nt(ne["ant\
151
- hropic-beta"]));}catch{}let ke=null;if(l!==null&&u.method==="POST"&&b.pathname==="/v1/messages"&&l.tiene("cache_ttl_tuning"))try{let v=Oe(K,K===w?L:"identity");if(v!==null){let J=kt(v),W=`${R?.sessionId??
152
- "sin-sesion"}:${J.system}`,Qe=Date.now(),Wt=a.ultima(W,Qe);if(a.anotar(W,J,Qe),St({fraccionNueva:xt(Wt,J)})){let oe=wt(v);oe!==null&&(K=oe.cuerpo,ke={rebajadas:oe.rebajadas,yaEran5m:oe.yaEran5m});}}}catch{}
153
- let C;try{C=await n(b,{method:u.method,headers:ne,body:["GET","HEAD"].includes(u.method??"")?void 0:K,redirect:"manual",signal:y.signal});}catch(h){k?.abortar(),p.headersSent||(p.writeHead(502,{"conten\
154
- t-type":"application/json"}),p.end(JSON.stringify({error:"bvsala gateway: upstream unreachable",detail:String(h)}))),o(`[gateway] ${u.method} ${b.pathname} \u2192 upstream inalcanzable: ${String(h)}`);
155
- return}let xe=Object.fromEntries(C.headers.entries());for(let h of Dn)delete xe[h];p.writeHead(C.status,xe);let Ge=C.headers.get("content-type")??"",Se=Ge.includes("text/event-stream")||Ge===""&&C.ok&&
156
- d(b.pathname)!==null;x=Se?d(b.pathname):null;let H=!Se&&C.ok&&r!==void 0&&u.method==="POST"&&b.pathname==="/v1/messages"&&(C.headers.get("content-type")??"").includes("application/json")?[]:null,Ye=0;
157
- if(C.body)for await(let h of C.body){let v=Buffer.from(h);p.write(v),x?.observar(v),H&&(Ye+=v.length,Ye>De?H=null:H.push(v)),k?.capturar(v);}if(p.end(),k?.terminar(C.status,xe),x&&C.ok){ee=!0;let h=x instanceof
158
- N?x.elision():null;m(g,w,x.usage(),!1,b.pathname,L,R,h,ke);}else if(H){let h=Buffer.concat(H);m(g,w,Ae(h),!1,b.pathname,L,R,it(h),ke);}else Se||o(`[gateway] ${u.method} ${b.pathname} \u2192 ${C.status}`);}catch(I){
159
- if(k?.abortar(),y.signal.aborted){let w=!ee&&x?x.usageFinal():null;if(w){o(`[gateway] ${u.method} ${b.pathname} \u2192 el cliente cerr\xF3 tras el usage final; se mide igual`);let te=x instanceof N?x.
160
- elision():null;m(g,M,w,false,b.pathname,L,R,te);}else o(`[gateway] ${u.method} ${b.pathname} \u2192 el cliente abort\xF3; upstream cancelado`);}else if(o(`[gateway] ${u.method} ${b.pathname} \u2192 error sirvie\
161
- ndo: ${String(I)}`),!p.headersSent){p.writeHead(502,{"content-type":"application/json"}),p.end(JSON.stringify({error:"bvsala gateway: stream interrupted",detail:String(I)}));return}p.writableEnded||p.
162
- end();}});return c.on("upgrade",(u,p)=>{o(`[gateway] ${u.method} ${new URL(u.url??"/","http://x").pathname} \u2192 426 (WebSocket no soportado; el cliente cae a HTTP)`),p.once("error",()=>{}),p.once("f\
163
- inish",()=>p.destroy()),p.end(`HTTP/1.1 426 Upgrade Required\r
149
+ `).update(n).digest("hex")}function $t(t){return Qn.map(e=>`${e}=${t(e)??""}`).join(`
150
+ `)}var xe=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(a=>n=a);this.enVuelo.set(e,{promesa:o,resolver:n});let r=[],
151
+ s=0,i=false;return {capturar:a=>{if(!i){if(s+=a.length,s>qe){i=true,r.length=0;return}r.push(a);}},terminar:(a,c)=>{let p=!i&&a>=200&&a<300;this.enVuelo.get(e)?.resolver(p?{status:a,headers:c,chunks:r}:null),
152
+ 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+=
153
+ 1),o}tieneEnVuelo(e){return this.enVuelo.has(e)}};var eo=["content-encoding","content-length","transfer-encoding"];async function Nt(t={}){let e=(t.upstream??"https://api.anthropic.com").replace(/\/+$/,""),n=t.fetchImpl??fetch,o=t.log??(u=>console.log(
154
+ u)),r;if(t.serviceAccountKey){r=new J({url:t.meteringUrl??"https://savings.bivelio.com/api/metering/usage",serviceAccountKey:t.serviceAccountKey,surface:"gateway",...t.fetchImpl?{fetchImpl:t.fetchImpl}:
155
+ {},onAuthError:m=>O("gateway-ingest-auth",`[bvsala gateway] la ingesta de uso rechaza la credencial (${m}). El tr\xE1fico sigue fluyendo (avisar, nunca romper), pero este uso no est\xE1 llegando al panel. R\
156
+ evisa BIVELIO_SERVICE_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let u=me();t.seatId?r.setSeat(t.seatId,u):fe(t.serviceAccountKey).then(m=>r?.setSeat(m,u)).catch(()=>{}),r.start();}else
157
+ O("gateway-sin-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.");
158
+ let s=t.coalescer?new xe:null,i=t.sombra&&r?new ve:null,a=new ke,c=t.elision!==false&&t.serviceAccountKey?new ye({url:new URL("/api/org/entitlements",t.meteringUrl??"https://savings.bivelio.com/api/meter\
159
+ ing/usage").toString(),serviceAccountKey:t.serviceAccountKey,...t.fetchImpl?{fetchImpl:t.fetchImpl}:{},log:o}):null,p=u=>u==="/v1/messages"?new U:u.endsWith("/responses")?new ge:null,f=(u,m,v,E,R,A,g,d,x,S)=>{
160
+ if(!r||!v)return;let D=r,I=v,_=yt(m,A);if(!_){O(`gateway-sin-modelo:${R}`,`[bvsala gateway] no se pudo leer el modelo del cuerpo de ${R} (content-encoding: ${A??"ninguno"}); su uso se reenv\xEDa pero no \
161
+ se mide.`);return}let C=vt(_,v);if(C){let X=E?St(u,_,C,g):xt(u,_,C,g,d,x);r.record(X);let q=X.cost.eliminatedInputFloorCost;o(`[gateway] POST ${R} ${E?"\xB7 COALESCIDA (llamada evitada)":""} \xB7 ${_}\
162
+ \xB7 $${C.costeUsd.toFixed(6)} (in ${C.tokens.entrada}, cache\u2191${C.tokens.cacheEscrita}${C.tokens.cacheEscrita1h?` (1h ${C.tokens.cacheEscrita1h})`:""} cache\u2193${C.tokens.cacheLeida}, out ${C.
163
+ tokens.salida})`+(d?` \xB7 elisi\xF3n: ${d.borrados} borrado(s), ${d.tokensLimpiados} tok limpiados por el proveedor`+(q!==void 0?` \xB7 suelo $${q.toFixed(6)} (lectura de cach\xE9)`:d.tokensLimpiadosToolUses>
164
+ 0?d.atribuible?" \xB7 sin precio de lectura en el cat\xE1logo: sin suelo":" \xB7 diales del cliente: se cuenta, no se acredita":d.tokensLimpiados>0?" \xB7 solo thinking (config del cliente): se cuenta, n\
165
+ o se acredita":""):""));let Z=d?.atribuible===true&&d.tokensLimpiadosToolUses>0;i&&!E&&R==="/v1/messages"&&setImmediate(()=>{try{let L=je(m,A);if(!L||typeof L!="object")return;let w=i.observar({cuerpo:L,
166
+ uso:I,model:_,at:S??Date.now(),...g?.sessionId!==void 0?{sessionId:g.sessionId}:{},...g?.agentId!==void 0?{agentId:g.agentId}:{}});if(!w)return;if(Z){o(`[gateway] sombra \xB7 ${_} \xB7 el proveedor ya bo\
167
+ rr\xF3 por nuestros diales: la cadena avanza, no se emite`);return}D.record(wt(`${u}:shadow`,_,w.baselineUsd,w.politicaUsd,g)),o(`[gateway] sombra \xB7 ${_} \xB7 baseline $${w.baselineUsd.toFixed(6)} \
168
+ \u2192 v0 $${w.politicaUsd.toFixed(6)}`);}catch{}});}else O(`gateway-sin-precio:${_}`,`[bvsala gateway] el modelo "${_}" no est\xE1 en el cat\xE1logo de precios; su uso se reenv\xEDa pero no se mide.`);},
169
+ l=createServer(async(u,m)=>{let v=randomUUID(),E=Date.now(),R=new AbortController;m.on("close",()=>{m.writableEnded||R.abort();});let A=null,g=new URL(u.url??"/",e),d=null,x=Buffer.alloc(0),S=false,D=null,I=(w,k)=>{if(w===
170
+ null||D===null||!D.nuestros)return w;let z=k?.cache_creation,Ae=k?.cache_creation_input_tokens??(z?.ephemeral_5m_input_tokens??0)+(z?.ephemeral_1h_input_tokens??0),ee=(k?.input_tokens??0)+(k?.cache_read_input_tokens??
171
+ 0)+Ae+w.tokensLimpiados,H=D.triggerDelCliente!==null&&ee>=D.triggerDelCliente;return {...w,atribuible:!H}},_=u.headers["content-encoding"],C=Array.isArray(_)?_[0]:_,X=w=>{let k=Array.isArray(w)?w[0]:w;
172
+ return k!==void 0&&/^[A-Za-z0-9._:/-]{1,128}$/.test(k)?k:void 0},q=X(u.headers["x-claude-code-session-id"]),Z=X(u.headers["x-claude-code-agent-id"]),L=q!==void 0||Z!==void 0?{...q!==void 0?{sessionId:q}:
173
+ {},...Z!==void 0?{agentId:Z}:{}}:void 0;try{let w=[];for await(let b of u)w.push(b);let k=Buffer.concat(w);x=k,g=new URL(u.url??"/",e);let z=s!==null&&u.method==="POST"&&k.length>0,Ae=$t(b=>{let y=u.headers[b];
174
+ return Array.isArray(y)?y.join(", "):y}),ee=z?jt("POST",g.pathname+g.search,k,Ae):"";if(z)if(s.tieneEnVuelo(ee)){let b=await s.esperar(ee);if(b){m.writeHead(b.status,b.headers);let y=p(g.pathname)??new U;
175
+ for(let re of b.chunks)m.write(re),y.observar(re);m.end();let oe=y.usage()??(g.pathname==="/v1/messages"?$e(Buffer.concat(b.chunks)):null);f(v,k,oe,!0,g.pathname,C,L);return}}else A=s.registrar(ee);let H={};
176
+ for(let[b,y]of Object.entries(u.headers))b==="host"||b==="content-length"||y===void 0||(H[b]=Array.isArray(y)?y.join(", "):y);let te=k;if(c!==null&&u.method==="POST"&&g.pathname==="/v1/messages"&&c.tiene(
177
+ "context_elision"))try{let b=ut(k,C);b!==null&&(te=b.cuerpo,D={nuestros:b.nuestros,triggerDelCliente:b.triggerDelCliente},H["anthropic-beta"]=pt(H["anthropic-beta"]));}catch{}let _e=null;if(c!==null&&u.
178
+ method==="POST"&&g.pathname==="/v1/messages"&&c.tiene("cache_ttl_tuning"))try{let y=Fe(te,te===k?C:"identity");if(y!==null){let oe=Ot(y),re=`${L?.sessionId??"sin-sesion"}:${oe.system}`,at=Date.now(),sn=a.
179
+ ultima(re,at);if(a.anotar(re,oe,at),Mt({fraccionNueva:Dt(sn,oe)})){let ue=Lt(y);ue!==null&&(te=ue.cuerpo,_e={rebajadas:ue.rebajadas,yaEran5m:ue.yaEran5m});}}}catch{}let P;try{P=await n(g,{method:u.method,
180
+ headers:H,body:["GET","HEAD"].includes(u.method??"")?void 0:te,redirect:"manual",signal:R.signal});}catch(b){A?.abortar(),m.headersSent||(m.writeHead(502,{"content-type":"application/json"}),m.end(JSON.
181
+ stringify({error:"bvsala gateway: upstream unreachable",detail:String(b)}))),o(`[gateway] ${u.method} ${g.pathname} \u2192 upstream inalcanzable: ${String(b)}`);return}let Re=Object.fromEntries(P.headers.
182
+ entries());for(let b of eo)delete Re[b];m.writeHead(P.status,Re);let st=P.headers.get("content-type")??"",Ie=st.includes("text/event-stream")||st===""&&P.ok&&p(g.pathname)!==null;d=Ie?p(g.pathname):null;
183
+ let ne=!Ie&&P.ok&&r!==void 0&&u.method==="POST"&&g.pathname==="/v1/messages"&&(P.headers.get("content-type")??"").includes("application/json")?[]:null,it=0;if(P.body)for await(let b of P.body){let y=Buffer.
184
+ from(b);m.write(y),d?.observar(y),ne&&(it+=y.length,it>qe?ne=null:ne.push(y)),A?.capturar(y);}if(m.end(),A?.terminar(P.status,Re),d&&P.ok){S=!0;let b=d.usage(),y=I(d instanceof U?d.elision():null,b);f(
185
+ v,k,b,!1,g.pathname,C,L,y,_e,E);}else if(ne){let b=Buffer.concat(ne),y=$e(b);f(v,k,y,!1,g.pathname,C,L,I(bt(b),y),_e,E);}else Ie||o(`[gateway] ${u.method} ${g.pathname} \u2192 ${P.status}`);}catch(w){if(A?.
186
+ abortar(),R.signal.aborted){let k=!S&&d?d.usageFinal():null;if(k){o(`[gateway] ${u.method} ${g.pathname} \u2192 el cliente cerr\xF3 tras el usage final; se mide igual`);let z=I(d instanceof U?d.elision():
187
+ null,k);f(v,x,k,false,g.pathname,C,L,z,void 0,E);}else o(`[gateway] ${u.method} ${g.pathname} \u2192 el cliente abort\xF3; upstream cancelado`);}else if(o(`[gateway] ${u.method} ${g.pathname} \u2192 error sirvi\
188
+ endo: ${String(w)}`),!m.headersSent){m.writeHead(502,{"content-type":"application/json"}),m.end(JSON.stringify({error:"bvsala gateway: stream interrupted",detail:String(w)}));return}m.writableEnded||m.
189
+ end();}});return l.on("upgrade",(u,m)=>{o(`[gateway] ${u.method} ${new URL(u.url??"/","http://x").pathname} \u2192 426 (WebSocket no soportado; el cliente cae a HTTP)`),m.once("error",()=>{}),m.once("f\
190
+ inish",()=>m.destroy()),m.end(`HTTP/1.1 426 Upgrade Required\r
164
191
  connection: close\r
165
192
  content-length: 0\r
166
193
  \r
167
- `);}),await new Promise((u,p)=>{c.once("error",p),c.listen(e.puerto??8402,"127.0.0.1",()=>u());}),{puerto:c.address().port,cerrar:async()=>{await r?.stopAndDrain(),await new Promise(u=>c.close(()=>u()));}}}var Le=["claude","codex","goose","qwen"];function At(e){return Le.includes(e??"")}function _t(e,t={}){let n=t.path??process.env.PATH??"",o=t.
168
- existe??existsSync,r=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(o(a))return {tipo:"exe",ruta:a}}if(r===null)for(let i of [".cmd",".bat"]){let a=join(s,e+
169
- i);if(o(a)){r=a;break}}}return r!==null?{tipo:"solo-shim",ruta:r}:{tipo:"no-encontrado"}}function It(e={}){let n=(e.env??process.env).BVSALA_CODEX_AUTH?.toLowerCase();if(n==="api-key"||n==="apikey")return "\
170
- api-key";if(n==="chatgpt")return "chatgpt";let o=null;try{o=e.leerAuth?e.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.
171
- toLowerCase().replace(/[^a-z]/g,"")==="apikey"?"api-key":"chatgpt":r.tokens!==void 0&&r.tokens!==null?"chatgpt":"api-key"}catch{return "api-key"}}var Mn={"api-key":{upstream:"https://api.openai.com",prefijo:"\
172
- /v1"},chatgpt:{upstream:"https://chatgpt.com",prefijo:"/backend-api/codex"}};function Me(e,t,n,o={}){let r=`http://127.0.0.1:${t}`;switch(e){case "claude":return {bin:"claude",args:n,env:{ANTHROPIC_BASE_URL:r}};case "\
194
+ `);}),await new Promise((u,m)=>{l.once("error",m),l.listen(t.puerto??8402,"127.0.0.1",()=>u());}),{puerto:l.address().port,cerrar:async()=>{await r?.stopAndDrain(),await new Promise(u=>l.close(()=>u()));}}}var He=["claude","codex","goose","qwen"];function Bt(t){return He.includes(t??"")}function Ut(t,e={}){let n=e.path??process.env.PATH??"",o=e.
195
+ existe??existsSync,r=null;for(let s of n.split(";").filter(i=>i.length>0)){for(let i of [".exe",".com"]){let a=join(s,t+i);if(o(a))return {tipo:"exe",ruta:a}}if(r===null)for(let i of [".cmd",".bat"]){let a=join(s,t+
196
+ i);if(o(a)){r=a;break}}}return r!==null?{tipo:"solo-shim",ruta:r}:{tipo:"no-encontrado"}}function Vt(t={}){let n=(t.env??process.env).BVSALA_CODEX_AUTH?.toLowerCase();if(n==="api-key"||n==="apikey")return "\
197
+ 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.
198
+ toLowerCase().replace(/[^a-z]/g,"")==="apikey"?"api-key":"chatgpt":r.tokens!==void 0&&r.tokens!==null?"chatgpt":"api-key"}catch{return "api-key"}}var no={"api-key":{upstream:"https://api.openai.com",prefijo:"\
199
+ /v1"},chatgpt:{upstream:"https://chatgpt.com",prefijo:"/backend-api/codex"}};function Ke(t,e,n,o={}){let r=`http://127.0.0.1:${e}`;switch(t){case "claude":return {bin:"claude",args:n,env:{ANTHROPIC_BASE_URL:r}};case "\
173
200
  goose":return {bin:"goose",args:n,env:{ANTHROPIC_HOST:r}};case "qwen":return {bin:"qwen",args:n,env:{ANTHROPIC_BASE_URL:r},nota:'Qwen Code solo enruta por aqu\xED con `security.auth.selectedType: "anthropic\
174
- "` en ~/.qwen/settings.json (ver `bvsala doctor`).'};case "codex":{let s=o.modoCodex??"api-key",i=Mn[s];return {bin:"codex",args:["-c",`openai_base_url="${r}${i.prefijo}"`,...n],env:{},upstream:i.upstream,
201
+ "` en ~/.qwen/settings.json (ver `bvsala doctor`).'};case "codex":{let s=o.modoCodex??"api-key",i=no[s];return {bin:"codex",args:["-c",`openai_base_url="${r}${i.prefijo}"`,...n],env:{},upstream:i.upstream,
175
202
  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\
176
- tokens.":"Auth por API key: el gateway enruta a api.openai.com/v1."}}}}function $n(e){let t=Number.parseInt(e.slice(8,10),10);return Number.isFinite(t)&&t%2===0?"palanca":"control"}function Pt(e){let t;try{t=JSON.parse(e());}catch{return null}if(typeof t!="object"||t===null)
177
- return null;let n=t,o=n.espia;return typeof o!="number"||!Number.isInteger(o)||o<1||o>65535?null:{activo:n.activo!==false,espia:o}}function Ot(e){let{enrolamiento:t,espiaVivo:n,upstreamEnv:o,elisionEnv:r,
178
- hoyUtcIso:s}=e;if(!t)return {linea:"",aviso:false};if(!t.activo)return {linea:"anillo 2: enrolamiento en pausa (activo:false)",aviso:false};if(!n)return {linea:`anillo 2: enrolado pero el esp\xEDa NO escucha en :${t.
179
- espia} \u2014 NO encadeno (el tr\xE1fico de hoy no entra en el corpus). Arr\xE1ncalo con \`pnpm anillo2:espia\`.`,aviso:true};let i=$n(s),a=`http://127.0.0.1:${t.espia}`,l=o!==void 0&&o!=="",d=r!==void 0&&
180
- r!=="",m=[];return m.push(`anillo 2: ${s} UTC \u2192 brazo ${i.toUpperCase()}`),m.push(l?`upstream respetado del entorno (${o})`:`encadenado a :${t.espia}`),d&&m.push(`elisi\xF3n respetada del entorno (=${r}\
181
- )`),{...l?{}:{upstream:a},...d?{}:{elision:i==="palanca"?"1":"0"},brazo:i,linea:m.join(", "),aviso:false}}var Bn="comprobar: en el log del gateway debe aparecer `[gateway] POST /v1/messages \u2026`; si ve\
182
- s `/v1/v1/messages`, sobra un /v1; si ves `POST /messages` a secas, falta uno.",Un=[{id:"claude",nombre:"Claude Code",binario:"claude",configs:[],detectable:true,receta:({base:e})=>["usa `bvsala claude`\
183
- \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\
184
- 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 \
185
- 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\
186
- e ah\xED)`,`${t[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:e,
187
- rutas:t})=>[`mecanismo: ${t[0]} \u2192 provider.anthropic.options.baseURL (el opencode.json del proyecto pisa al global). CON /v1.`,"{",' "provider": {',' "anthropic": {',` "options": { "base\
188
- URL": "${e}" }`," }"," }","}",'alternativa: "baseURL": "{env:BVSALA_BASE_URL}" y exportar la variable; trampa: sin la variable, baseURL queda vac\xEDo.']},{id:"goose",nombre:"Goose",binario:"goose",
189
- configs:[join(".config","goose","config.yaml")],detectable:true,receta:({base:e,rutas:t})=>[`mecanismo: variable de entorno ANTHROPIC_HOST (pisa ${t[0]}). SIN /v1.`,`ANTHROPIC_HOST=${e} ANTHROPIC_API_KEY=\u2026\
190
- goose`]},{id:"crush",nombre:"Crush",binario:"crush",configs:[join(".config","crush","crushrc")],detectable:true,receta:({baseV1:e,rutas:t})=>[`mecanismo: ${t[0]} (Bash); crush.json est\xE1 deprecado. CON /v1\
191
- y SIN barra final (el SDK Go resuelve relativo: /v1/ \u2192 /v1/v1/messages).`,`provider add bvsala --type anthropic --base-url ${e} --api-key "$ANTHROPIC_API_KEY"`]},{id:"qwen",nombre:"Qwen Code",binario:"\
192
- qwen",configs:[join(".qwen","settings.json")],detectable:true,receta:({base:e,rutas:t})=>[`mecanismo: variable de entorno ANTHROPIC_BASE_URL + ${t[0]} con selectedType = anthropic. SIN /v1 (el SDK TS ofici\
193
- al a\xF1ade /v1/messages).`,`ANTHROPIC_BASE_URL=${e} ANTHROPIC_API_KEY=\u2026 qwen`,`comprueba a mano que ${t[0]} lleve selectedType: anthropic \u2014 el doctor no lee el archivo.`]},{id:"droid",nombre:"\
194
- Droid (Factory)",binario:"droid",configs:[join(".factory","settings.json")],detectable:true,receta:({base:e,rutas:t})=>[`mecanismo: ${t[0]} \u2192 customModels[] con provider "anthropic". SIN /v1 [inferido: val\
203
+ tokens.":"Auth por API key: el gateway enruta a api.openai.com/v1."}}}}function oo(t){let e=Number.parseInt(t.slice(8,10),10);return Number.isFinite(e)&&e%2===0?"palanca":"control"}function Ft(t){let e;try{e=JSON.parse(t());}catch{return null}if(typeof e!="object"||e===null)
204
+ return null;let n=e,o=n.espia;return typeof o!="number"||!Number.isInteger(o)||o<1||o>65535?null:{activo:n.activo!==false,espia:o}}function qt(t){let{enrolamiento:e,espiaVivo:n,upstreamEnv:o,elisionEnv:r,
205
+ hoyUtcIso:s}=t;if(!e)return {linea:"",aviso:false};if(!e.activo)return {linea:"anillo 2: enrolamiento en pausa (activo:false)",aviso:false};if(!n)return {linea:`anillo 2: enrolado pero el esp\xEDa NO escucha en :${e.
206
+ espia} \u2014 NO encadeno (el tr\xE1fico de hoy no entra en el corpus). Arr\xE1ncalo con \`pnpm anillo2:espia\`.`,aviso:true};let i=oo(s),a=`http://127.0.0.1:${e.espia}`,c=o!==void 0&&o!=="",p=r!==void 0&&
207
+ r!=="",f=[];return f.push(`anillo 2: ${s} UTC \u2192 brazo ${i.toUpperCase()}`),f.push(c?`upstream respetado del entorno (${o})`:`encadenado a :${e.espia}`),p&&f.push(`elisi\xF3n respetada del entorno (=${r}\
208
+ )`),{...c?{}:{upstream:a},...p?{}:{elision:i==="palanca"?"1":"0"},brazo:i,linea:f.join(", "),aviso:false}}var ao="comprobar: en el log del gateway debe aparecer `[gateway] POST /v1/messages \u2026`; si ve\
209
+ s `/v1/v1/messages`, sobra un /v1; si ves `POST /messages` a secas, falta uno.",co=[{id:"claude",nombre:"Claude Code",binario:"claude",configs:[],detectable:true,receta:({base:t})=>["usa `bvsala claude`\
210
+ \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\
211
+ 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 \
212
+ 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\
213
+ 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,
214
+ rutas:e})=>[`mecanismo: ${e[0]} \u2192 provider.anthropic.options.baseURL (el opencode.json del proyecto pisa al global). CON /v1.`,"{",' "provider": {',' "anthropic": {',` "options": { "base\
215
+ 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",
216
+ 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\
217
+ 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\
218
+ 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:"\
219
+ 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\
220
+ 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:"\
221
+ 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\
195
222
  idar en mano contra el log del gateway].`,"{",' "customModels": ['," {",' "model": "<id de modelo Anthropic>",',' "displayName": "<nombre visible>",',' "provider": "anthropic",',` \
196
- "baseUrl": "${e}",`,' "apiKey": "<tu API key de Anthropic>"'," }"," ]","}"]},{id:"cline",nombre:"Cline",configs:[],detectable:false,receta:({baseV1:e})=>["mecanismo: UI \u2192 proveedor Anthropic\
197
- \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,
198
- 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 Vn(e,t){
199
- let n=e.split(delimiter).filter(r=>r.length>0),o=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return r=>n.some(s=>o.some(i=>t(join(s,r+i))))}async function Dt(e,t={}){if(!Number.isInteger(e)||e<1||
200
- e>65535)throw new RangeError(`[bvsala doctor] puerto inv\xE1lido: ${String(e)}`);let n=t.home??homedir(),o=t.existe??existsSync,r=t.enPath??Vn(t.path??process.env.PATH??"",o),s=`http://127.0.0.1:${e}`,i=`${s}/v1`,
201
- a=[],l=[`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 \
202
- se lee el contenido de ning\xFAn archivo.",""];for(let d of Un){let m=d.configs.map(g=>join(n,g)),c=d.binario!==void 0&&r(d.binario),f=m.filter(g=>o(g)),u=c||f.length>0;u&&a.push(d.id);let p;d.detectable?
203
- u?p=`detectado \u2014 ${[...c?[`binario \`${d.binario}\` en PATH`]:[],...f.map(y=>`config presente: ${y}`)].join("; ")}`:p="no detectado":p="sin detecci\xF3n autom\xE1tica (extensi\xF3n de editor)",l.
204
- push(`\xBB ${d.id}: ${p}`),l.push(` ${d.nombre}`);for(let g of d.receta({base:s,baseV1:i,rutas:m}))l.push(` ${g}`);l.push(` ${Bn}`),l.push("");}return l.push("Regla BYOK: las recetas del anillo Anth\
223
+ "baseUrl": "${t}",`,' "apiKey": "<tu API key de Anthropic>"'," }"," ]","}"]},{id:"cline",nombre:"Cline",configs:[],detectable:false,receta:({baseV1:t})=>["mecanismo: UI \u2192 proveedor Anthropic\
224
+ \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,
225
+ 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 lo(t,e){
226
+ let n=t.split(delimiter).filter(r=>r.length>0),o=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return r=>n.some(s=>o.some(i=>e(join(s,r+i))))}async function Ht(t,e={}){if(!Number.isInteger(t)||t<1||
227
+ t>65535)throw new RangeError(`[bvsala doctor] puerto inv\xE1lido: ${String(t)}`);let n=e.home??homedir(),o=e.existe??existsSync,r=e.enPath??lo(e.path??process.env.PATH??"",o),s=`http://127.0.0.1:${t}`,i=`${s}/v1`,
228
+ a=[],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 \
229
+ se lee el contenido de ning\xFAn archivo.",""];for(let p of co){let f=p.configs.map(v=>join(n,v)),l=p.binario!==void 0&&r(p.binario),h=f.filter(v=>o(v)),u=l||h.length>0;u&&a.push(p.id);let m;p.detectable?
230
+ u?m=`detectado \u2014 ${[...l?[`binario \`${p.binario}\` en PATH`]:[],...h.map(E=>`config presente: ${E}`)].join("; ")}`:m="no detectado":m="sin detecci\xF3n autom\xE1tica (extensi\xF3n de editor)",c.
231
+ push(`\xBB ${p.id}: ${m}`),c.push(` ${p.nombre}`);for(let v of p.receta({base:s,baseV1:i,rutas:f}))c.push(` ${v}`);c.push(` ${ao}`),c.push("");}return c.push("Regla BYOK: las recetas del anillo Anth\
205
232
  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 \
206
- 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:l.join(`
207
- `),detectados:a}}var Lt="savings-mode";function Mt(e,t){for(let n of e){let o=join(n,"skills",Lt,"SKILL.md");if(t.existe(o))return o}return null}var $t="<!-- bvsala:savings-mode:inicio -->",fe="\
208
- <!-- bvsala:savings-mode:fin -->";function Fn(e){let t=e.replace(/^---\n[\s\S]*?\n---\n*/,"").trim();return `${$t}
209
- ${t}
233
+ 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(`
234
+ `),detectados:a}}var Kt="savings-mode";function Jt(t,e){for(let n of t){let o=join(n,"skills",Kt,"SKILL.md");if(e.existe(o))return o}return null}var Wt="<!-- bvsala:savings-mode:inicio -->",Se="\
235
+ <!-- bvsala:savings-mode:fin -->";function uo(t){let e=t.replace(/^---\n[\s\S]*?\n---\n*/,"").trim();return `${Wt}
236
+ ${e}
210
237
 
211
238
  _Always on (AGENTS.md has no activation step). Delete this block to turn it off; \`bvsala skill --codex --forzar\` restores it._
212
- ${fe}`}function jt(e){let t=Mt(e.origenes,e.fs);if(!t)return {ok:false,destino:"",mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${e.origenes.join(", ")})`};let n=Fn(e.fs.
213
- leer(t)),o=e.proyecto?e.cwd:join(e.home,".codex"),r=join(o,"AGENTS.md");if(!e.fs.existe(r))return e.fs.crearDir(o),e.fs.escribir(r,n+`
214
- `),{ok:true,destino:r,mensaje:$e(r,"instalado")};let s=e.fs.leer(r),i=s.indexOf($t),a=s.indexOf(fe);return i===-1||a===-1||a<i?(e.fs.escribir(r,s.trimEnd()+`
239
+ ${Se}`}function Gt(t){let e=Jt(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=uo(t.fs.
240
+ 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+`
241
+ `),{ok:true,destino:r,mensaje:Je(r,"instalado")};let s=t.fs.leer(r),i=s.indexOf(Wt),a=s.indexOf(Se);return i===-1||a===-1||a<i?(t.fs.escribir(r,s.trimEnd()+`
215
242
 
216
243
  `+n+`
217
- `),{ok:true,destino:r,mensaje:$e(r,"a\xF1adido al AGENTS.md existente")}):s.slice(i,a+fe.length)===n?{ok:true,destino:r,mensaje:`[bvsala skill] ya instalado y al d\xEDa: ${r}`}:e.forzar?(e.fs.escribir(r,s.
218
- slice(0,i)+n+s.slice(a+fe.length)),{ok:true,destino:r,mensaje:$e(r,"bloque actualizado")}):{ok:false,destino:r,mensaje:`[bvsala skill] el bloque savings-mode de ${r} tiene contenido DISTINTO \u2014 no lo piso; \
219
- usa --forzar para actualizarlo`}}function $e(e,t){return `[bvsala skill] ${t}: ${e}
244
+ `),{ok:true,destino:r,mensaje:Je(r,"a\xF1adido al AGENTS.md existente")}):s.slice(i,a+Se.length)===n?{ok:true,destino:r,mensaje:`[bvsala skill] ya instalado y al d\xEDa: ${r}`}:t.forzar?(t.fs.escribir(r,s.
245
+ slice(0,i)+n+s.slice(a+Se.length)),{ok:true,destino:r,mensaje:Je(r,"bloque actualizado")}):{ok:false,destino:r,mensaje:`[bvsala skill] el bloque savings-mode de ${r} tiene contenido DISTINTO \u2014 no lo piso; \
246
+ usa --forzar para actualizarlo`}}function Je(t,e){return `[bvsala skill] ${e}: ${t}
220
247
  [bvsala skill] AGENTS.md va SIEMPRE activo en Codex (no hay paso de activaci\xF3n); borra el bloque para apagarlo.
221
- [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 Nt(e){let t=Mt(e.origenes,e.fs);if(!t)return {ok:false,destino:"",
222
- 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"),o=join(n,Lt),r=join(o,
223
- "SKILL.md"),s=e.fs.leer(t);if(e.fs.existe(r)&&!e.forzar){let i=e.fs.leer(r)===s;return {ok:i,destino:r,mensaje:i?`[bvsala skill] ya instalado y al d\xEDa: ${r}`:`[bvsala skill] ya existe ${r} con conte\
224
- nido DISTINTO \u2014 no lo piso; usa --forzar para sobrescribir`}}return e.fs.crearDir(o),e.fs.escribir(r,s),{ok:true,destino:r,mensaje:`[bvsala skill] instalado: ${r}
248
+ [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 Yt(t){let e=Jt(t.origenes,t.fs);if(!e)return {ok:false,destino:"",
249
+ 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,Kt),r=join(o,
250
+ "SKILL.md"),s=t.fs.leer(e);if(t.fs.existe(r)&&!t.forzar){let i=t.fs.leer(r)===s;return {ok:i,destino:r,mensaje:i?`[bvsala skill] ya instalado y al d\xEDa: ${r}`:`[bvsala skill] ya existe ${r} con conte\
251
+ 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}
225
252
  [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.
226
- [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 je=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)??[],o=0;for(let r of n){let s=r[0];if(/\s/.test(s)){let i=(r.
253
+ [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(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 i=(r.
227
254
  match(/\n/g)??[]).length;o+=i+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,
228
- Math.ceil(t.length/4))}},Ne=new je;var ze=class{estimators=new Map;modelToTokenizer=new Map;fallbackId;constructor(t=Ne){this.fallbackId=t.id,this.estimators.set(t.id,t);}register(t){return this.estimators.set(t.id,t),this}mapModel(t,n){
229
- 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 o=this.modelToTokenizer.get(t.model);if(o){let r=this.estimators.
230
- get(o);if(r)return r}}return this.estimators.get(this.fallbackId)}count(t,n){return this.resolve(n).count(t)}};new ze;new TextEncoder;new TextDecoder;new TextDecoder;var so={"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}};
231
- Te(so);var Fe="0.4.16";function fo(e,t=300){return new Promise(n=>{let o=connect({port:e,host:"127.0.0.1"}),r=s=>{o.destroy(),n(s);};o.setTimeout(t,()=>r(false)),o.once("connect",()=>r(true)),o.once("error",()=>r(false));})}var[,,S,...D]=process.
232
- argv;function ho(){console.log(`bvsala ${Fe} \u2014 BiVelio Savings Layer
255
+ Math.ceil(e.length/4))}},Ge=new We;var Ye=class{estimators=new Map;modelToTokenizer=new Map;fallbackId;constructor(e=Ge){this.fallbackId=e.id,this.estimators.set(e.id,e);}register(e){return this.estimators.set(e.id,e),this}mapModel(e,n){
256
+ 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.
257
+ get(o);if(r)return r}}return this.estimators.get(this.fallbackId)}count(e,n){return this.resolve(n).count(e)}};new Ye;new TextEncoder;new TextDecoder;new TextDecoder;var Ao={"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}};
258
+ De(Ao);function Lo(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[,,T,...N]=process.
259
+ argv;function jo(){console.log(`bvsala ${K} \u2014 BiVelio Savings Layer
233
260
 
234
261
  Comandos:
235
262
  gateway [--puerto N] Proxy local medidor (por defecto 8402) para terminales que
@@ -277,24 +304,24 @@ Entorno:
277
304
  CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 (Claude Code, solo API key) tus modelos en /model.
278
305
 
279
306
  El gateway nunca corta el tr\xE1fico: sin clave o con la ingesta ca\xEDda, reenv\xEDa y avisa.
280
- Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}var Z=At(S);S!=="gateway"&&S!=="doctor"&&S!=="skill"&&!Z&&(ho(),process.exit(S===void 0||S==="hel\
281
- p"||S==="--help"?0:1));if(S==="skill"){let e=dirname(fileURLToPath(import.meta.url)),t={origenes:[join(e,"..",".."),join(e,"..")],home:homedir(),cwd:process.cwd(),proyecto:D.includes("--proyecto"),forzar:D.includes("--forzar"),
282
- fs:{existe:existsSync,leer:o=>readFileSync(o,"utf8"),escribir:(o,r)=>writeFileSync(o,r),crearDir:o=>mkdirSync(o,{recursive:true})}},n=D.includes("--codex")?jt(t):Nt(t);console.log(n.mensaje),process.exit(n.ok?0:1);}var Ke=D.indexOf("--puer\
283
- to"),F=Z?0:Ke>=0?Number(D[Ke+1]):8402;(!Number.isInteger(F)||(S==="doctor"?F<1:F<0)||F>65535)&&(console.error(`[bvsala ${S}] puerto inv\xE1lido: ${D[Ke+1]}`),process.exit(1));if(S==="doctor"){D.includes(
284
- "--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 Dt(F);console.log(e.texto),process.exit(0);}var _=Z?
285
- Me(S,0,D,{modoCodex:S==="codex"?It({leerAuth:()=>readFileSync(join(homedir(),".codex","auth.json"),"utf8")}):void 0}):null,ve=process.env.BIVELIO_SERVICE_KEY,go=Z&&process.env.BVSALA_GATEWAY_LOG!=="1",qe=_?.upstream?null:
286
- Pt(()=>readFileSync(process.env.BVSALA_ANILLO2_FICHERO??join(homedir(),".bvsala","anillo2.json"),"utf8")),X=Ot({enrolamiento:qe,espiaVivo:qe!==null&&await fo(qe.espia),upstreamEnv:process.env.BVSALA_GATEWAY_UPSTREAM,elisionEnv:process.
287
- env.BVSALA_GATEWAY_ELISION,hoyUtcIso:new Date().toISOString().slice(0,10)}),He=process.env.BVSALA_GATEWAY_UPSTREAM??X.upstream,Kt=process.env.BVSALA_GATEWAY_ELISION??X.elision,B=await Ct({puerto:F,...go?
288
- {log:()=>{}}:{},...ve?{serviceAccountKey:ve}:{},...process.env.BVSALA_SEAT_ID?{seatId:process.env.BVSALA_SEAT_ID}:{},...He?{upstream:He}:_?.upstream?{upstream:_.upstream}:{},...process.env.BVSALA_GATEWAY_COALESCE===
289
- "1"?{coalescer:true}:{},...process.env.BVSALA_GATEWAY_SHADOW==="1"?{sombra:true}:{},elision:Kt!=="0",...process.env.BVSALA_METERING_URL?{meteringUrl:process.env.BVSALA_METERING_URL}:{}}),bo=He??_?.upstream??
290
- "https://api.anthropic.com";console.log(`[bvsala gateway] v${Fe} escuchando en http://127.0.0.1:${B.puerto} \u2192 ${bo}`);console.log(`[bvsala gateway] medici\xF3n: ${ve?"ACTIVA (clave de servicio pr\
291
- esente)":"APAGADA (falta BIVELIO_SERVICE_KEY)"}`);{let e=tt(Kt,ve!==void 0);(e.aviso?console.error:console.log)(`[bvsala gateway] ${e.linea}`),X.linea&&(X.aviso?console.error:console.log)(`[bvsala gat\
292
- eway] ${X.linea}`);}process.env.BVSALA_GATEWAY_UPSTREAM&&_?.upstream&&process.env.BVSALA_GATEWAY_UPSTREAM!==_.upstream&&console.error(`[bvsala ${S}] AVISO: BVSALA_GATEWAY_UPSTREAM=${process.env.BVSALA_GATEWAY_UPSTREAM}\
293
- pisa el upstream de este terminal (${_.upstream}). Si no es lo que quieres, quita la variable.`);S==="codex"&&!lt()&&console.error(`[bvsala codex] AVISO: este Node (${process.version}) no descomprime\
294
- zstd y Codex manda el cuerpo en zstd: el tr\xE1fico pasa pero NO se mide. Usa Node \u2265 22.15.`);if(_&&Z){let e=Me(S,B.puerto,D,{..._.upstream?{modoCodex:_.upstream.includes("chatgpt.com")?"chatgpt":
295
- "api-key"}:{}});e.nota&&console.log(`[bvsala ${S}] ${e.nota}`);let t=e.bin;if(process.platform==="win32"){let o=_t(e.bin);o.tipo==="exe"?t=o.ruta:o.tipo==="solo-shim"&&(console.error(`[bvsala ${S}] \`${e.
296
- bin}\` est\xE1 instalado como shim de npm (${o.ruta}) y Windows no puede lanzarlo de forma segura con argumentos (CVE-2024-27980). Inst\xE1lalo con su instalador nativo (deja un ${e.bin}.exe en el PAT\
297
- H) o usa la receta manual de docs/terminales/.`),await B.cerrar(),process.exit(127));}let n=spawn(t,e.args,{stdio:"inherit",env:{...process.env,...e.env}});n.on("error",o=>{console.error(`[bvsala ${S}] no\
298
- se pudo lanzar \`${e.bin}\`: ${String(o)}. \xBFEst\xE1 instalado y en el PATH?`),B.cerrar().then(()=>process.exit(127));}),n.on("exit",(o,r)=>{B.cerrar().then(()=>process.exit(o??(r?1:0)));});}else console.
299
- log(`[bvsala gateway] apunta tu terminal (o usa \`bvsala ${Le.join("|")}\`): ANTHROPIC_BASE_URL=http://127.0.0.1:${B.puerto} claude \xB7 bvsala doctor para el resto`);var Ht=async()=>{await B.cerrar(),
300
- process.exit(0);};process.on("SIGINT",()=>{Ht();});process.on("SIGTERM",()=>{Ht();});
307
+ Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}var le=Bt(T);T!=="gateway"&&T!=="doctor"&&T!=="skill"&&!le&&(jo(),process.exit(T===void 0||T==="h\
308
+ elp"||T==="--help"?0:1));if(T==="skill"){let t=dirname(fileURLToPath(import.meta.url)),e={origenes:[join(t,"..",".."),join(t,"..")],home:homedir(),cwd:process.cwd(),proyecto:N.includes("--proyecto"),forzar:N.includes("--forza\
309
+ r"),fs:{existe:existsSync,leer:o=>readFileSync(o,"utf8"),escribir:(o,r)=>writeFileSync(o,r),crearDir:o=>mkdirSync(o,{recursive:true})}},n=N.includes("--codex")?Gt(e):Yt(e);console.log(n.mensaje),process.exit(n.ok?0:1);}var tt=N.indexOf("--\
310
+ puerto"),Q=le?0:tt>=0?Number(N[tt+1]):8402;(!Number.isInteger(Q)||(T==="doctor"?Q<1:Q<0)||Q>65535)&&(console.error(`[bvsala ${T}] puerto inv\xE1lido: ${N[tt+1]}`),process.exit(1));if(T==="doctor"){N.includes(
311
+ "--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 Ht(Q);console.log(t.texto),process.exit(0);}var M=le?
312
+ Ke(T,0,N,{modoCodex:T==="codex"?Vt({leerAuth:()=>readFileSync(join(homedir(),".codex","auth.json"),"utf8")}):void 0}):null,Ce=process.env.BIVELIO_SERVICE_KEY,$o=le&&process.env.BVSALA_GATEWAY_LOG!=="1",et=M?.upstream?
313
+ null:Ft(()=>readFileSync(process.env.BVSALA_ANILLO2_FICHERO??join(homedir(),".bvsala","anillo2.json"),"utf8")),ce=qt({enrolamiento:et,espiaVivo:et!==null&&await Lo(et.espia),upstreamEnv:process.env.BVSALA_GATEWAY_UPSTREAM,
314
+ elisionEnv:process.env.BVSALA_GATEWAY_ELISION,hoyUtcIso:new Date().toISOString().slice(0,10)}),nt=process.env.BVSALA_GATEWAY_UPSTREAM??ce.upstream,on=process.env.BVSALA_GATEWAY_ELISION??ce.elision,F=await Nt(
315
+ {puerto:Q,...$o?{log:()=>{}}:{},...Ce?{serviceAccountKey:Ce}:{},...process.env.BVSALA_SEAT_ID?{seatId:process.env.BVSALA_SEAT_ID}:{},...nt?{upstream:nt}:M?.upstream?{upstream:M.upstream}:{},...process.
316
+ env.BVSALA_GATEWAY_COALESCE==="1"?{coalescer:true}:{},...process.env.BVSALA_GATEWAY_SHADOW==="1"?{sombra:true}:{},elision:on!=="0",...process.env.BVSALA_METERING_URL?{meteringUrl:process.env.BVSALA_METERING_URL}:
317
+ {}}),No=nt??M?.upstream??"https://api.anthropic.com";console.log(`[bvsala gateway] v${K} escuchando en http://127.0.0.1:${F.puerto} \u2192 ${No}`);console.log(`[bvsala gateway] medici\xF3n: ${Ce?"ACTI\
318
+ VA (clave de servicio presente)":"APAGADA (falta BIVELIO_SERVICE_KEY)"}`);{let t=dt(on,Ce!==void 0);(t.aviso?console.error:console.log)(`[bvsala gateway] ${t.linea}`),ce.linea&&(ce.aviso?console.error:
319
+ console.log)(`[bvsala gateway] ${ce.linea}`);}process.env.BVSALA_GATEWAY_UPSTREAM&&M?.upstream&&process.env.BVSALA_GATEWAY_UPSTREAM!==M.upstream&&console.error(`[bvsala ${T}] AVISO: BVSALA_GATEWAY_UPST\
320
+ REAM=${process.env.BVSALA_GATEWAY_UPSTREAM} pisa el upstream de este terminal (${M.upstream}). Si no es lo que quieres, quita la variable.`);T==="codex"&&!kt()&&console.error(`[bvsala codex] AVISO: es\
321
+ te 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(M&&le){let t=Ke(T,F.puerto,N,{...M.upstream?{modoCodex:M.
322
+ upstream.includes("chatgpt.com")?"chatgpt":"api-key"}:{}});t.nota&&console.log(`[bvsala ${T}] ${t.nota}`);let e=t.bin;if(process.platform==="win32"){let o=Ut(t.bin);o.tipo==="exe"?e=o.ruta:o.tipo==="s\
323
+ olo-shim"&&(console.error(`[bvsala ${T}] \`${t.bin}\` est\xE1 instalado como shim de npm (${o.ruta}) y Windows no puede lanzarlo de forma segura con argumentos (CVE-2024-27980). Inst\xE1lalo con su insta\
324
+ lador 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.env,...t.env}});n.on(
325
+ "error",o=>{console.error(`[bvsala ${T}] 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)=>{F.cerrar().then(
326
+ ()=>process.exit(o??(r?1:0)));});}else console.log(`[bvsala gateway] apunta tu terminal (o usa \`bvsala ${He.join("|")}\`): ANTHROPIC_BASE_URL=http://127.0.0.1:${F.puerto} claude \xB7 bvsala doctor pa\
327
+ ra el resto`);var rn=async()=>{await F.cerrar(),process.exit(0);};process.on("SIGINT",()=>{rn();});process.on("SIGTERM",()=>{rn();});