@bivelio/savings-layer 0.4.13 → 0.4.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,11 @@
1
- # BV‑SALA — the savings layer for your LLM bill
1
+ <p align="center">
2
+ <img src="https://savings.bivelio.com/brand/savings-logo.png" alt="Savings. by BiVelio" width="360">
3
+ </p>
4
+
5
+ <h1 align="center">The savings layer for your LLM bill</h1>
2
6
 
3
7
  <p align="center">
4
- <img src="https://savings.bivelio.com/en/how-it-works/opengraph-image" alt="Your application → BV-SALA → provider API. The bill drops from $330 to $160 a month, measured." width="720">
8
+ <em>Cut your AI bill — and see exactly why, measured on the same meter your provider bills you with.</em>
5
9
  </p>
6
10
 
7
11
  <p align="center">
@@ -10,10 +14,26 @@
10
14
  <img src="https://img.shields.io/badge/license-commercial-0F1218" alt="Commercial license">
11
15
  </p>
12
16
 
13
- **One layer inside your code, right where your app calls the OpenAI or Anthropic API.**
14
- For every request it picks the cheapest execution that still meets your quality bar —
15
- avoiding calls that don't need to happen and trimming what must be sent — and hands
16
- you an auditable `SavingsReport`. Your bill drops, and you can verify why.
17
+ ### In plain words
18
+
19
+ Every request your app sends to an AI is paid for by the text going in and out.
20
+ **Savings** sits on that path and lets through only what's needed — skipping calls
21
+ that don't have to happen, and trimming what does — so you pay for less. It is not a
22
+ promise you take on faith: **every saving is measured with the provider's official
23
+ meter, the same one on your bill**, and handed back to you request by request.
24
+
25
+ **We only earn when you save.** Our commission comes out of the measured saving,
26
+ never out of your pocket — most of what you save stays with you, and a month with no
27
+ saving is zero commission. And your prompts **never leave your infrastructure**:
28
+ BiVelio only ever sees counts and cost, never your content.
29
+
30
+ ### For engineers, in one line
31
+
32
+ `@bivelio/savings-layer` (**BV‑SALA**) is one layer you add inside your code, right
33
+ where your app calls the OpenAI‑compatible or Anthropic API. For every request it
34
+ picks the cheapest execution that still meets your quality bar and hands you an
35
+ auditable `SavingsReport` — the same numbers your dashboard reads. Traffic still
36
+ goes straight from your app to your provider; the SDK is never a middleman server.
17
37
 
18
38
  > **Commercial software — © 2026 BiVelio Inc.** Free to install, **paid to run**:
19
39
  > BV‑SALA is fail‑closed and executes only with an active BiVelio license key.
@@ -23,14 +43,20 @@ you an auditable `SavingsReport`. Your bill drops, and you can verify why.
23
43
 
24
44
  ## Where it installs
25
45
 
46
+ <p align="center">
47
+ <img src="https://savings.bivelio.com/en/how-it-works/opengraph-image" alt="Your application → BV-SALA → provider API. The bill drops from $330 to $160 a month, measured." width="720">
48
+ </p>
49
+
26
50
  Your application → **BV‑SALA** → provider API. Traffic always goes straight from
27
51
  your app to your provider — BV‑SALA is a library inside your code, never a
28
52
  middleman server, and it works with any OpenAI‑compatible endpoint (OpenAI, Azure,
29
53
  vLLM, SGLang, a gateway) as well as Anthropic.
30
54
 
31
- **Only use ChatGPT or Claude?** Then there is nothing to install: those products
32
- charge a flat subscription, so there is no per‑token bill to cut. BV‑SALA is for
33
- applications that call the API with their own key. The whole story, in plain words:
55
+ **Is this for me?** If your product or automation calls the AI **with its own API
56
+ key** — and pays a per‑token bill for it — yes: this is exactly where the saving
57
+ installs. **Only use ChatGPT or Claude?** Then there is nothing to install: those
58
+ products charge a flat subscription, so there is no per‑token bill to cut. The whole
59
+ story, in plain words:
34
60
  **[Where does the saving install?](https://savings.bivelio.com/en/how-it-works)**
35
61
 
36
62
  **Claude Code, Codex CLI, Goose or Qwen Code with an API key?** The package also
@@ -1,5 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import {spawn}from'child_process';import {existsSync,readFileSync,mkdirSync,writeFileSync}from'fs';import {homedir}from'os';import {join,dirname,delimiter}from'path';import {fileURLToPath}from'url';import {createServer}from'http';import {randomUUID,createHash}from'crypto';import*as A from'zlib';var $e=new Set;function E(e,t){$e.has(e)||($e.add(e),console.warn(t));}var z=class{options;now;flushIntervalMs;maxBatch;maxBuffer;buffer=[];seatId;ci;timer;inflight=null;fallosSeguidos=0;constructor(t){this.options=t,this.now=t.now??(()=>Date.now()),this.flushIntervalMs=
2
+ import {spawn}from'child_process';import {existsSync,readFileSync,mkdirSync,writeFileSync}from'fs';import {homedir}from'os';import {join,dirname,delimiter}from'path';import {fileURLToPath}from'url';import {createServer}from'http';import {randomUUID,createHash}from'crypto';import*as A from'zlib';var X="context-management-2025-06-27";function $e(){return {edits:[{type:"clear_tool_uses_20250919",trigger:{type:"input_tokens",value:5e4},keep:{type:"tool_uses",value:8},clear_at_least:{type:"input_tokens",value:5e3}}]}}function je(e,t){if(t!==void 0&&t!==""&&t!=="identity")return null;try{let n=JSON.parse(e.toString("utf8"));return n===null||typeof n!="object"||Array.isArray(n)||typeof n.model!="string"||!Array.isArray(
3
+ n.messages)?null:(n.context_management=At(n.context_management),Buffer.from(JSON.stringify(n),"utf8"))}catch{return null}}var It="clear_tool_uses_20250919",Ne="clear_thinking_20251015";function At(e){
4
+ let t=$e().edits[0],n=e!==null&&typeof e=="object"&&!Array.isArray(e)?{...e}:{},r=(Array.isArray(n.edits)?n.edits:[]).filter(i=>i!==null&&typeof i=="object"&&!Array.isArray(i)&&i.type!==It),o=r.filter(
5
+ i=>i.type===Ne),s=r.filter(i=>i.type!==Ne);return {...n,edits:[...o,...s,t]}}function ze(e,t){let n=" (se enciende solo si la licencia de la org trae context_elision; fail-closed)";return e==="0"?{linea:"\
6
+ elisi\xF3n S4a: APAGADA (BVSALA_GATEWAY_ELISION=0) \u2014 brazo CONTROL",aviso:false}:t?e==="1"?{linea:"elisi\xF3n S4a: ARMADA (BVSALA_GATEWAY_ELISION=1) \u2014 brazo PALANCA"+n,aviso:false}:{linea:"elisi\xF3n\
7
+ S4a: ARMADA por defecto (sin bandera; =0 la apaga) \u2014 brazo PALANCA"+n,aviso:false}:{linea:"elisi\xF3n S4a: NO SE ARMA \u2014 falta BIVELIO_SERVICE_KEY (sin clave no hay org que consultar); este proceso es \
8
+ brazo CONTROL"+(e==="1"?" AUNQUE la bandera diga =1. Abre un terminal nuevo o exporta la clave y relanza":""),aviso:e==="1"}}function Be(e){return e===void 0||e.trim()===""?X:e.split(",").map(n=>n.trim()).
9
+ filter(n=>n.length>0).includes(X)?e:`${e},${X}`}var Ue=new Set;function C(e,t){Ue.has(e)||(Ue.add(e),console.warn(t));}var z=class{options;now;flushIntervalMs;maxBatch;maxBuffer;buffer=[];seatId;ci;timer;inflight=null;fallosSeguidos=0;constructor(t){this.options=t,this.now=t.now??(()=>Date.now()),this.flushIntervalMs=
3
10
  t.flushIntervalMs??15e3,this.maxBatch=t.maxBatch??50,this.maxBuffer=t.maxBuffer??1e3,this.ci=t.ci??false;}setSeat(t,n){t&&(this.seatId=t),this.ci=n;}record(t){this.buffer.push({report:t,at:this.now()}),this.
4
11
  buffer.length>this.maxBuffer&&this.buffer.splice(0,this.buffer.length-this.maxBuffer),this.buffer.length>=this.maxBatch&&this.flush();}start(){this.timer||(this.timer=setInterval(()=>{this.flush();},this.
5
12
  flushIntervalMs),this.timer.unref?.());}stop(){this.timer&&(clearInterval(this.timer),this.timer=void 0),this.flush();}async stopAndDrain(t){this.timer&&(clearInterval(this.timer),this.timer=void 0);let n=t??
@@ -7,7 +14,7 @@ Math.ceil(this.maxBuffer/this.maxBatch)+4,r=0;for(let o=0;o<n&&this.buffer.lengt
7
14
  inflight)return this.inflight;if(this.buffer.length!==0){this.inflight=this.hacerFlush();try{await this.inflight;}finally{this.inflight=null;}}}async hacerFlush(){let t=this.options.fetchImpl??globalThis.
8
15
  fetch;if(!t)return;let n=this.buffer.splice(0,this.maxBatch);try{let r=n.map(s=>this.toWire(s)),o=await t(this.options.url,{method:"POST",headers:{"content-type":"application/json",authorization:`Bear\
9
16
  er ${this.options.serviceAccountKey}`},body:JSON.stringify(r)});o.ok?this.fallosSeguidos=0:o.status>=500?(this.fallosSeguidos++,this.requeue(n),this.avisarDeFallo(`el servidor respondi\xF3 ${o.status}`)):
10
- o.status===401||o.status===403?(E(`metering-auth-${o.status}`,`[bv-sala] el env\xEDo de uso est\xE1 siendo rechazado con HTTP ${o.status} en ${this.options.url}. Revisa 'serviceAccountKey' (\xBFrotada? \xBF\
17
+ o.status===401||o.status===403?(C(`metering-auth-${o.status}`,`[bv-sala] el env\xEDo de uso est\xE1 siendo rechazado con HTTP ${o.status} en ${this.options.url}. Revisa 'serviceAccountKey' (\xBFrotada? \xBF\
11
18
  revocada? \xBFde otra organizaci\xF3n?). Mientras no funcione NO se reporta uso: el panel dir\xE1 que no ve tr\xE1fico y los asientos facturables saldr\xE1n a cero.`),this.options.onAuthError?.(o.status)):
12
19
  (this.fallosSeguidos++,this.avisarDeFallo(o.status===404||o.status===405?`HTTP ${o.status}: la URL de env\xEDo parece equivocada`:`el servidor rechaz\xF3 el lote con HTTP ${o.status}`));}catch(r){this.
13
20
  fallosSeguidos++,this.requeue(n),this.avisarDeFallo(r instanceof Error?r.message:"error de red");}}avisarDeFallo(t){if(this.options.silenceWarnings)return;let n=this.fallosSeguidos;n<3||(n-3)%12!==0||console.
@@ -17,16 +24,16 @@ length>this.maxBuffer&&(this.buffer.length=this.maxBuffer);}toWire(t){let n=t.re
17
24
  model:n.model,at:t.at,avoidedLlm:n.calls.avoidedLlm,actualLlm:n.calls.actualLlm,baselineInputTokens:n.tokens.baselineInput,actualInputTokens:n.tokens.actualInput,eliminatedInputTokens:n.tokens.eliminatedInput,
18
25
  compressedInputTokens:n.tokens.compressedInput,baselineOutputTokens:n.tokens.baselineOutput,actualOutputTokens:n.tokens.actualOutput,providerCachedInputTokens:n.tokens.providerCachedInput??0,cacheResult:n.
19
26
  cache.result,baselineCost:n.cost.baselineEstimate,actualCost:n.cost.actual,netSavings:n.cost.netSavings,...n.cost.basis?{basis:n.cost.basis}:{},...n.attribution?.sessionId?{sessionId:n.attribution.sessionId}:
20
- {},...n.attribution?.agentId?{agentId:n.attribution.agentId}:{}}}};function X(){return globalThis.process}function Rt(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]";
21
- return new RegExp(`-${t}{8,10}-${t}{5}$`).test(e)}function _t(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??
22
- e.NETLIFY)}async function It(){if(X()?.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 At(e,t=It){
23
- if(e.KUBERNETES_SERVICE_HOST||_t(e))return;let n=e.HOSTNAME??e.COMPUTERNAME??await t();if(!(!n||Rt(n)))return n}async function Pt(){let e=X();if(!e||!e.env)return;let t=e.env,n=await At(t),r=[e.platform,
24
- e.arch,e.execPath,n,t.USER??t.USERNAME??t.LOGNAME,t.HOME??t.USERPROFILE].filter(o=>typeof o=="string"&&o.length>0);return r.length?r.join("|"):void 0}var Ot=["CI","CONTINUOUS_INTEGRATION","GITHUB_ACTI\
25
- ONS","GITLAB_CI","CIRCLECI","TRAVIS","JENKINS_URL","BUILDKITE","TF_BUILD","TEAMCITY_VERSION","BITBUCKET_BUILD_NUMBER","CODEBUILD_BUILD_ID","HEROKU_TEST_RUN_ID","DRONE"];function Z(){let e=X()?.env;if(!e)
26
- return false;for(let t of Ot){let n=e[t];if(n&&n!=="false"&&n!=="0")return true}return false}async function Dt(e,t){let n=globalThis.crypto,r=new TextEncoder;if(n?.subtle)try{let i=await n.subtle.importKey("raw",
27
+ {},...n.attribution?.agentId?{agentId:n.attribution.agentId}:{}}}};function Z(){return globalThis.process}function Pt(e){if(/^[0-9a-f]{12}$/.test(e)||/^\d{1,3}(\.\d{1,3}){3}$/.test(e)||/^ip-\d{1,3}(-\d{1,3}){3}$/i.test(e))return true;let t="[bcdfghjklmnpqrstvwxz2456789]";
28
+ return new RegExp(`-${t}{8,10}-${t}{5}$`).test(e)}function Ot(e){return !!(e.AWS_LAMBDA_FUNCTION_NAME??e.LAMBDA_TASK_ROOT??e.VERCEL??e.VERCEL_ENV??e.K_SERVICE??e.FUNCTION_TARGET??e.FUNCTIONS_WORKER_RUNTIME??
29
+ e.NETLIFY)}async function Dt(){if(Z()?.execPath)try{let t=await import(["node","os"].join(":")),n=typeof t.hostname=="function"?t.hostname():"";return n.length>0?n:void 0}catch{return}}async function Lt(e,t=Dt){
30
+ if(e.KUBERNETES_SERVICE_HOST||Ot(e))return;let n=e.HOSTNAME??e.COMPUTERNAME??await t();if(!(!n||Pt(n)))return n}async function Mt(){let e=Z();if(!e||!e.env)return;let t=e.env,n=await Lt(t),r=[e.platform,
31
+ e.arch,e.execPath,n,t.USER??t.USERNAME??t.LOGNAME,t.HOME??t.USERPROFILE].filter(o=>typeof o=="string"&&o.length>0);return r.length?r.join("|"):void 0}var $t=["CI","CONTINUOUS_INTEGRATION","GITHUB_ACTI\
32
+ ONS","GITLAB_CI","CIRCLECI","TRAVIS","JENKINS_URL","BUILDKITE","TF_BUILD","TEAMCITY_VERSION","BITBUCKET_BUILD_NUMBER","CODEBUILD_BUILD_ID","HEROKU_TEST_RUN_ID","DRONE"];function ee(){let e=Z()?.env;if(!e)
33
+ return false;for(let t of $t){let n=e[t];if(n&&n!=="false"&&n!=="0")return true}return false}async function Nt(e,t){let n=globalThis.crypto,r=new TextEncoder;if(n?.subtle)try{let i=await n.subtle.importKey("raw",
27
34
  r.encode(e),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),a=await n.subtle.sign("HMAC",i,r.encode(t));return [...new Uint8Array(a)].map(u=>u.toString(16).padStart(2,"0")).join("")}catch{}let o=2166136261,s=`${e}\
28
- |${t}`;for(let i=0;i<s.length;i++)o^=s.charCodeAt(i),o=Math.imul(o,16777619);return (o>>>0).toString(16).padStart(8,"0")}async function ee(e){let n=X()?.env?.BVSALA_SEAT_ID;if(n&&Lt.test(n))return n;let r=await Pt();
29
- if(!r)return;let o=await Dt(e,r);if(o)return `m-${o.slice(0,32)}`}var Lt=/^[A-Za-z0-9._:/-]{1,128}$/;var pe={"gpt-4.1":{inputPer1k:.002,outputPer1k:.008,cachedInputPer1k:5e-4},"gpt-4.1-mini":{inputPer1k:4e-4,outputPer1k:.0016,cachedInputPer1k:1e-4},"gpt-4.1-nano":{inputPer1k:1e-4,outputPer1k:4e-4,cachedInputPer1k:25e-6},
35
+ |${t}`;for(let i=0;i<s.length;i++)o^=s.charCodeAt(i),o=Math.imul(o,16777619);return (o>>>0).toString(16).padStart(8,"0")}async function te(e){let n=Z()?.env?.BVSALA_SEAT_ID;if(n&&jt.test(n))return n;let r=await Mt();
36
+ if(!r)return;let o=await Nt(e,r);if(o)return `m-${o.slice(0,32)}`}var jt=/^[A-Za-z0-9._:/-]{1,128}$/;var me={"gpt-4.1":{inputPer1k:.002,outputPer1k:.008,cachedInputPer1k:5e-4},"gpt-4.1-mini":{inputPer1k:4e-4,outputPer1k:.0016,cachedInputPer1k:1e-4},"gpt-4.1-nano":{inputPer1k:1e-4,outputPer1k:4e-4,cachedInputPer1k:25e-6},
30
37
  "gpt-4o":{inputPer1k:.0025,outputPer1k:.01,cachedInputPer1k:.00125},"gpt-4o-mini":{inputPer1k:15e-5,outputPer1k:6e-4,cachedInputPer1k:75e-6},"gpt-4-turbo":{inputPer1k:.01,outputPer1k:.03},"gpt-4":{inputPer1k:.03,
31
38
  outputPer1k:.06},"gpt-3.5-turbo":{inputPer1k:5e-4,outputPer1k:.0015},"gpt-5":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},"gpt-5-codex":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},
32
39
  "gpt-5-mini":{inputPer1k:25e-5,outputPer1k:.002,cachedInputPer1k:25e-6},"gpt-5-nano":{inputPer1k:5e-5,outputPer1k:4e-4,cachedInputPer1k:5e-6},"gpt-5.1-codex":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},
@@ -38,104 +45,104 @@ t-5.6-sol":{inputPer1k:.004,outputPer1k:.02,cachedInputPer1k:4e-4},"gpt-5.6-terr
38
45
  "claude-opus-4-6":{inputPer1k:.005,outputPer1k:.025,cachedInputPer1k:5e-4},"claude-opus-4-7":{inputPer1k:.005,outputPer1k:.025,cachedInputPer1k:5e-4},"claude-opus-4-8":{inputPer1k:.005,outputPer1k:.025,
39
46
  cachedInputPer1k:5e-4},"claude-opus-5":{inputPer1k:.005,outputPer1k:.025,cachedInputPer1k:5e-4},"claude-opus-4":{inputPer1k:.015,outputPer1k:.075,cachedInputPer1k:.0015},"claude-sonnet-4-5":{inputPer1k:.003,
40
47
  outputPer1k:.015,cachedInputPer1k:3e-4},"claude-sonnet-4-6":{inputPer1k:.003,outputPer1k:.015,cachedInputPer1k:3e-4},"claude-sonnet-5":{inputPer1k:.002,outputPer1k:.01,cachedInputPer1k:2e-4},"claude-f\
41
- able-5":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:.001},"claude-sonnet-4":{inputPer1k:.003,outputPer1k:.015,cachedInputPer1k:3e-4},"claude-haiku-4-5":{inputPer1k:.001,outputPer1k:.005,cachedInputPer1k:1e-4},
42
- "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,outputPer1k:.075,
43
- cachedInputPer1k:.0015},"claude-3-haiku":{inputPer1k:25e-5,outputPer1k:.00125,cachedInputPer1k:3e-5},"gemini-3.7-flash":{inputPer1k:75e-5,outputPer1k:.00375,cachedInputPer1k:75e-6},"gemini-3.5-flash":{
44
- inputPer1k:.0015,outputPer1k:.009,cachedInputPer1k:15e-5},"gemini-3.5-flash-lite":{inputPer1k:3e-4,outputPer1k:.0025,cachedInputPer1k:3e-5},"gemini-3.1-pro-preview":{inputPer1k:.002,outputPer1k:.012,cachedInputPer1k:2e-4},
45
- "gemini-2.5-pro":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},"gemini-2.5-flash":{inputPer1k:3e-4,outputPer1k:.0025,cachedInputPer1k:3e-5}};function Ne(e,t,n){if(!n)return;let r=e[n];if(r)
46
- return r;let o=n.lastIndexOf("/"),s=o>=0?n.slice(o+1):n,i=e[s];if(i)return i;for(let a of t){if(!s.startsWith(a))continue;let u=s.charAt(a.length);if(u!==""&&u!=="-"&&u!=="."&&u!=="_")continue;let p=s.
47
- slice(a.length+1);if(!(/^\d/.test(p)&&!/^\d{4}/.test(p)))return e[a]}}function me(e){return Object.keys(e).sort((t,n)=>n.length-t.length)}var Mt=me(pe);function M(e){return Ne(pe,Mt,e)}var $=class{resto="";uso=null;elisionObservada=null;eventos={};observar(t){this.resto+=typeof t=="string"?t:t.toString("utf8");let n;for(;(n=this.resto.indexOf(`
48
+ able-5":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:.001},"claude-fable-5-1":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:25e-5},"claude-mythos-5-1":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:25e-5},
49
+ "claude-mythos-5":{inputPer1k:.01,outputPer1k:.05,cachedInputPer1k:.001},"claude-sonnet-4":{inputPer1k:.003,outputPer1k:.015,cachedInputPer1k:3e-4},"claude-haiku-4-5":{inputPer1k:.001,outputPer1k:.005,
50
+ cachedInputPer1k:1e-4},"claude-3-5-sonnet":{inputPer1k:.003,outputPer1k:.015,cachedInputPer1k:3e-4},"claude-3-5-haiku":{inputPer1k:8e-4,outputPer1k:.004,cachedInputPer1k:8e-5},"claude-3-opus":{inputPer1k:.015,
51
+ outputPer1k:.075,cachedInputPer1k:.0015},"claude-3-haiku":{inputPer1k:25e-5,outputPer1k:.00125,cachedInputPer1k:3e-5},"gemini-3.7-flash":{inputPer1k:75e-5,outputPer1k:.00375,cachedInputPer1k:75e-6},"g\
52
+ emini-3.5-flash":{inputPer1k:.0015,outputPer1k:.009,cachedInputPer1k:15e-5},"gemini-3.5-flash-lite":{inputPer1k:3e-4,outputPer1k:.0025,cachedInputPer1k:3e-5},"gemini-3.1-pro-preview":{inputPer1k:.002,
53
+ outputPer1k:.012,cachedInputPer1k:2e-4},"gemini-2.5-pro":{inputPer1k:.00125,outputPer1k:.01,cachedInputPer1k:125e-6},"gemini-2.5-flash":{inputPer1k:3e-4,outputPer1k:.0025,cachedInputPer1k:3e-5}};function Ve(e,t,n){
54
+ if(!n)return;let r=e[n];if(r)return r;let o=n.lastIndexOf("/"),s=o>=0?n.slice(o+1):n,i=e[s];if(i)return i;for(let a of t){if(!s.startsWith(a))continue;let u=s.charAt(a.length);if(u!==""&&u!=="-"&&u!==
55
+ "."&&u!=="_")continue;let p=s.slice(a.length+1);if(!(/^\d/.test(p)&&!/^\d{4}/.test(p)))return e[a]}}function fe(e){return Object.keys(e).sort((t,n)=>n.length-t.length)}var zt=fe(me);function M(e){return Ve(
56
+ me,zt,e)}var $=class{resto="";uso=null;elisionObservada=null;eventos={};observar(t){this.resto+=typeof t=="string"?t:t.toString("utf8");let n;for(;(n=this.resto.indexOf(`
48
57
 
49
58
  `))>=0;){let r=this.resto.slice(0,n);this.resto=this.resto.slice(n+2);let o=/^event: (.+)$/m.exec(r)?.[1];if(o&&(this.eventos[o]=(this.eventos[o]??0)+1),o!=="message_start"&&o!=="message_delta")continue;
50
- let s=/^data: (.+)$/m.exec(r)?.[1];if(s)try{let i=JSON.parse(s),a=ze(i.context_management);a&&(this.elisionObservada=a);let u=i.usage??i.message?.usage;if(u){let p=u.cache_creation||this.uso?.cache_creation?
59
+ let s=/^data: (.+)$/m.exec(r)?.[1];if(s)try{let i=JSON.parse(s),a=qe(i.context_management);a&&(this.elisionObservada=a);let u=i.usage??i.message?.usage;if(u){let p=u.cache_creation||this.uso?.cache_creation?
51
60
  {...this.uso?.cache_creation,...u.cache_creation}:void 0;this.uso={...this.uso,...u,...p?{cache_creation:p}:{}};}}catch{}}}usage(){return this.uso}usageFinal(){return (this.eventos.message_delta??0)>0?this.
52
- uso:null}elision(){return this.elisionObservada}};function ze(e){if(e===null||typeof e!="object")return null;let t=e.applied_edits;if(!Array.isArray(t)||t.length===0)return null;let n=0;for(let r of t){
53
- let o=r.cleared_input_tokens;typeof o=="number"&&Number.isFinite(o)&&o>0&&(n+=o);}return {borrados:t.length,tokensLimpiados:n}}function Be(e){try{let t=JSON.parse(typeof e=="string"?e:e.toString("utf8"));
54
- return ze(t.context_management)}catch{return null}}var te=class{resto="";uso=null;eventos={};observar(t){this.resto+=typeof t=="string"?t:t.toString("utf8");let n;for(;(n=this.resto.indexOf(`
61
+ uso:null}elision(){return this.elisionObservada}};function qe(e){if(e===null||typeof e!="object")return null;let t=e.applied_edits;if(!Array.isArray(t)||t.length===0)return null;let n=0;for(let r of t){
62
+ let o=r.cleared_input_tokens;typeof o=="number"&&Number.isFinite(o)&&o>0&&(n+=o);}return {borrados:t.length,tokensLimpiados:n}}function Ke(e){try{let t=JSON.parse(typeof e=="string"?e:e.toString("utf8"));
63
+ return qe(t.context_management)}catch{return null}}var ne=class{resto="";uso=null;eventos={};observar(t){this.resto+=typeof t=="string"?t:t.toString("utf8");let n;for(;(n=this.resto.indexOf(`
55
64
 
56
65
  `))>=0;){let r=this.resto.slice(0,n);this.resto=this.resto.slice(n+2);let o=/^event: (.+)$/m.exec(r)?.[1];o&&(this.eventos[o]=(this.eventos[o]??0)+1);let s=/^data: (.+)$/m.exec(r)?.[1];if(s)try{let i=JSON.
57
- parse(s);if((o??i.type)!=="response.completed")continue;let a=i.response?.usage;a&&(this.uso=$t(a));}catch{}}}usage(){return this.uso}usageFinal(){return this.uso}};function $t(e){let t=Math.max(0,e.input_tokens??
66
+ parse(s);if((o??i.type)!=="response.completed")continue;let a=i.response?.usage;a&&(this.uso=Bt(a));}catch{}}}usage(){return this.uso}usageFinal(){return this.uso}};function Bt(e){let t=Math.max(0,e.input_tokens??
58
67
  0),n=Math.min(Math.max(0,e.input_tokens_details?.cached_tokens??0),t),r=Math.min(Math.max(0,e.input_tokens_details?.cache_write_tokens??0),t-n);return {input_tokens:t-n-r,output_tokens:Math.max(0,e.output_tokens??
59
- 0),cache_read_input_tokens:n,cache_creation_input_tokens:r}}var je=1.25,fe=2;function Ue(e,t){let n=M(e);if(!n)return null;let r=t.input_tokens??0,o=t.output_tokens??0,s=t.cache_read_input_tokens??0,i=t.
68
+ 0),cache_read_input_tokens:n,cache_creation_input_tokens:r}}var Fe=1.25,he=2;function He(e,t){let n=M(e);if(!n)return null;let r=t.input_tokens??0,o=t.output_tokens??0,s=t.cache_read_input_tokens??0,i=t.
60
69
  cache_creation,a=t.cache_creation_input_tokens??(i?.ephemeral_5m_input_tokens??0)+(i?.ephemeral_1h_input_tokens??0),u=Math.min(i?.ephemeral_1h_input_tokens??0,a),p=n.cachedInputPer1k??n.inputPer1k;return {
61
- costeUsd:r/1e3*n.inputPer1k+s/1e3*p+(a-u)/1e3*n.inputPer1k*ge(e)+u/1e3*n.inputPer1k*fe+o/1e3*n.outputPer1k,precio:n,tokens:{entrada:r,salida:o,cacheLeida:s,cacheEscrita:a,cacheEscrita1h:u}}}function Ve(e,t){
62
- let r=he(e,t)?.model;return typeof r=="string"?r:""}function he(e,t){try{let n=e,r={maxOutputLength:Nt};switch((t??"").trim().toLowerCase()){case "gzip":case "x-gzip":n=A.gunzipSync(e,r);break;case "defl\
70
+ costeUsd:r/1e3*n.inputPer1k+s/1e3*p+(a-u)/1e3*n.inputPer1k*be(e)+u/1e3*n.inputPer1k*he+o/1e3*n.outputPer1k,precio:n,tokens:{entrada:r,salida:o,cacheLeida:s,cacheEscrita:a,cacheEscrita1h:u}}}function Je(e,t){
71
+ let r=ge(e,t)?.model;return typeof r=="string"?r:""}function ge(e,t){try{let n=e,r={maxOutputLength:Ut};switch((t??"").trim().toLowerCase()){case "gzip":case "x-gzip":n=A.gunzipSync(e,r);break;case "defl\
63
72
  ate":n=A.inflateSync(e,r);break;case "br":n=A.brotliDecompressSync(e,r);break;case "zstd":{let o=A.zstdDecompressSync;if(typeof o!="function")return null;n=o(e,r);break}default:break}return JSON.parse(n.
64
- toString("utf8"))}catch{return null}}var Nt=5*1024*1024;function Fe(){return typeof A.zstdDecompressSync=="function"}function ge(e){let t=e.toLowerCase();return t.startsWith("gpt-")||t.startsWith("o1")||
65
- t.startsWith("o3")||t.startsWith("o4")?/^gpt-5\.6/.test(t)?je:1:t.startsWith("gemini")?1:je}function be(e){try{return JSON.parse(typeof e=="string"?e:e.toString("utf8")).usage??null}catch{return null}}
66
- function qe(e,t,n,r,o){return Je(e,t,n,false,r,o)}function Ke(e,t,n,r){return Je(e,t,n,true,r)}function He(e,t,n,r,o){return {requestId:e,model:t,...o&&(o.sessionId||o.agentId)?{attribution:o}:{},calls:{avoidedLlm:0,
73
+ toString("utf8"))}catch{return null}}var Ut=5*1024*1024;function We(){return typeof A.zstdDecompressSync=="function"}function be(e){let t=e.toLowerCase();return t.startsWith("gpt-")||t.startsWith("o1")||
74
+ t.startsWith("o3")||t.startsWith("o4")?/^gpt-5\.6/.test(t)?Fe:1:t.startsWith("gemini")?1:Fe}function ve(e){try{return JSON.parse(typeof e=="string"?e:e.toString("utf8")).usage??null}catch{return null}}
75
+ function Ge(e,t,n,r,o){return Xe(e,t,n,false,r,o)}function Ye(e,t,n,r){return Xe(e,t,n,true,r)}function Qe(e,t,n,r,o){return {requestId:e,model:t,...o&&(o.sessionId||o.agentId)?{attribution:o}:{},calls:{avoidedLlm:0,
67
76
  actualLlm:0},tokens:{baselineInput:0,actualInput:0,eliminatedInput:0,compressedInput:0,baselineOutput:0,actualOutput:0,providerCachedInput:0},cache:{result:"miss"},cost:{baselineEstimate:n,actual:r,netSavings:n>
68
- 0?Math.max(-100,Math.min(1,(n-r)/n)):0,basis:"shadow"}}}function Je(e,t,n,r,o,s){let i=n.tokens.entrada+n.tokens.cacheLeida+n.tokens.cacheEscrita;return {requestId:e,model:t,...o&&(o.sessionId||o.agentId)?
77
+ 0?Math.max(-100,Math.min(1,(n-r)/n)):0,basis:"shadow"}}}function Xe(e,t,n,r,o,s){let i=n.tokens.entrada+n.tokens.cacheLeida+n.tokens.cacheEscrita;return {requestId:e,model:t,...o&&(o.sessionId||o.agentId)?
69
78
  {attribution:o}:{},calls:r?{avoidedLlm:1,actualLlm:0}:{avoidedLlm:0,actualLlm:1},tokens:{baselineInput:i,actualInput:r?0:i,eliminatedInput:r?0:s?.tokensLimpiados??0,compressedInput:0,baselineOutput:n.
70
79
  tokens.salida,actualOutput:r?0:n.tokens.salida,providerCachedInput:r?0:n.tokens.cacheLeida},cache:{result:r?"singleflight":"miss"},cost:r?{baselineEstimate:n.costeUsd,actual:0,netSavings:1,basis:"esti\
71
- mated"}:{baselineEstimate:n.costeUsd,actual:n.costeUsd,netSavings:0,basis:"measured"}}}var zt=1024,q=120,Bt=8,Ut=256*1024,Vt=/error|exception|traceback|warn|fatal|fail|panic|assert|denied|refused|timeout|\bat\s+\S+:\d+/i,Ge=/^\s*(export\s|import\s|function\s|class\s|interface\s|type\s|enum\s|def\s|fn\s|func\s|impl\s|struct\s|trait\s|package\s|module\s|@\w)/;
72
- function Ft(e){return Buffer.byteLength(typeof e=="string"?e:JSON.stringify(e??""))}function qt(e){return typeof e=="string"?e:Array.isArray(e)?e.map(t=>t&&typeof t=="object"&&typeof t.text=="string"?
80
+ mated"}:{baselineEstimate:n.costeUsd,actual:n.costeUsd,netSavings:0,basis:"measured"}}}var Ft=1024,q=120,qt=8,Kt=256*1024,Ht=/error|exception|traceback|warn|fatal|fail|panic|assert|denied|refused|timeout|\bat\s+\S+:\d+/i,et=/^\s*(export\s|import\s|function\s|class\s|interface\s|type\s|enum\s|def\s|fn\s|func\s|impl\s|struct\s|trait\s|package\s|module\s|@\w)/;
81
+ function Jt(e){return Buffer.byteLength(typeof e=="string"?e:JSON.stringify(e??""))}function Wt(e){return typeof e=="string"?e:Array.isArray(e)?e.map(t=>t&&typeof t=="object"&&typeof t.text=="string"?
73
82
  t.text:"").join(`
74
- `):""}var Kt=/^\s*\d+[\t→]/;function Ye(e){return e.replace(Kt,"")}function Ht(e){if(!e)return "otro";let t=e.split(`
75
- `),n=Math.max(1,t.length),r=0,o=0,s=0;for(let i of t){let a=Ye(i);(/^[+-](?![+-])/.test(a)||a.startsWith("@@")||a.startsWith("diff --git"))&&(r+=1),Ge.test(a)&&(o+=1),(/^\s*(\d{4}-\d{2}-\d{2}|\[\d|\d{2}:\d{2}:\d{2})/.
76
- test(a)||/\b(INFO|DEBUG|TRACE|WARN|ERROR)\b/.test(a))&&(s+=1);}return r/n>.25?"diff":s/n>.3?"log":o/n>.08?"codigo":"otro"}function Jt(e,t){if(t==="diff"||t==="otro")return Buffer.byteLength(e);let n=e.
83
+ `):""}var Gt=/^\s*\d+[\t→]/;function tt(e){return e.replace(Gt,"")}function Yt(e){if(!e)return "otro";let t=e.split(`
84
+ `),n=Math.max(1,t.length),r=0,o=0,s=0;for(let i of t){let a=tt(i);(/^[+-](?![+-])/.test(a)||a.startsWith("@@")||a.startsWith("diff --git"))&&(r+=1),et.test(a)&&(o+=1),(/^\s*(\d{4}-\d{2}-\d{2}|\[\d|\d{2}:\d{2}:\d{2})/.
85
+ test(a)||/\b(INFO|DEBUG|TRACE|WARN|ERROR)\b/.test(a))&&(s+=1);}return r/n>.25?"diff":s/n>.3?"log":o/n>.08?"codigo":"otro"}function Qt(e,t){if(t==="diff"||t==="otro")return Buffer.byteLength(e);let n=e.
77
86
  split(`
78
- `),r=new Set;for(let s=0;s<n.length;s++){let i=Ye(n[s]);(t==="log"?Vt.test(i):Ge.test(i))&&(r.add(s),t==="log"&&(s>0&&r.add(s-1),s<n.length-1&&r.add(s+1)));}let o=q;for(let s of r)o+=Buffer.byteLength(
79
- n[s])+1;return Math.min(o,Buffer.byteLength(e))}function Qe(e){let t=[],n=(r,o)=>{let s=Ft(o),i={clave:createHash("sha256").update(typeof o=="string"?o:JSON.stringify(o??"")).digest("hex").slice(0,16),tipo:r,
80
- bytes:s,bytesV1:s,clase:"otro",esError:false};if(r.endsWith(":tool_result")&&o&&typeof o=="object"){let a=o;i.esError=a.is_error===true;let u=qt(a.content);i.clase=Ht(u);let p=s-Buffer.byteLength(u);i.bytesV1=
81
- Math.min(s,Math.max(0,p)+Jt(u,i.clase));}t.push(i);};if((e.system??void 0)!==void 0&&n("system",e.system),Array.isArray(e.tools))for(let r of e.tools)n("tools",r);for(let r of Array.isArray(e.messages)?
87
+ `),r=new Set;for(let s=0;s<n.length;s++){let i=tt(n[s]);(t==="log"?Ht.test(i):et.test(i))&&(r.add(s),t==="log"&&(s>0&&r.add(s-1),s<n.length-1&&r.add(s+1)));}let o=q;for(let s of r)o+=Buffer.byteLength(
88
+ n[s])+1;return Math.min(o,Buffer.byteLength(e))}function nt(e){let t=[],n=(r,o)=>{let s=Jt(o),i={clave:createHash("sha256").update(typeof o=="string"?o:JSON.stringify(o??"")).digest("hex").slice(0,16),tipo:r,
89
+ bytes:s,bytesV1:s,clase:"otro",esError:false};if(r.endsWith(":tool_result")&&o&&typeof o=="object"){let a=o;i.esError=a.is_error===true;let u=Wt(a.content);i.clase=Yt(u);let p=s-Buffer.byteLength(u);i.bytesV1=
90
+ Math.min(s,Math.max(0,p)+Qt(u,i.clase));}t.push(i);};if((e.system??void 0)!==void 0&&n("system",e.system),Array.isArray(e.tools))for(let r of e.tools)n("tools",r);for(let r of Array.isArray(e.messages)?
82
91
  e.messages:[]){if(!r||typeof r!="object"){n("?:invalido",r);continue}let o=r,s=typeof o.role=="string"?o.role:"?";if(typeof o.content=="string")n(`${s}:text`,o.content);else if(Array.isArray(o.content))
83
- for(let i of o.content)n(`${s}:${i?.type??"?"}`,i);}return t}function Wt(){return {nacimiento:new Map,turno:0,elididosV2m:new Set}}function Gt(e,t){let n=e.turno++;for(let r of t)e.nacimiento.has(r.clave)||
84
- e.nacimiento.set(r.clave,n);return n}function Xe(e,t,n,r,o=Ut){let s=t.reduce((l,c,d)=>c.tipo.endsWith(":tool_result")?d:l,-1),i=(l,c)=>l.tipo.endsWith(":tool_result")&&l.bytes>=zt&&c!==s;return t.map((l,c)=>{if(!i(l,c))return {clave:l.clave,bytes:l.bytes};let d=r-(n.nacimiento.get(l.clave)??r);return d>=2&&d*l.bytes/1024>=Bt?{clave:`${l.clave}:e`,bytes:q}:{clave:l.clave,bytes:l.bytes}});
85
- }function Yt(e){let t=M(e);return t?{lecturaPer1k:t.cachedInputPer1k??t.inputPer1k,escrituraPer1k:t.
86
- inputPer1k*ge(e),escritura1hPer1k:t.inputPer1k*fe}:null}function We(){return {lecturaUsd:0,escrituraUsd:0,totalUsd:0,tokensLeidos:0,tokensEscritos:0,tokensInvalidados:0,invalidacionUsd:0}}var Qt={"1h":36e5,
87
- "5m":3e5},K=class{constructor(t){this.transformar=t;}transformar;estado=Wt();previo=[];hayPrevio=false;atPrevio=0;acumulado=We();paso(t){let n=We(),r=Gt(this.estado,t.bloques),o=Yt(t.model),s=this.transformar(
88
- t.bloques,this.estado,r);if(!o||t.entradaReal<=0)return this.previo=s,this.hayPrevio=true,this.atPrevio=t.at,n;let i=t.bloques.reduce((h,b)=>h+b.bytes,0),a=i>0?t.entradaReal/i:0,u=Qt[t.escritura1h?"1h":
92
+ for(let i of o.content)n(`${s}:${i?.type??"?"}`,i);}return t}function Xt(){return {nacimiento:new Map,turno:0,elididosV2m:new Set}}function Zt(e,t){let n=e.turno++;for(let r of t)e.nacimiento.has(r.clave)||
93
+ e.nacimiento.set(r.clave,n);return n}function ot(e,t,n,r,o=Kt){let s=t.reduce((l,c,d)=>c.tipo.endsWith(":tool_result")?d:l,-1),i=(l,c)=>l.tipo.endsWith(":tool_result")&&l.bytes>=Ft&&c!==s;return t.map((l,c)=>{if(!i(l,c))return {clave:l.clave,bytes:l.bytes};let d=r-(n.nacimiento.get(l.clave)??r);return d>=2&&d*l.bytes/1024>=qt?{clave:`${l.clave}:e`,bytes:q}:{clave:l.clave,bytes:l.bytes}});
94
+ }function en(e){let t=M(e);return t?{lecturaPer1k:t.cachedInputPer1k??t.inputPer1k,escrituraPer1k:t.
95
+ inputPer1k*be(e),escritura1hPer1k:t.inputPer1k*he}:null}function Ze(){return {lecturaUsd:0,escrituraUsd:0,totalUsd:0,tokensLeidos:0,tokensEscritos:0,tokensInvalidados:0,invalidacionUsd:0}}var tn={"1h":36e5,
96
+ "5m":3e5},K=class{constructor(t){this.transformar=t;}transformar;estado=Xt();previo=[];hayPrevio=false;atPrevio=0;acumulado=Ze();paso(t){let n=Ze(),r=Zt(this.estado,t.bloques),o=en(t.model),s=this.transformar(
97
+ t.bloques,this.estado,r);if(!o||t.entradaReal<=0)return this.previo=s,this.hayPrevio=true,this.atPrevio=t.at,n;let i=t.bloques.reduce((h,b)=>h+b.bytes,0),a=i>0?t.entradaReal/i:0,u=tn[t.escritura1h?"1h":
89
98
  "5m"],p=this.hayPrevio&&t.at-this.atPrevio>u,m=0;if(!p)for(;m<s.length&&m<this.previo.length&&s[m].clave===this.previo[m].clave&&s[m].bytes===this.previo[m].bytes;)m+=1;let l=this.previo.slice(m),c=0,
90
99
  d=t.escritura1h?o.escritura1hPer1k:o.escrituraPer1k;for(let h=0;h<s.length;h++){let b=s[h],v=b.bytes*a;if(h<m){n.tokensLeidos+=v,n.lecturaUsd+=v/1e3*o.lecturaPer1k;continue}if(n.tokensEscritos+=v,n.escrituraUsd+=
91
100
  v/1e3*d,!p){let f=c;for(;f<l.length&&l[f].clave!==b.clave;)f+=1;f<l.length&&(l[f].bytes===b.bytes&&(n.tokensInvalidados+=v,n.invalidacionUsd+=v/1e3*(d-o.lecturaPer1k)),c=f+1);}}return this.previo=s,this.
92
101
  hayPrevio=true,this.atPrevio=t.at,n.totalUsd=n.lecturaUsd+n.escrituraUsd,this.acumulado.lecturaUsd+=n.lecturaUsd,this.acumulado.escrituraUsd+=n.escrituraUsd,this.acumulado.totalUsd+=n.totalUsd,this.acumulado.
93
- tokensLeidos+=n.tokensLeidos,this.acumulado.tokensEscritos+=n.tokensEscritos,this.acumulado.tokensInvalidados+=n.tokensInvalidados,this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function Ze(e){return e.map(t=>({clave:t.clave,bytes:t.bytes}))}var Zt=64,ne=class{cadenas=new Map;observar(t){let n=t.uso.cache_creation_input_tokens??(t.uso.cache_creation?.ephemeral_5m_input_tokens??0)+(t.uso.cache_creation?.ephemeral_1h_input_tokens??0),r=(t.uso.
94
- input_tokens??0)+(t.uso.cache_read_input_tokens??0)+n;if(r<=0)return null;let o={bloques:Qe(t.cuerpo),at:t.at,model:t.model,entradaReal:r,escritura1h:(t.uso.cache_creation?.ephemeral_1h_input_tokens??
102
+ tokensLeidos+=n.tokensLeidos,this.acumulado.tokensEscritos+=n.tokensEscritos,this.acumulado.tokensInvalidados+=n.tokensInvalidados,this.acumulado.invalidacionUsd+=n.invalidacionUsd,n}};function rt(e){return e.map(t=>({clave:t.clave,bytes:t.bytes}))}var on=64,oe=class{cadenas=new Map;observar(t){let n=t.uso.cache_creation_input_tokens??(t.uso.cache_creation?.ephemeral_5m_input_tokens??0)+(t.uso.cache_creation?.ephemeral_1h_input_tokens??0),r=(t.uso.
103
+ input_tokens??0)+(t.uso.cache_read_input_tokens??0)+n;if(r<=0)return null;let o={bloques:nt(t.cuerpo),at:t.at,model:t.model,entradaReal:r,escritura1h:(t.uso.cache_creation?.ephemeral_1h_input_tokens??
95
104
  0)>0};if(o.bloques.length===0)return null;let s=this.cadenaPara(this.clave(t)),i=s.base.paso(o),a=s.v0.paso(o);return i.totalUsd<=0&&a.totalUsd<=0?null:{baselineUsd:i.totalUsd,politicaUsd:a.totalUsd}}clave(t){
96
105
  if(t.sessionId)return `s:${t.sessionId}\xB7a:${t.agentId??""}\xB7${t.model}`;let n=Array.isArray(t.cuerpo.messages)?t.cuerpo.messages[0]:void 0;return `m:${createHash("sha256").update(JSON.stringify(n??null)).digest(
97
- "hex").slice(0,16)}\xB7${t.model}`}cadenaPara(t){let n=this.cadenas.get(t);if(!n&&(n={base:new K(r=>Ze(r)),v0:new K((r,o,s)=>Xe("v0",r,o,s)),ultimoUso:0},this.cadenas.set(t,n),this.cadenas.size>Zt)){let r=null,
98
- o=1/0;for(let[s,i]of this.cadenas)i.ultimoUso<o&&(o=i.ultimoUso,r=s);r!==null&&this.cadenas.delete(r);}return n.ultimoUso=Date.now(),n}};var oe=class{url;clave;ttlMs;fetchImpl;log;features=new Set;validoHasta=0;enVuelo=null;avisado=false;constructor(t){this.url=t.url,this.clave=t.serviceAccountKey,this.ttlMs=t.ttlMs??3e5,this.fetchImpl=t.
106
+ "hex").slice(0,16)}\xB7${t.model}`}cadenaPara(t){let n=this.cadenas.get(t);if(!n&&(n={base:new K(r=>rt(r)),v0:new K((r,o,s)=>ot("v0",r,o,s)),ultimoUso:0},this.cadenas.set(t,n),this.cadenas.size>on)){let r=null,
107
+ o=1/0;for(let[s,i]of this.cadenas)i.ultimoUso<o&&(o=i.ultimoUso,r=s);r!==null&&this.cadenas.delete(r);}return n.ultimoUso=Date.now(),n}};var re=class{url;clave;ttlMs;fetchImpl;log;features=new Set;validoHasta=0;enVuelo=null;avisado=false;constructor(t){this.url=t.url,this.clave=t.serviceAccountKey,this.ttlMs=t.ttlMs??3e5,this.fetchImpl=t.
99
108
  fetchImpl??fetch,this.log=t.log??(()=>{}),this.refrescar();}tiene(t){return Date.now()>this.validoHasta&&this.enVuelo===null&&this.refrescar(),this.features.has(t)}refrescar(){return this.enVuelo?this.
100
109
  enVuelo:(this.enVuelo=this.pedir().finally(()=>{this.enVuelo=null;}),this.enVuelo)}async pedir(){try{let t=await this.fetchImpl(this.url,{method:"GET",headers:{authorization:`Bearer ${this.clave}`},signal:AbortSignal.
101
110
  timeout(1e4)});if(!t.ok){this.cerrar(`entitlements HTTP ${t.status}`);return}let n=await t.json();if(!Array.isArray(n.features)||!n.features.every(o=>typeof o=="string")){this.cerrar("entitlements con\
102
111
  forma inesperada");return}this.features=new Set(n.features);let r=typeof n.refreshAfterSeconds=="number"&&n.refreshAfterSeconds>0?Math.min(n.refreshAfterSeconds*1e3,this.ttlMs):this.ttlMs;this.validoHasta=
103
112
  Date.now()+r,this.avisado=!1;}catch(t){this.cerrar(String(t));}}cerrar(t){this.features=new Set,this.validoHasta=Date.now()+Math.min(6e4,this.ttlMs),this.avisado||(this.avisado=true,this.log(`[gateway] en\
104
- titlements no disponibles (${t}) \u2014 palanca apagada (fail-closed)`));}};var re="context-management-2025-06-27";function et(){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 tt(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(
105
- n.messages)?null:(n.context_management=et(),Buffer.from(JSON.stringify(n),"utf8"))}catch{return null}}function nt(e){return e===void 0||e.trim()===""?re:e.split(",").map(n=>n.trim()).filter(n=>n.length>
106
- 0).includes(re)?e:`${e},${re}`}var ve=5*1024*1024,tn=["authorization","x-api-key","anthropic-version","anthropic-beta"];function ot(e,t,n,r=""){return createHash("sha256").update(e).update(`
113
+ titlements no disponibles (${t}) \u2014 palanca apagada (fail-closed)`));}};var ye=5*1024*1024,sn=["authorization","x-api-key","anthropic-version","anthropic-beta"];function st(e,t,n,r=""){return createHash("sha256").update(e).update(`
107
114
  `).update(t).update(`
108
115
  `).update(r).update(`
109
- `).update(n).digest("hex")}function rt(e){return tn.map(t=>`${t}=${e(t)??""}`).join(`
116
+ `).update(n).digest("hex")}function it(e){return sn.map(t=>`${t}=${e(t)??""}`).join(`
110
117
  `)}var se=class{enVuelo=new Map;primarias=0;gemelas=0;registrar(t){if(this.enVuelo.has(t))return null;this.primarias+=1;let n,r=new Promise(a=>n=a);this.enVuelo.set(t,{promesa:r,resolver:n});let o=[],
111
- s=0,i=false;return {capturar:a=>{if(!i){if(s+=a.length,s>ve){i=true,o.length=0;return}o.push(a);}},terminar:(a,u)=>{let p=!i&&a>=200&&a<300;this.enVuelo.get(t)?.resolver(p?{status:a,headers:u,chunks:o}:null),
118
+ s=0,i=false;return {capturar:a=>{if(!i){if(s+=a.length,s>ye){i=true,o.length=0;return}o.push(a);}},terminar:(a,u)=>{let p=!i&&a>=200&&a<300;this.enVuelo.get(t)?.resolver(p?{status:a,headers:u,chunks:o}:null),
112
119
  this.enVuelo.delete(t);},abortar:()=>{this.enVuelo.get(t)?.resolver(null),this.enVuelo.delete(t);}}}async esperar(t){let n=this.enVuelo.get(t);if(!n)return null;let r=await n.promesa;return r&&(this.gemelas+=
113
- 1),r}tieneEnVuelo(t){return this.enVuelo.has(t)}};var rn=["content-encoding","content-length","transfer-encoding"];async function st(e={}){let t=(e.upstream??"https://api.anthropic.com").replace(/\/+$/,""),n=e.fetchImpl??fetch,r=e.log??(c=>console.log(
114
- c)),o;if(e.serviceAccountKey){o=new z({url:e.meteringUrl??"https://savings.bivelio.com/api/metering/usage",serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},onAuthError:d=>E(
120
+ 1),r}tieneEnVuelo(t){return this.enVuelo.has(t)}};var ln=["content-encoding","content-length","transfer-encoding"];async function at(e={}){let t=(e.upstream??"https://api.anthropic.com").replace(/\/+$/,""),n=e.fetchImpl??fetch,r=e.log??(c=>console.log(
121
+ c)),o;if(e.serviceAccountKey){o=new z({url:e.meteringUrl??"https://savings.bivelio.com/api/metering/usage",serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},onAuthError:d=>C(
115
122
  "gateway-ingest-auth",`[bvsala gateway] la ingesta de uso rechaza la credencial (${d}). El tr\xE1fico sigue fluyendo (avisar, nunca romper), pero este uso no est\xE1 llegando al panel. Revisa BIVELIO_SERVIC\
116
- E_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let c=Z();e.seatId?o.setSeat(e.seatId,c):ee(e.serviceAccountKey).then(d=>o?.setSeat(d,c)).catch(()=>{}),o.start();}else E("gateway-sin\
117
- -clave","[bvsala gateway] sin BIVELIO_SERVICE_KEY: el gateway reenv\xEDa el tr\xE1fico pero NO mide. Consigue tu clave en savings.bivelio.com/dashboard/install para ver el gasto en tu panel.");let s=e.
118
- coalescer?new se:null,i=e.sombra&&o?new ne:null,a=e.elision&&e.serviceAccountKey?new oe({url:new URL("/api/org/entitlements",e.meteringUrl??"https://savings.bivelio.com/api/metering/usage").toString(),
119
- serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},log:r}):null,u=c=>c==="/v1/messages"?new $:c.endsWith("/responses")?new te:null,p=(c,d,h,b,v,f,y,R)=>{if(!o||!h)return;let W=o,
120
- V=h,S=Ve(d,f);if(!S){E(`gateway-sin-modelo:${v}`,`[bvsala gateway] no se pudo leer el modelo del cuerpo de ${v} (content-encoding: ${f??"ninguno"}); su uso se reenv\xEDa pero no se mide.`);return}let T=Ue(
121
- S,h);T?(o.record(b?Ke(c,S,T,y):qe(c,S,T,y,R)),r(`[gateway] POST ${v} ${b?"\xB7 COALESCIDA (llamada evitada)":""} \xB7 ${S} \xB7 $${T.costeUsd.toFixed(6)} (in ${T.tokens.entrada}, cache\u2191${T.tokens.
123
+ E_KEY y el estado de la suscripci\xF3n en savings.bivelio.com.`)});let c=ee();e.seatId?o.setSeat(e.seatId,c):te(e.serviceAccountKey).then(d=>o?.setSeat(d,c)).catch(()=>{}),o.start();}else C("gateway-si\
124
+ n-clave","[bvsala gateway] sin BIVELIO_SERVICE_KEY: el gateway reenv\xEDa el tr\xE1fico pero NO mide. Consigue tu clave en savings.bivelio.com/dashboard/install para ver el gasto en tu panel.");let s=e.
125
+ coalescer?new se:null,i=e.sombra&&o?new oe:null,a=e.elision!==false&&e.serviceAccountKey?new re({url:new URL("/api/org/entitlements",e.meteringUrl??"https://savings.bivelio.com/api/metering/usage").toString(),
126
+ serviceAccountKey:e.serviceAccountKey,...e.fetchImpl?{fetchImpl:e.fetchImpl}:{},log:r}):null,u=c=>c==="/v1/messages"?new $:c.endsWith("/responses")?new ne:null,p=(c,d,h,b,v,f,y,R)=>{if(!o||!h)return;let W=o,
127
+ V=h,S=Je(d,f);if(!S){C(`gateway-sin-modelo:${v}`,`[bvsala gateway] no se pudo leer el modelo del cuerpo de ${v} (content-encoding: ${f??"ninguno"}); su uso se reenv\xEDa pero no se mide.`);return}let T=He(
128
+ S,h);T?(o.record(b?Ye(c,S,T,y):Ge(c,S,T,y,R)),r(`[gateway] POST ${v} ${b?"\xB7 COALESCIDA (llamada evitada)":""} \xB7 ${S} \xB7 $${T.costeUsd.toFixed(6)} (in ${T.tokens.entrada}, cache\u2191${T.tokens.
122
129
  cacheEscrita}${T.tokens.cacheEscrita1h?` (1h ${T.tokens.cacheEscrita1h})`:""} cache\u2193${T.tokens.cacheLeida}, out ${T.tokens.salida})`+(R?` \xB7 elisi\xF3n: ${R.borrados} borrado(s), ${R.tokensLimpiados}\
123
- tok limpiados por el proveedor`:"")),i&&!b&&v==="/v1/messages"&&setImmediate(()=>{try{let L=he(d,f);if(!L||typeof L!="object")return;let _=i.observar({cuerpo:L,uso:V,model:S,at:Date.now(),...y?.sessionId!==
124
- void 0?{sessionId:y.sessionId}:{},...y?.agentId!==void 0?{agentId:y.agentId}:{}});if(!_)return;W.record(He(`${c}:shadow`,S,_.baselineUsd,_.politicaUsd,y)),r(`[gateway] sombra \xB7 ${S} \xB7 baseline $${_.
125
- baselineUsd.toFixed(6)} \u2192 v0 $${_.politicaUsd.toFixed(6)}`);}catch{}})):E(`gateway-sin-precio:${S}`,`[bvsala gateway] el modelo "${S}" no est\xE1 en el cat\xE1logo de precios; su uso se reenv\xEDa pero no \
130
+ tok limpiados por el proveedor`:"")),i&&!b&&v==="/v1/messages"&&setImmediate(()=>{try{let L=ge(d,f);if(!L||typeof L!="object")return;let _=i.observar({cuerpo:L,uso:V,model:S,at:Date.now(),...y?.sessionId!==
131
+ void 0?{sessionId:y.sessionId}:{},...y?.agentId!==void 0?{agentId:y.agentId}:{}});if(!_)return;W.record(Qe(`${c}:shadow`,S,_.baselineUsd,_.politicaUsd,y)),r(`[gateway] sombra \xB7 ${S} \xB7 baseline $${_.
132
+ baselineUsd.toFixed(6)} \u2192 v0 $${_.politicaUsd.toFixed(6)}`);}catch{}})):C(`gateway-sin-precio:${S}`,`[bvsala gateway] el modelo "${S}" no est\xE1 en el cat\xE1logo de precios; su uso se reenv\xEDa pero no \
126
133
  se mide.`);},m=createServer(async(c,d)=>{let h=randomUUID(),b=new AbortController;d.on("close",()=>{d.writableEnded||b.abort();});let v=null,f=new URL(c.url??"/",t),y=null,R=Buffer.alloc(0),W=false,V=c.headers["content-enco\
127
134
  ding"],S=Array.isArray(V)?V[0]:V,T=I=>{let w=Array.isArray(I)?I[0]:I;return w!==void 0&&/^[A-Za-z0-9._:/-]{1,128}$/.test(w)?w:void 0},L=T(c.headers["x-claude-code-session-id"]),_=T(c.headers["x-claude\
128
135
  -code-agent-id"]),G=L!==void 0||_!==void 0?{...L!==void 0?{sessionId:L}:{},..._!==void 0?{agentId:_}:{}}:void 0;try{let I=[];for await(let g of c)I.push(g);let w=Buffer.concat(I);R=w,f=new URL(c.url??
129
- "/",t);let Y=s!==null&&c.method==="POST"&&w.length>0,Ct=rt(g=>{let x=c.headers[g];return Array.isArray(x)?x.join(", "):x}),le=Y?ot("POST",f.pathname+f.search,w,Ct):"";if(Y)if(s.tieneEnVuelo(le)){let g=await s.
130
- esperar(le);if(g){d.writeHead(g.status,g.headers);let x=u(f.pathname)??new $;for(let Me of g.chunks)d.write(Me),x.observar(Me);d.end();let Et=x.usage()??(f.pathname==="/v1/messages"?be(Buffer.concat(g.
131
- chunks)):null);p(h,w,Et,!0,f.pathname,S,G);return}}else v=s.registrar(le);let Q={};for(let[g,x]of Object.entries(c.headers))g==="host"||g==="content-length"||x===void 0||(Q[g]=Array.isArray(x)?x.join(
132
- ", "):x);let Oe=w;if(a!==null&&c.method==="POST"&&f.pathname==="/v1/messages"&&a.tiene("context_elision"))try{let g=tt(w,S);g!==null&&(Oe=g,Q["anthropic-beta"]=nt(Q["anthropic-beta"]));}catch{}let C;try{
133
- C=await n(f,{method:c.method,headers:Q,body:["GET","HEAD"].includes(c.method??"")?void 0:Oe,redirect:"manual",signal:b.signal});}catch(g){v?.abortar(),d.headersSent||(d.writeHead(502,{"content-type":"a\
134
- pplication/json"}),d.end(JSON.stringify({error:"bvsala gateway: upstream unreachable",detail:String(g)}))),r(`[gateway] ${c.method} ${f.pathname} \u2192 upstream inalcanzable: ${String(g)}`);return}let ue=Object.
135
- fromEntries(C.headers.entries());for(let g of rn)delete ue[g];d.writeHead(C.status,ue);let De=C.headers.get("content-type")??"",de=De.includes("text/event-stream")||De===""&&C.ok&&u(f.pathname)!==null;
136
- y=de?u(f.pathname):null;let F=!de&&C.ok&&o!==void 0&&c.method==="POST"&&f.pathname==="/v1/messages"&&(C.headers.get("content-type")??"").includes("application/json")?[]:null,Le=0;if(C.body)for await(let g of C.
137
- body){let x=Buffer.from(g);d.write(x),y?.observar(x),F&&(Le+=x.length,Le>ve?F=null:F.push(x)),v?.capturar(x);}if(d.end(),v?.terminar(C.status,ue),y&&C.ok){W=!0;let g=y instanceof $?y.elision():null;p(h,
138
- w,y.usage(),!1,f.pathname,S,G,g);}else if(F){let g=Buffer.concat(F);p(h,w,be(g),!1,f.pathname,S,G,Be(g));}else de||r(`[gateway] ${c.method} ${f.pathname} \u2192 ${C.status}`);}catch(I){if(v?.abortar(),b.
136
+ "/",t);let Y=s!==null&&c.method==="POST"&&w.length>0,Rt=it(g=>{let x=c.headers[g];return Array.isArray(x)?x.join(", "):x}),ue=Y?st("POST",f.pathname+f.search,w,Rt):"";if(Y)if(s.tieneEnVuelo(ue)){let g=await s.
137
+ esperar(ue);if(g){d.writeHead(g.status,g.headers);let x=u(f.pathname)??new $;for(let Me of g.chunks)d.write(Me),x.observar(Me);d.end();let _t=x.usage()??(f.pathname==="/v1/messages"?ve(Buffer.concat(g.
138
+ chunks)):null);p(h,w,_t,!0,f.pathname,S,G);return}}else v=s.registrar(ue);let Q={};for(let[g,x]of Object.entries(c.headers))g==="host"||g==="content-length"||x===void 0||(Q[g]=Array.isArray(x)?x.join(
139
+ ", "):x);let Oe=w;if(a!==null&&c.method==="POST"&&f.pathname==="/v1/messages"&&a.tiene("context_elision"))try{let g=je(w,S);g!==null&&(Oe=g,Q["anthropic-beta"]=Be(Q["anthropic-beta"]));}catch{}let E;try{
140
+ E=await n(f,{method:c.method,headers:Q,body:["GET","HEAD"].includes(c.method??"")?void 0:Oe,redirect:"manual",signal:b.signal});}catch(g){v?.abortar(),d.headersSent||(d.writeHead(502,{"content-type":"a\
141
+ pplication/json"}),d.end(JSON.stringify({error:"bvsala gateway: upstream unreachable",detail:String(g)}))),r(`[gateway] ${c.method} ${f.pathname} \u2192 upstream inalcanzable: ${String(g)}`);return}let de=Object.
142
+ fromEntries(E.headers.entries());for(let g of ln)delete de[g];d.writeHead(E.status,de);let De=E.headers.get("content-type")??"",pe=De.includes("text/event-stream")||De===""&&E.ok&&u(f.pathname)!==null;
143
+ y=pe?u(f.pathname):null;let F=!pe&&E.ok&&o!==void 0&&c.method==="POST"&&f.pathname==="/v1/messages"&&(E.headers.get("content-type")??"").includes("application/json")?[]:null,Le=0;if(E.body)for await(let g of E.
144
+ body){let x=Buffer.from(g);d.write(x),y?.observar(x),F&&(Le+=x.length,Le>ye?F=null:F.push(x)),v?.capturar(x);}if(d.end(),v?.terminar(E.status,de),y&&E.ok){W=!0;let g=y instanceof $?y.elision():null;p(h,
145
+ w,y.usage(),!1,f.pathname,S,G,g);}else if(F){let g=Buffer.concat(F);p(h,w,ve(g),!1,f.pathname,S,G,Ke(g));}else pe||r(`[gateway] ${c.method} ${f.pathname} \u2192 ${E.status}`);}catch(I){if(v?.abortar(),b.
139
146
  signal.aborted){let w=!W&&y?y.usageFinal():null;if(w){r(`[gateway] ${c.method} ${f.pathname} \u2192 el cliente cerr\xF3 tras el usage final; se mide igual`);let Y=y instanceof $?y.elision():null;p(h,R,
140
147
  w,false,f.pathname,S,G,Y);}else r(`[gateway] ${c.method} ${f.pathname} \u2192 el cliente abort\xF3; upstream cancelado`);}else if(r(`[gateway] ${c.method} ${f.pathname} \u2192 error sirviendo: ${String(I)}`),
141
148
  !d.headersSent){d.writeHead(502,{"content-type":"application/json"}),d.end(JSON.stringify({error:"bvsala gateway: stream interrupted",detail:String(I)}));return}d.writableEnded||d.end();}});return m.on(
@@ -144,17 +151,17 @@ d.end(`HTTP/1.1 426 Upgrade Required\r
144
151
  connection: close\r
145
152
  content-length: 0\r
146
153
  \r
147
- `);}),await new Promise((c,d)=>{m.once("error",d),m.listen(e.puerto??8402,"127.0.0.1",()=>c());}),{puerto:m.address().port,cerrar:async()=>{await o?.stopAndDrain(),await new Promise(c=>m.close(()=>c()));}}}var ye=["claude","codex","goose","qwen"];function at(e){return ye.includes(e??"")}function ct(e,t={}){let n=t.path??process.env.PATH??"",r=t.
154
+ `);}),await new Promise((c,d)=>{m.once("error",d),m.listen(e.puerto??8402,"127.0.0.1",()=>c());}),{puerto:m.address().port,cerrar:async()=>{await o?.stopAndDrain(),await new Promise(c=>m.close(()=>c()));}}}var ke=["claude","codex","goose","qwen"];function lt(e){return ke.includes(e??"")}function ut(e,t={}){let n=t.path??process.env.PATH??"",r=t.
148
155
  existe??existsSync,o=null;for(let s of n.split(";").filter(i=>i.length>0)){for(let i of [".exe",".com"]){let a=join(s,e+i);if(r(a))return {tipo:"exe",ruta:a}}if(o===null)for(let i of [".cmd",".bat"]){let a=join(s,e+
149
- i);if(r(a)){o=a;break}}}return o!==null?{tipo:"solo-shim",ruta:o}:{tipo:"no-encontrado"}}function lt(e={}){let n=(e.env??process.env).BVSALA_CODEX_AUTH?.toLowerCase();if(n==="api-key"||n==="apikey")return "\
156
+ i);if(r(a)){o=a;break}}}return o!==null?{tipo:"solo-shim",ruta:o}:{tipo:"no-encontrado"}}function dt(e={}){let n=(e.env??process.env).BVSALA_CODEX_AUTH?.toLowerCase();if(n==="api-key"||n==="apikey")return "\
150
157
  api-key";if(n==="chatgpt")return "chatgpt";let r=null;try{r=e.leerAuth?e.leerAuth():null;}catch{r=null;}if(r===null)return "api-key";try{let o=JSON.parse(r);return typeof o.auth_mode=="string"?o.auth_mode.
151
- toLowerCase().replace(/[^a-z]/g,"")==="apikey"?"api-key":"chatgpt":o.tokens!==void 0&&o.tokens!==null?"chatgpt":"api-key"}catch{return "api-key"}}var an={"api-key":{upstream:"https://api.openai.com",prefijo:"\
152
- /v1"},chatgpt:{upstream:"https://chatgpt.com",prefijo:"/backend-api/codex"}};function ke(e,t,n,r={}){let o=`http://127.0.0.1:${t}`;switch(e){case "claude":return {bin:"claude",args:n,env:{ANTHROPIC_BASE_URL:o}};case "\
158
+ toLowerCase().replace(/[^a-z]/g,"")==="apikey"?"api-key":"chatgpt":o.tokens!==void 0&&o.tokens!==null?"chatgpt":"api-key"}catch{return "api-key"}}var dn={"api-key":{upstream:"https://api.openai.com",prefijo:"\
159
+ /v1"},chatgpt:{upstream:"https://chatgpt.com",prefijo:"/backend-api/codex"}};function xe(e,t,n,r={}){let o=`http://127.0.0.1:${t}`;switch(e){case "claude":return {bin:"claude",args:n,env:{ANTHROPIC_BASE_URL:o}};case "\
153
160
  goose":return {bin:"goose",args:n,env:{ANTHROPIC_HOST:o}};case "qwen":return {bin:"qwen",args:n,env:{ANTHROPIC_BASE_URL:o},nota:'Qwen Code solo enruta por aqu\xED con `security.auth.selectedType: "anthropic\
154
- "` en ~/.qwen/settings.json (ver `bvsala doctor`).'};case "codex":{let s=r.modoCodex??"api-key",i=an[s];return {bin:"codex",args:["-c",`openai_base_url="${o}${i.prefijo}"`,...n],env:{},upstream:i.upstream,
161
+ "` en ~/.qwen/settings.json (ver `bvsala doctor`).'};case "codex":{let s=r.modoCodex??"api-key",i=dn[s];return {bin:"codex",args:["-c",`openai_base_url="${o}${i.prefijo}"`,...n],env:{},upstream:i.upstream,
155
162
  nota:s==="chatgpt"?"Auth ChatGPT detectada: el gateway enruta a chatgpt.com/backend-api/codex. El tr\xE1fico de suscripci\xF3n se mide (equivalente a precio de lista) pero no se monetiza: no hay factura por\
156
- tokens.":"Auth por API key: el gateway enruta a api.openai.com/v1."}}}}var dn="comprobar: en el log del gateway debe aparecer `[gateway] POST /v1/messages \u2026`; si ve\
157
- s `/v1/v1/messages`, sobra un /v1; si ves `POST /messages` a secas, falta uno.",pn=[{id:"claude",nombre:"Claude Code",binario:"claude",configs:[],detectable:true,receta:({base:e})=>["usa `bvsala claude`\
163
+ tokens.":"Auth por API key: el gateway enruta a api.openai.com/v1."}}}}var hn="comprobar: en el log del gateway debe aparecer `[gateway] POST /v1/messages \u2026`; si ve\
164
+ s `/v1/v1/messages`, sobra un /v1; si ves `POST /messages` a secas, falta uno.",gn=[{id:"claude",nombre:"Claude Code",binario:"claude",configs:[],detectable:true,receta:({base:e})=>["usa `bvsala claude`\
158
165
  \u2014 arranca el gateway en un puerto ef\xEDmero, lanza `claude` apunt\xE1ndole y lo apaga al salir.",`a mano: ANTHROPIC_BASE_URL=${e} claude (sin /v1: el cliente a\xF1ade /v1/messages)`]},{id:"co\
159
166
  dex",nombre:"Codex CLI",binario:"codex",configs:[join(".codex","config.toml"),join(".codex","auth.json")],detectable:true,receta:({base:e,rutas:t})=>["usa `bvsala codex` \u2014 el prefijo del base URL depende del \
160
167
  modo de auth y lo resuelve el envoltorio:",` API key \u2192 openai_base_url=${e}/v1`,` suscripci\xF3n ChatGPT \u2192 openai_base_url=${e}/backend-api/codex (tiene que terminar exactament\
@@ -170,40 +177,40 @@ Droid (Factory)",binario:"droid",configs:[join(".factory","settings.json")],dete
170
177
  idar en mano contra el log del gateway].`,"{",' "customModels": ['," {",' "model": "<id de modelo Anthropic>",',' "displayName": "<nombre visible>",',' "provider": "anthropic",',` \
171
178
  "baseUrl": "${e}",`,' "apiKey": "<tu API key de Anthropic>"'," }"," ]","}"]},{id:"cline",nombre:"Cline",configs:[],detectable:false,receta:({baseV1:e})=>["mecanismo: UI \u2192 proveedor Anthropic\
172
179
  \u2192 marca \xABUse custom base URL\xBB. CON /v1 (Cline fija https://api.anthropic.com/v1 y solo normaliza la URL oficial exacta).",`Base URL: ${e}`]},{id:"kilo",nombre:"Kilo Code",configs:[],detectable:false,
173
- receta:({baseV1:e})=>["mecanismo: UI \u2192 proveedor custom, Provider API \xABAnthropic Messages\xBB. Probar CON /v1 primero (linaje Cline) [inferido: validar en mano].",`Base URL: ${e}`]}];function mn(e,t){
174
- let n=e.split(delimiter).filter(o=>o.length>0),r=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return o=>n.some(s=>r.some(i=>t(join(s,o+i))))}async function ut(e,t={}){if(!Number.isInteger(e)||e<1||
175
- e>65535)throw new RangeError(`[bvsala doctor] puerto inv\xE1lido: ${String(e)}`);let n=t.home??homedir(),r=t.existe??existsSync,o=t.enPath??mn(t.path??process.env.PATH??"",r),s=`http://127.0.0.1:${e}`,i=`${s}/v1`,
180
+ receta:({baseV1:e})=>["mecanismo: UI \u2192 proveedor custom, Provider API \xABAnthropic Messages\xBB. Probar CON /v1 primero (linaje Cline) [inferido: validar en mano].",`Base URL: ${e}`]}];function bn(e,t){
181
+ let n=e.split(delimiter).filter(o=>o.length>0),r=process.platform==="win32"?["",".exe",".cmd",".bat"]:[""];return o=>n.some(s=>r.some(i=>t(join(s,o+i))))}async function pt(e,t={}){if(!Number.isInteger(e)||e<1||
182
+ e>65535)throw new RangeError(`[bvsala doctor] puerto inv\xE1lido: ${String(e)}`);let n=t.home??homedir(),r=t.existe??existsSync,o=t.enPath??bn(t.path??process.env.PATH??"",r),s=`http://127.0.0.1:${e}`,i=`${s}/v1`,
176
183
  a=[],u=[`bvsala doctor \u2014 gateway local en ${s}`,"Solo imprime: no escribe ninguna configuraci\xF3n. Detecci\xF3n por existencia (binarios en PATH y","archivos de configuraci\xF3n de usuario); nunca \
177
- se lee el contenido de ning\xFAn archivo.",""];for(let p of pn){let m=p.configs.map(b=>join(n,b)),l=p.binario!==void 0&&o(p.binario),c=m.filter(b=>r(b)),d=l||c.length>0;d&&a.push(p.id);let h;p.detectable?
184
+ se lee el contenido de ning\xFAn archivo.",""];for(let p of gn){let m=p.configs.map(b=>join(n,b)),l=p.binario!==void 0&&o(p.binario),c=m.filter(b=>r(b)),d=l||c.length>0;d&&a.push(p.id);let h;p.detectable?
178
185
  d?h=`detectado \u2014 ${[...l?[`binario \`${p.binario}\` en PATH`]:[],...c.map(v=>`config presente: ${v}`)].join("; ")}`:h="no detectado":h="sin detecci\xF3n autom\xE1tica (extensi\xF3n de editor)",u.
179
- push(`\xBB ${p.id}: ${h}`),u.push(` ${p.nombre}`);for(let b of p.receta({base:s,baseV1:i,rutas:m}))u.push(` ${b}`);u.push(` ${dn}`),u.push("");}return u.push("Regla BYOK: las recetas del anillo Anth\
186
+ push(`\xBB ${p.id}: ${h}`),u.push(` ${p.nombre}`);for(let b of p.receta({base:s,baseV1:i,rutas:m}))u.push(` ${b}`);u.push(` ${hn}`),u.push("");}return u.push("Regla BYOK: las recetas del anillo Anth\
180
187
  ropic (Goose, Qwen Code, opencode, Crush, Droid, Cline, Kilo) son","para API key. Nunca enrutes por el gateway el OAuth de una suscripci\xF3n Claude Pro/Max desde un harness","de terceros \u2014 Anthropic \
181
188
  lo proh\xEDbe. Claude Code y Codex con suscripci\xF3n se enrutan y se miden, pero no","se monetizan: no hay factura por tokens.","Detalle por terminal: docs/terminales/<terminal>.md"),{texto:u.join(`
182
- `),detectados:a}}var dt="savings-mode";function pt(e,t){for(let n of e){let r=join(n,"skills",dt,"SKILL.md");if(t.existe(r))return r}return null}var mt="<!-- bvsala:savings-mode:inicio -->",ie="\
183
- <!-- bvsala:savings-mode:fin -->";function fn(e){let t=e.replace(/^---\n[\s\S]*?\n---\n*/,"").trim();return `${mt}
189
+ `),detectados:a}}var mt="savings-mode";function ft(e,t){for(let n of e){let r=join(n,"skills",mt,"SKILL.md");if(t.existe(r))return r}return null}var ht="<!-- bvsala:savings-mode:inicio -->",ie="\
190
+ <!-- bvsala:savings-mode:fin -->";function vn(e){let t=e.replace(/^---\n[\s\S]*?\n---\n*/,"").trim();return `${ht}
184
191
  ${t}
185
192
 
186
193
  _Always on (AGENTS.md has no activation step). Delete this block to turn it off; \`bvsala skill --codex --forzar\` restores it._
187
- ${ie}`}function ft(e){let t=pt(e.origenes,e.fs);if(!t)return {ok:false,destino:"",mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${e.origenes.join(", ")})`};let n=fn(e.fs.
194
+ ${ie}`}function gt(e){let t=ft(e.origenes,e.fs);if(!t)return {ok:false,destino:"",mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${e.origenes.join(", ")})`};let n=vn(e.fs.
188
195
  leer(t)),r=e.proyecto?e.cwd:join(e.home,".codex"),o=join(r,"AGENTS.md");if(!e.fs.existe(o))return e.fs.crearDir(r),e.fs.escribir(o,n+`
189
- `),{ok:true,destino:o,mensaje:xe(o,"instalado")};let s=e.fs.leer(o),i=s.indexOf(mt),a=s.indexOf(ie);return i===-1||a===-1||a<i?(e.fs.escribir(o,s.trimEnd()+`
196
+ `),{ok:true,destino:o,mensaje:Se(o,"instalado")};let s=e.fs.leer(o),i=s.indexOf(ht),a=s.indexOf(ie);return i===-1||a===-1||a<i?(e.fs.escribir(o,s.trimEnd()+`
190
197
 
191
198
  `+n+`
192
- `),{ok:true,destino:o,mensaje:xe(o,"a\xF1adido al AGENTS.md existente")}):s.slice(i,a+ie.length)===n?{ok:true,destino:o,mensaje:`[bvsala skill] ya instalado y al d\xEDa: ${o}`}:e.forzar?(e.fs.escribir(o,s.
193
- slice(0,i)+n+s.slice(a+ie.length)),{ok:true,destino:o,mensaje:xe(o,"bloque actualizado")}):{ok:false,destino:o,mensaje:`[bvsala skill] el bloque savings-mode de ${o} tiene contenido DISTINTO \u2014 no lo piso; \
194
- usa --forzar para actualizarlo`}}function xe(e,t){return `[bvsala skill] ${t}: ${e}
199
+ `),{ok:true,destino:o,mensaje:Se(o,"a\xF1adido al AGENTS.md existente")}):s.slice(i,a+ie.length)===n?{ok:true,destino:o,mensaje:`[bvsala skill] ya instalado y al d\xEDa: ${o}`}:e.forzar?(e.fs.escribir(o,s.
200
+ slice(0,i)+n+s.slice(a+ie.length)),{ok:true,destino:o,mensaje:Se(o,"bloque actualizado")}):{ok:false,destino:o,mensaje:`[bvsala skill] el bloque savings-mode de ${o} tiene contenido DISTINTO \u2014 no lo piso; \
201
+ usa --forzar para actualizarlo`}}function Se(e,t){return `[bvsala skill] ${t}: ${e}
195
202
  [bvsala skill] AGENTS.md va SIEMPRE activo en Codex (no hay paso de activaci\xF3n); borra el bloque para apagarlo.
196
- [bvsala skill] para medir su efecto: trabaja unos d\xEDas con \xE9l y otros sin \xE9l bajo \`bvsala codex\`, y compara en el panel.`}function ht(e){let t=pt(e.origenes,e.fs);if(!t)return {ok:false,destino:"",
197
- mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${e.origenes.join(", ")})`};let n=e.proyecto?join(e.cwd,".claude","skills"):join(e.home,".claude","skills"),r=join(n,dt),o=join(r,
203
+ [bvsala skill] para medir su efecto: trabaja unos d\xEDas con \xE9l y otros sin \xE9l bajo \`bvsala codex\`, y compara en el panel.`}function bt(e){let t=ft(e.origenes,e.fs);if(!t)return {ok:false,destino:"",
204
+ mensaje:`[bvsala skill] no encuentro el SKILL.md empaquetado (ra\xEDces probadas: ${e.origenes.join(", ")})`};let n=e.proyecto?join(e.cwd,".claude","skills"):join(e.home,".claude","skills"),r=join(n,mt),o=join(r,
198
205
  "SKILL.md"),s=e.fs.leer(t);if(e.fs.existe(o)&&!e.forzar){let i=e.fs.leer(o)===s;return {ok:i,destino:o,mensaje:i?`[bvsala skill] ya instalado y al d\xEDa: ${o}`:`[bvsala skill] ya existe ${o} con conte\
199
206
  nido DISTINTO \u2014 no lo piso; usa --forzar para sobrescribir`}}return e.fs.crearDir(r),e.fs.escribir(o,s),{ok:true,destino:o,mensaje:`[bvsala skill] instalado: ${o}
200
207
  [bvsala skill] arranca (o reinicia) Claude Code y p\xEDdele \xABsavings mode\xBB \u2014 o deja que se active solo al hablar de l\xEDmites.
201
- [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 Se=class{id;exact=false;constructor(t="heuristic"){this.id=t;}count(t){if(t.length===0)return 0;let n=t.match(/[A-Za-z]+|\d+|\s+|[^\sA-Za-z\d]/g)??[],r=0;for(let o of n){let s=o[0];if(/\s/.test(s)){let i=(o.
208
+ [bvsala skill] para medir su efecto de verdad: trabaja unos d\xEDas con \xE9l y otros sin \xE9l bajo \`bvsala claude\`, y compara en el panel.`}}var we=class{id;exact=false;constructor(t="heuristic"){this.id=t;}count(t){if(t.length===0)return 0;let n=t.match(/[A-Za-z]+|\d+|\s+|[^\sA-Za-z\d]/g)??[],r=0;for(let o of n){let s=o[0];if(/\s/.test(s)){let i=(o.
202
209
  match(/\n/g)??[]).length;r+=i+Math.floor(Math.max(0,o.length-1)/2);}else /[A-Za-z]/.test(s)?r+=Math.max(1,Math.ceil(o.length/4)):/\d/.test(s)?r+=Math.max(1,Math.ceil(o.length/2)):r+=1;}return Math.max(r,
203
- Math.ceil(t.length/4))}},we=new Se;var Te=class{estimators=new Map;modelToTokenizer=new Map;fallbackId;constructor(t=we){this.fallbackId=t.id,this.estimators.set(t.id,t);}register(t){return this.estimators.set(t.id,t),this}mapModel(t,n){
210
+ Math.ceil(t.length/4))}},Te=new we;var Ee=class{estimators=new Map;modelToTokenizer=new Map;fallbackId;constructor(t=Te){this.fallbackId=t.id,this.estimators.set(t.id,t);}register(t){return this.estimators.set(t.id,t),this}mapModel(t,n){
204
211
  return this.modelToTokenizer.set(t,n),this}resolve(t){let n=t.tokenizer?this.estimators.get(t.tokenizer):void 0;if(n)return n;if(t.model){let r=this.modelToTokenizer.get(t.model);if(r){let o=this.estimators.
205
- get(r);if(o)return o}}return this.estimators.get(this.fallbackId)}count(t,n){return this.resolve(n).count(t)}};new Te;new TextEncoder;new TextDecoder;new TextDecoder;var An={"gpt-4o-mini":{deltaTokens:-16,salidaDelBrazoA:72,contrato:"triage (6 fields, long enums)",pares:8},"gpt-4o":{deltaTokens:3,salidaDelBrazoA:75,contrato:"triage (6 fields, long enums)",pares:8}};
206
- me(An);var _e="0.4.13";var[,,k,...O]=process.argv;function Nn(){console.log(`bvsala ${_e} \u2014 BiVelio Savings Layer
212
+ get(r);if(o)return o}}return this.estimators.get(this.fallbackId)}count(t,n){return this.resolve(n).count(t)}};new Ee;new TextEncoder;new TextDecoder;new TextDecoder;var Ln={"gpt-4o-mini":{deltaTokens:-16,salidaDelBrazoA:72,contrato:"triage (6 fields, long enums)",pares:8},"gpt-4o":{deltaTokens:3,salidaDelBrazoA:75,contrato:"triage (6 fields, long enums)",pares:8}};
213
+ fe(Ln);var Ie="0.4.15";var[,,k,...O]=process.argv;function Un(){console.log(`bvsala ${Ie} \u2014 BiVelio Savings Layer
207
214
 
208
215
  Comandos:
209
216
  gateway [--puerto N] Proxy local medidor (por defecto 8402) para terminales que
@@ -231,34 +238,36 @@ Entorno:
231
238
  BVSALA_GATEWAY_SHADOW =1 enciende el carril sombra de la elisi\xF3n (S2): calcula qu\xE9
232
239
  habr\xEDa ahorrado la pol\xEDtica v0 SIN tocar el tr\xE1fico y lo
233
240
  reporta aparte (jam\xE1s entra en la comisi\xF3n).
234
- BVSALA_GATEWAY_ELISION =1 arma la palanca de diales del proveedor (S4a). Solo se
235
- enciende de verdad si adem\xE1s la licencia de tu organizaci\xF3n
236
- trae el feature context_elision (consulta fail-closed): ajusta
237
- SOLO el bloque context_management de cada petici\xF3n /v1/messages
238
- y el borrado lo hace el propio proveedor. Ante cualquier duda,
239
- la petici\xF3n viaja intacta.
241
+ BVSALA_GATEWAY_ELISION =0 APAGA la palanca de diales del proveedor (S4a), que va
242
+ armada por defecto. Solo se enciende de verdad si la licencia
243
+ de tu organizaci\xF3n trae el feature context_elision (consulta
244
+ fail-closed): ajusta SOLO el bloque context_management de cada
245
+ petici\xF3n /v1/messages y el borrado lo hace el propio proveedor.
246
+ Ante cualquier duda, la petici\xF3n viaja intacta. (Hasta 0.4.13
247
+ la bandera era al rev\xE9s: \xAB=1 arma\xBB; en un A/B p\xE1sala SIEMPRE
248
+ expl\xEDcita, =1 o =0, y no depender\xE1s de la versi\xF3n instalada.)
240
249
  BVSALA_CODEX_AUTH api-key | chatgpt \u2014 fuerza el modo de auth de Codex.
241
250
  BVSALA_GATEWAY_LOG =1 ense\xF1a el log por petici\xF3n tambi\xE9n dentro de los envoltorios
242
251
  (por defecto va silenciado para no pisar el TUI; mira el panel).
243
252
  CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 (Claude Code, solo API key) tus modelos en /model.
244
253
 
245
254
  El gateway nunca corta el tr\xE1fico: sin clave o con la ingesta ca\xEDda, reenv\xEDa y avisa.
246
- Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}var J=at(k);k!=="gateway"&&k!=="doctor"&&k!=="skill"&&!J&&(Nn(),process.exit(k===void 0||k==="hel\
255
+ Tus prompts jam\xE1s salen de tu m\xE1quina \u2014 solo cuentas y coste. M\xE1s: savings.bivelio.com`);}var J=lt(k);k!=="gateway"&&k!=="doctor"&&k!=="skill"&&!J&&(Un(),process.exit(k===void 0||k==="hel\
247
256
  p"||k==="--help"?0:1));if(k==="skill"){let e=dirname(fileURLToPath(import.meta.url)),t={origenes:[join(e,"..",".."),join(e,"..")],home:homedir(),cwd:process.cwd(),proyecto:O.includes("--proyecto"),forzar:O.includes("--forzar"),
248
- fs:{existe:existsSync,leer:r=>readFileSync(r,"utf8"),escribir:(r,o)=>writeFileSync(r,o),crearDir:r=>mkdirSync(r,{recursive:true})}},n=O.includes("--codex")?ft(t):ht(t);console.log(n.mensaje),process.exit(n.ok?0:1);}var Ae=O.indexOf("--puer\
249
- to"),U=J?0:Ae>=0?Number(O[Ae+1]):8402;(!Number.isInteger(U)||(k==="doctor"?U<1:U<0)||U>65535)&&(console.error(`[bvsala ${k}] puerto inv\xE1lido: ${O[Ae+1]}`),process.exit(1));if(k==="doctor"){O.includes(
250
- "--write")&&(console.error("[bvsala doctor] --write todav\xEDa no existe: el doctor solo imprime; copia el bloque a mano."),process.exit(1));let e=await ut(U);console.log(e.texto),process.exit(0);}var D=J?
251
- ke(k,0,O,{modoCodex:k==="codex"?lt({leerAuth:()=>readFileSync(join(homedir(),".codex","auth.json"),"utf8")}):void 0}):null,Pe=process.env.BIVELIO_SERVICE_KEY,jn=J&&process.env.BVSALA_GATEWAY_LOG!=="1",j=await st({puerto:U,
252
- ...jn?{log:()=>{}}:{},...Pe?{serviceAccountKey:Pe}:{},...process.env.BVSALA_SEAT_ID?{seatId:process.env.BVSALA_SEAT_ID}:{},...process.env.BVSALA_GATEWAY_UPSTREAM?{upstream:process.env.BVSALA_GATEWAY_UPSTREAM}:
253
- D?.upstream?{upstream:D.upstream}:{},...process.env.BVSALA_GATEWAY_COALESCE==="1"?{coalescer:true}:{},...process.env.BVSALA_GATEWAY_SHADOW==="1"?{sombra:true}:{},...process.env.BVSALA_GATEWAY_ELISION==="1"?
254
- {elision:true}:{},...process.env.BVSALA_METERING_URL?{meteringUrl:process.env.BVSALA_METERING_URL}:{}}),zn=process.env.BVSALA_GATEWAY_UPSTREAM??D?.upstream??"https://api.anthropic.com";console.log(`[bvs\
255
- ala gateway] v${_e} escuchando en http://127.0.0.1:${j.puerto} \u2192 ${zn}`);console.log(`[bvsala gateway] medici\xF3n: ${Pe?"ACTIVA (clave de servicio presente)":"APAGADA (falta BIVELIO_SERVICE_KEY)"}`);
256
- process.env.BVSALA_GATEWAY_UPSTREAM&&D?.upstream&&process.env.BVSALA_GATEWAY_UPSTREAM!==D.upstream&&console.error(`[bvsala ${k}] AVISO: BVSALA_GATEWAY_UPSTREAM=${process.env.BVSALA_GATEWAY_UPSTREAM} p\
257
- isa el upstream de este terminal (${D.upstream}). Si no es lo que quieres, quita la variable.`);k==="codex"&&!Fe()&&console.error(`[bvsala codex] AVISO: este Node (${process.version}) no descomprime z\
258
- std y Codex manda el cuerpo en zstd: el tr\xE1fico pasa pero NO se mide. Usa Node \u2265 22.15.`);if(D&&J){let e=ke(k,j.puerto,O,{...D.upstream?{modoCodex:D.upstream.includes("chatgpt.com")?"chatgpt":
259
- "api-key"}:{}});e.nota&&console.log(`[bvsala ${k}] ${e.nota}`);let t=e.bin;if(process.platform==="win32"){let r=ct(e.bin);r.tipo==="exe"?t=r.ruta:r.tipo==="solo-shim"&&(console.error(`[bvsala ${k}] \`${e.
260
- bin}\` est\xE1 instalado como shim de npm (${r.ruta}) y Windows no puede lanzarlo de forma segura con argumentos (CVE-2024-27980). Inst\xE1lalo con su instalador nativo (deja un ${e.bin}.exe en el PAT\
261
- H) o usa la receta manual de docs/terminales/.`),await j.cerrar(),process.exit(127));}let n=spawn(t,e.args,{stdio:"inherit",env:{...process.env,...e.env}});n.on("error",r=>{console.error(`[bvsala ${k}] no\
262
- se pudo lanzar \`${e.bin}\`: ${String(r)}. \xBFEst\xE1 instalado y en el PATH?`),j.cerrar().then(()=>process.exit(127));}),n.on("exit",(r,o)=>{j.cerrar().then(()=>process.exit(r??(o?1:0)));});}else console.
263
- log(`[bvsala gateway] apunta tu terminal (o usa \`bvsala ${ye.join("|")}\`): ANTHROPIC_BASE_URL=http://127.0.0.1:${j.puerto} claude \xB7 bvsala doctor para el resto`);var Tt=async()=>{await j.cerrar(),
264
- process.exit(0);};process.on("SIGINT",()=>{Tt();});process.on("SIGTERM",()=>{Tt();});
257
+ fs:{existe:existsSync,leer:r=>readFileSync(r,"utf8"),escribir:(r,o)=>writeFileSync(r,o),crearDir:r=>mkdirSync(r,{recursive:true})}},n=O.includes("--codex")?gt(t):bt(t);console.log(n.mensaje),process.exit(n.ok?0:1);}var Pe=O.indexOf("--puer\
258
+ to"),U=J?0:Pe>=0?Number(O[Pe+1]):8402;(!Number.isInteger(U)||(k==="doctor"?U<1:U<0)||U>65535)&&(console.error(`[bvsala ${k}] puerto inv\xE1lido: ${O[Pe+1]}`),process.exit(1));if(k==="doctor"){O.includes(
259
+ "--write")&&(console.error("[bvsala doctor] --write todav\xEDa no existe: el doctor solo imprime; copia el bloque a mano."),process.exit(1));let e=await pt(U);console.log(e.texto),process.exit(0);}var D=J?
260
+ xe(k,0,O,{modoCodex:k==="codex"?dt({leerAuth:()=>readFileSync(join(homedir(),".codex","auth.json"),"utf8")}):void 0}):null,le=process.env.BIVELIO_SERVICE_KEY,Vn=J&&process.env.BVSALA_GATEWAY_LOG!=="1",j=await at({puerto:U,
261
+ ...Vn?{log:()=>{}}:{},...le?{serviceAccountKey:le}:{},...process.env.BVSALA_SEAT_ID?{seatId:process.env.BVSALA_SEAT_ID}:{},...process.env.BVSALA_GATEWAY_UPSTREAM?{upstream:process.env.BVSALA_GATEWAY_UPSTREAM}:
262
+ D?.upstream?{upstream:D.upstream}:{},...process.env.BVSALA_GATEWAY_COALESCE==="1"?{coalescer:true}:{},...process.env.BVSALA_GATEWAY_SHADOW==="1"?{sombra:true}:{},elision:process.env.BVSALA_GATEWAY_ELISION!==
263
+ "0",...process.env.BVSALA_METERING_URL?{meteringUrl:process.env.BVSALA_METERING_URL}:{}}),Fn=process.env.BVSALA_GATEWAY_UPSTREAM??D?.upstream??"https://api.anthropic.com";console.log(`[bvsala gateway]\
264
+ v${Ie} escuchando en http://127.0.0.1:${j.puerto} \u2192 ${Fn}`);console.log(`[bvsala gateway] medici\xF3n: ${le?"ACTIVA (clave de servicio presente)":"APAGADA (falta BIVELIO_SERVICE_KEY)"}`);{let e=ze(
265
+ process.env.BVSALA_GATEWAY_ELISION,le!==void 0);(e.aviso?console.error:console.log)(`[bvsala gateway] ${e.linea}`);}process.env.BVSALA_GATEWAY_UPSTREAM&&D?.upstream&&process.env.BVSALA_GATEWAY_UPSTREAM!==
266
+ D.upstream&&console.error(`[bvsala ${k}] AVISO: BVSALA_GATEWAY_UPSTREAM=${process.env.BVSALA_GATEWAY_UPSTREAM} pisa el upstream de este terminal (${D.upstream}). Si no es lo que quieres, quita la vari\
267
+ able.`);k==="codex"&&!We()&&console.error(`[bvsala codex] AVISO: este Node (${process.version}) no descomprime zstd y Codex manda el cuerpo en zstd: el tr\xE1fico pasa pero NO se mide. Usa Node \u2265 22.15.`);
268
+ if(D&&J){let e=xe(k,j.puerto,O,{...D.upstream?{modoCodex:D.upstream.includes("chatgpt.com")?"chatgpt":"api-key"}:{}});e.nota&&console.log(`[bvsala ${k}] ${e.nota}`);let t=e.bin;if(process.platform==="\
269
+ win32"){let r=ut(e.bin);r.tipo==="exe"?t=r.ruta:r.tipo==="solo-shim"&&(console.error(`[bvsala ${k}] \`${e.bin}\` est\xE1 instalado como shim de npm (${r.ruta}) y Windows no puede lanzarlo de forma seg\
270
+ ura con argumentos (CVE-2024-27980). Inst\xE1lalo con su instalador nativo (deja un ${e.bin}.exe en el PATH) o usa la receta manual de docs/terminales/.`),await j.cerrar(),process.exit(127));}let n=spawn(
271
+ t,e.args,{stdio:"inherit",env:{...process.env,...e.env}});n.on("error",r=>{console.error(`[bvsala ${k}] no se pudo lanzar \`${e.bin}\`: ${String(r)}. \xBFEst\xE1 instalado y en el PATH?`),j.cerrar().then(
272
+ ()=>process.exit(127));}),n.on("exit",(r,o)=>{j.cerrar().then(()=>process.exit(r??(o?1:0)));});}else console.log(`[bvsala gateway] apunta tu terminal (o usa \`bvsala ${ke.join("|")}\`): ANTHROPIC_BASE_UR\
273
+ L=http://127.0.0.1:${j.puerto} claude \xB7 bvsala doctor para el resto`);var Ct=async()=>{await j.cerrar(),process.exit(0);};process.on("SIGINT",()=>{Ct();});process.on("SIGTERM",()=>{Ct();});