@bivelio/savings-layer 0.4.36 → 0.5.0
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 +14 -5
- package/dist/adapters/ai-sdk.js +87 -78
- package/dist/adapters/anthropic-sdk.d.ts +13 -0
- package/dist/adapters/anthropic-sdk.js +115 -102
- package/dist/adapters/langchain.js +67 -58
- package/dist/adapters/mastra.js +80 -71
- package/dist/gateway/bin.js +749 -754
- package/dist/index.d.ts +86 -1253
- package/dist/index.js +1441 -1447
- package/docs/terminales/README.md +2 -2
- package/docs/terminales/codex.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -121,9 +121,10 @@ bvsala gateway # Anthropic, the default, on 8402
|
|
|
121
121
|
|
|
122
122
|
Flags and environment variables are in English (`--port`, `--project`, `--force`,
|
|
123
123
|
`BVSALA_GATEWAY_EFFORT`, `BVSALA_GATEWAY_SIBLING_MODEL`). The Spanish spellings from
|
|
124
|
-
|
|
125
|
-
`BVSALA_GATEWAY_MODELO_HERMANO`)
|
|
126
|
-
|
|
124
|
+
0.4.x (`--puerto`, `--proyecto`, `--forzar`, `BVSALA_GATEWAY_ESFUERZO`,
|
|
125
|
+
`BVSALA_GATEWAY_MODELO_HERMANO`) were removed in 0.5: using one is an error that
|
|
126
|
+
names the English spelling, and the gateway does not start. `bvsala --help` lists
|
|
127
|
+
them all.
|
|
127
128
|
|
|
128
129
|
```python
|
|
129
130
|
from openai import OpenAI
|
|
@@ -169,6 +170,9 @@ and the free **Measure** license, which runs the layer in shadow mode on your ow
|
|
|
169
170
|
traffic and shows what it would have saved, valued with your provider's counter. The verifier that replays the optimizer on your own data
|
|
170
171
|
lives in your dashboard once you sign in.
|
|
171
172
|
|
|
173
|
+
**Upgrading from 0.4?** Every breaking change of 0.5, with a before and after for
|
|
174
|
+
each, is in [Migrating from 0.4 to 0.5](https://savings.bivelio.com/en/migrate-to-0.5).
|
|
175
|
+
|
|
172
176
|
## Set it up in one command
|
|
173
177
|
|
|
174
178
|
```bash
|
|
@@ -560,7 +564,7 @@ report.nativeSavings;
|
|
|
560
564
|
```
|
|
561
565
|
|
|
562
566
|
It is present only when a call ran and the provider reported cache reads or writes;
|
|
563
|
-
a cache hit or a coalesced request never carries it. It is not in `cost.
|
|
567
|
+
a cache hit or a coalesced request never carries it. It is not in `cost.netSavingsRatio`,
|
|
564
568
|
not in `cost.baselineEstimate`, and never in the commission base. Your dashboard shows
|
|
565
569
|
it as its own card, **Native savings unlocked**, next to the credited savings.
|
|
566
570
|
|
|
@@ -913,7 +917,7 @@ Ask for a response contract and you also get `data`, validated against your sche
|
|
|
913
917
|
```ts
|
|
914
918
|
const { data, text } = await layer.generate<{ answer: number }>({
|
|
915
919
|
model: "openai/gpt-4o-mini",
|
|
916
|
-
messages: [{ role: "user", content: "
|
|
920
|
+
messages: [{ role: "user", content: "How many legs does a spider have?" }],
|
|
917
921
|
response: {
|
|
918
922
|
contractId: "answer:v1",
|
|
919
923
|
schema: {
|
|
@@ -929,6 +933,11 @@ const { data, text } = await layer.generate<{ answer: number }>({
|
|
|
929
933
|
console.log(data.answer); // 8
|
|
930
934
|
```
|
|
931
935
|
|
|
936
|
+
A question the layer answers on its own (the arithmetic of the first example)
|
|
937
|
+
never reaches the model, so its `data` is the resolver's `{ value: 8 }`, not
|
|
938
|
+
your schema's shape: `report.qualityLedger` says the contract was not met.
|
|
939
|
+
Ask the model for anything you want in your contract's shape.
|
|
940
|
+
|
|
932
941
|
</details>
|
|
933
942
|
|
|
934
943
|
<details>
|
package/dist/adapters/ai-sdk.js
CHANGED
|
@@ -1,84 +1,93 @@
|
|
|
1
|
-
import {createSavingsLayer,LicenseError
|
|
2
|
-
nothing more was sent.",
|
|
3
|
-
completada:false,...{}}}async function
|
|
4
|
-
t)===
|
|
5
|
-
function
|
|
6
|
-
async generate(a,
|
|
7
|
-
text",delta:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
let u=n.run(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import {createSavingsLayer,LicenseError}from'@bivelio/savings-layer';import {AsyncLocalStorage}from'async_hooks';var _=new Set;function F(t,e,n){t===true||_.has(e)||(_.add(e),console.warn(n));}var V=Symbol.for("@bivelio/savings-layer:provider-origin");var me="[bvsala] internal: the layer changed a request this adapter must forward unchanged; nothing was sent.",ve="[bvsala] internal: the layer asked for a second model call within one framework call;\
|
|
2
|
+
nothing more was sent.",ye="[bvsala] internal: the layer called the model outside a framework call; nothing was sent.";function j(t,e,n,r){return {renderizado:t,generar:e,...n?{transmitir:n}:{},invocada:false,
|
|
3
|
+
completada:false,...{}}}async function P(t,e){try{let n=await e();return t.completada=!0,n}catch(n){throw t.errorDelMarco={error:n},n}}function he(t,e){if(t===e)return true;try{return W(
|
|
4
|
+
t)===W(e)}catch{return false}}function J(t,e){let n=t??[],r=e??[];return n.length===r.length&&n.every((a,s)=>he(a,r[s]))}function xe(t,e){return t.model===e.model&&J(t.messages,e.messages)&&J(t.tools,e.tools)}
|
|
5
|
+
function B(t,e){let n=a=>{let s=e.getStore();if(!s)throw new Error(ye);if(s.invocada)throw new Error(ve);if(!xe(a,s.renderizado))throw new Error(me);return s.invocada=true,s},r={id:`bivelio-adapter:${t}`,
|
|
6
|
+
async generate(a,s){return n(a).generar(s?.signal)},async*generateStream(a,s){let o=n(a);if(o.transmitir){yield*o.transmitir(s?.signal);return}let i=await o.generar(s?.signal);i.text!==""&&(yield {type:"\
|
|
7
|
+
text",delta:i.text}),yield {type:"done",response:i};}};return Object.defineProperty(r,V,{value:()=>e.getStore()?.origen}),r}function K(){return new AsyncLocalStorage}function W(t){return JSON.stringify(E(t))}function E(t){
|
|
8
|
+
if(Array.isArray(t))return t.map(E);if(t&&typeof t=="object"){let e={};for(let n of Object.keys(t).sort())e[n]=E(t[n]);return e}return t}var we=["licenseKey","licenseServerUrl","serviceAccountKey","licenseRefresh","licenseRevocation","licensePollIntervalSeconds","licenseFetch","metering","meteringUrl","meteringFetch","costModels","defa\
|
|
9
|
+
ultCostModel","exactCache","exactCacheTtlMs","resolvers","exactTokenizer","silenceWarnings","failOpen"];function H(t,e){return e instanceof LicenseError||t.errorDelMarco&&t.errorDelMarco.error===e?false:t.invocada&&
|
|
10
|
+
t.completada}var Z="[bvsala] the model answered, but the savings layer failed while accounting for it; the answer is returned unchanged, without a savings report and without a usage record.";function Q(t,e){
|
|
11
|
+
let n=K(),r={};for(let o of we)e[o]!==void 0&&(r[o]=e[o]);let a=createSavingsLayer({...r,provider:B(t,n)}),s=(o,i)=>F(e.silenceWarnings,`${t}:${o}`,i);return {ejecutar(o,i){return n.run(i,()=>a.generate(o))},async generar(o,i){
|
|
12
|
+
try{let u=await n.run(i,()=>a.generate(o));return i.invocada?{tipo:"vivo",result:u}:{tipo:"atajo",result:u}}catch(u){if(H(i,u))return s("sin-informe",Z),{tipo:"sin-informe"};throw u}},async transmitir(o,i,u){
|
|
13
|
+
let d=n.run(i,()=>a.generateStream(o,u?{signal:u}:{})).result;i.resultado=d,d.catch(()=>{});let f;try{f=await Promise.race([i.abierta.then(()=>"abierta"),d.then(()=>"resuelta")]);}catch(l){if(H(i,l))return s(
|
|
14
|
+
"sin-informe",Z),{tipo:"sin-informe"};throw l}if(f==="abierta")return {tipo:"abierto"};let g=await d;return i.invocada?{tipo:"entero",result:g}:{tipo:"atajo",result:g}},informe(o){let i=JSON.parse(JSON.
|
|
15
|
+
stringify(o));if(e.onReport)try{e.onReport(i);}catch{s("onreport","[bvsala] `onReport` threw; the error was caught and the model call was not affected.");}return i},avisar:s,close(){a.close();}}}function X(){
|
|
16
|
+
let t;return {abierta:new Promise(n=>{t=n;}),abrir:t}}var L=class{pendientes=[];esperando;terminada=false;fallo;push(e){if(this.terminada||this.fallo)return;let n=this.esperando;if(n){this.esperando=void 0,n.resolver({value:e,done:false});return}this.pendientes.
|
|
16
17
|
push(e);}end(){if(this.terminada||this.fallo)return;this.terminada=true;let e=this.esperando;e&&this.pendientes.length===0&&(this.esperando=void 0,e.resolver({value:void 0,done:true}));}fail(e){if(this.terminada||
|
|
17
18
|
this.fallo)return;this.fallo={error:e};let n=this.esperando;n&&this.pendientes.length===0&&(this.esperando=void 0,n.rechazar(e));}get cerrada(){return this.terminada||this.fallo!==void 0}[Symbol.asyncIterator](){
|
|
18
19
|
return {next:()=>this.pendientes.length>0?Promise.resolve({value:this.pendientes.shift(),done:false}):this.fallo?Promise.reject(this.fallo.error):this.terminada?Promise.resolve({value:void 0,done:true}):new Promise(
|
|
19
|
-
(e,n)=>{this.esperando={resolver:e,rechazar:n};}),return:()=>(this.terminada=true,this.pendientes.length=0,Promise.resolve({value:void 0,done:true}))}}};function
|
|
20
|
+
(e,n)=>{this.esperando={resolver:e,rechazar:n};}),return:()=>(this.terminada=true,this.pendientes.length=0,Promise.resolve({value:void 0,done:true}))}}};function m(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Y(t){return typeof t=="string"?[{type:"text",text:t}]:Array.isArray(t)?t.filter(m):[]}function O(t){return t.filter(e=>e.type===
|
|
20
21
|
"text"&&typeof e.text=="string").map(e=>e.text).join(`
|
|
21
|
-
`)}function
|
|
22
|
-
"string"?t.value:
|
|
23
|
-
return
|
|
24
|
-
system",content:typeof n.content=="string"?n.content:
|
|
25
|
-
map(
|
|
26
|
-
tool":for(let a of r)a.type==="tool-result"&&e.push({role:"tool",content:
|
|
27
|
-
{}});break}}return e}var
|
|
28
|
-
entries(t))if(!(n==="toolCallId"||n==="id")&&!(n==="text"&&t.type==="text")){if(n==="providerOptions"||n==="providerMetadata"){e[n]=
|
|
29
|
-
t:[]).map(e=>
|
|
30
|
-
if(!
|
|
31
|
-
entries(t))n==="prompt"||n==="abortSignal"||n==="headers"||n==="providerOptions"||(e[n]=r);return e.prompt=
|
|
32
|
-
responseFormat;if(
|
|
33
|
-
void 0}function
|
|
34
|
-
outputTokens:g??0,complete:false}}let
|
|
35
|
-
void 0?{cacheWriteInputTokens:
|
|
36
|
-
g")return t.unified}function
|
|
37
|
-
|
|
22
|
+
`)}function w(t){if(typeof t=="string")return t;try{return JSON.stringify(t??{})}catch{return "{}"}}function Se(t){if(!m(t))return w(t);switch(t.type){case "text":case "error-text":return typeof t.value==
|
|
23
|
+
"string"?t.value:w(t.value);case "json":case "error-json":return w(t.value);case "execution-denied":return `execution denied${typeof t.reason=="string"?`: ${t.reason}`:""}`;case "content":return O(e(t.value));default:
|
|
24
|
+
return w(t)}function e(n){return Array.isArray(n)?n.filter(m):[]}}function ee(t){let e=[];for(let n of Array.isArray(t)?t:[]){if(!m(n))continue;let r=Y(n.content);switch(n.role){case "system":e.push({role:"\
|
|
25
|
+
system",content:typeof n.content=="string"?n.content:O(r)});break;case "user":e.push({role:"user",content:O(r)});break;case "assistant":{let a=r.filter(s=>s.type==="tool-call"&&s.providerExecuted!==true).
|
|
26
|
+
map(s=>({...typeof s.toolCallId=="string"?{id:s.toolCallId}:{},name:String(s.toolName??""),arguments:w(s.input??s.args)}));e.push({role:"assistant",content:O(r),...a.length>0?{toolCalls:a}:{}});break}case "\
|
|
27
|
+
tool":for(let a of r)a.type==="tool-result"&&e.push({role:"tool",content:Se(a.output??a.result),...typeof a.toolCallId=="string"?{toolCallId:a.toolCallId}:{},...typeof a.toolName=="string"?{name:a.toolName}:
|
|
28
|
+
{}});break}}return e}var Ae=new Set(["bivelio","mastra"]);function T(t){if(!m(t))return t;let e={};for(let[n,r]of Object.entries(t))Ae.has(n)||(e[n]=r);return e}function ke(t){let e={};for(let[n,r]of Object.
|
|
29
|
+
entries(t))if(!(n==="toolCallId"||n==="id")&&!(n==="text"&&t.type==="text")){if(n==="providerOptions"||n==="providerMetadata"){e[n]=T(r);continue}e[n]=r;}return e}function De(t){return (Array.isArray(t)?
|
|
30
|
+
t:[]).map(e=>m(e)?{role:e.role,content:typeof e.content=="string"?"$text":Y(e.content).map(ke),providerOptions:T(e.providerOptions)}:e)}var Me=new Set(["anthropic-beta","openai-beta"]);function Ce(t){
|
|
31
|
+
if(!m(t))return;let e={};for(let[n,r]of Object.entries(t))Me.has(n.toLowerCase())&&r!==void 0&&(e[n.toLowerCase()]=r);return Object.keys(e).length>0?e:void 0}function te(t){let e={};for(let[n,r]of Object.
|
|
32
|
+
entries(t))n==="prompt"||n==="abortSignal"||n==="headers"||n==="providerOptions"||(e[n]=r);return e.prompt=De(t.prompt),e.headers=Ce(t.headers),e.providerOptions=T(t.providerOptions),e}function ne(t){
|
|
33
|
+
let e=t.responseFormat;if(m(e)&&e.type==="json")return true;let n=t.toolChoice;return m(n)&&(n.type==="required"||n.type==="tool")?true:n==="required"}function b(t){return typeof t=="number"&&Number.isFinite(
|
|
34
|
+
t)?t:void 0}function Pe(t,e){let n=m(t)?t:{},r=m(n.inputTokens)?n.inputTokens:void 0,a=m(n.outputTokens)?n.outputTokens:void 0;if(!r||!a){let f=b(n.inputTokens),g=b(n.outputTokens);return {inputTokens:f??
|
|
35
|
+
0,outputTokens:g??0,complete:false}}let s=b(r.total),o=b(r.cacheRead),i=b(r.cacheWrite),u=b(a.total),c=b(a.reasoning);return {inputTokens:s??0,outputTokens:u??0,...o!==void 0?{cachedInputTokens:o}:{},...i!==
|
|
36
|
+
void 0?{cacheWriteInputTokens:i}:{},...c!==void 0?{reasoningTokens:c}:{},...s!==void 0&&u!==void 0&&!e?{}:{complete:false}}}function Le(t){if(typeof t=="string")return t;if(m(t)&&typeof t.unified=="strin\
|
|
37
|
+
g")return t.unified}function Oe(t){switch(t){case void 0:return;case "tool-calls":return "tool_calls";case "content-filter":return "content_filter";default:return t}}function Te(t){return m(t)&&Object.keys(
|
|
38
|
+
T(t)).length>0}var D=class{texto="";toolCalls=[];reproducible=true;finish;error;anadir(e){switch(e.type){case "text-delta":{let n=typeof e.delta=="string"?e.delta:typeof e.textDelta=="string"?e.textDelta:
|
|
38
39
|
"";return this.texto+=n,n===""?void 0:n}case "text":{let n=typeof e.text=="string"?e.text:"";return this.texto+=n,n===""?void 0:n}case "tool-call":e.providerExecuted===true?this.reproducible=false:this.toolCalls.
|
|
39
|
-
push({...typeof e.toolCallId=="string"?{id:e.toolCallId}:{},name:String(e.toolName??""),arguments:
|
|
40
|
-
-end":
|
|
41
|
-
raw":return;case "finish":this.finish=e;return;case "error":this.error={error:e.error};return;default:this.reproducible=false;return}}respuesta(e,n,r){let a=
|
|
42
|
-
text:this.texto,...this.toolCalls.length>0?{toolCalls:this.toolCalls}:{},...
|
|
43
|
-
t.content:[])
|
|
44
|
-
return t.text!==""&&e.push({type:"text",text:t.text}),(t.toolCalls??[]).forEach((n,r)=>{e.push({type:"tool-call",toolCallId:n.id??`bvsala-${t.requestId}-${r}`,toolName:n.name,input:n.arguments});}),e}function
|
|
45
|
-
return {unified:(t.toolCalls?.length??0)>0?"tool-calls":"stop",raw:void 0}}function
|
|
46
|
-
response-metadata",...n.response}),t.forEach((a,
|
|
47
|
-
xt-start",id:o,...
|
|
48
|
-
{providerMetadata:a.providerMetadata}:{};r.push({type:"reasoning-start",id:o,...
|
|
49
|
-
id:o,...
|
|
50
|
-
{pull(n){e<t.length?n.enqueue(t[e++]):n.close();}})}function
|
|
51
|
-
return typeof t.provider=="string"&&t.provider.toLowerCase().startsWith("mock")}function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
o}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
o
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
40
|
+
push({...typeof e.toolCallId=="string"?{id:e.toolCallId}:{},name:String(e.toolName??""),arguments:w(e.input??e.args)});return;case "reasoning":case "reasoning-start":case "reasoning-delta":case "reasoning\
|
|
41
|
+
-end":Te(e.providerMetadata)&&(this.reproducible=false);return;case "text-start":case "text-end":case "tool-input-start":case "tool-input-delta":case "tool-input-end":case "stream-start":case "response-metadata":case "\
|
|
42
|
+
raw":return;case "finish":this.finish=e;return;case "error":this.error={error:e.error};return;default:this.reproducible=false;return}}respuesta(e,n,r){let a=Le(n),s=Oe(a),o=this.reproducible&&a==="stop";return {
|
|
43
|
+
text:this.texto,...this.toolCalls.length>0?{toolCalls:this.toolCalls}:{},...s?{finishReason:s}:{},usage:Pe(e,r),...o?{}:{replayable:false}}}};function q(t,e){let n=new D;for(let r of Array.isArray(t.content)?
|
|
44
|
+
t.content:[])m(r)&&n.anadir(r);return n.respuesta(t.usage,t.finishReason,e)}var U={inputTokens:{total:0,noCache:0,cacheRead:0,cacheWrite:0},outputTokens:{total:0,text:0,reasoning:0}};function N(t){let e=[];
|
|
45
|
+
return t.text!==""&&e.push({type:"text",text:t.text}),(t.toolCalls??[]).forEach((n,r)=>{e.push({type:"tool-call",toolCallId:n.id??`bvsala-${t.requestId}-${r}`,toolName:n.name,input:n.arguments});}),e}function $(t){
|
|
46
|
+
return {unified:(t.toolCalls?.length??0)>0?"tool-calls":"stop",raw:void 0}}function z(t,e,n){let r=[{type:"stream-start",warnings:Array.isArray(n.warnings)?n.warnings:[]}];return n.response&&r.push({type:"\
|
|
47
|
+
response-metadata",...n.response}),t.forEach((a,s)=>{if(!m(a))return;let o=`bvsala-${s}`;if(a.type==="text"){let i=a.providerMetadata!==void 0?{providerMetadata:a.providerMetadata}:{};r.push({type:"te\
|
|
48
|
+
xt-start",id:o,...i}),typeof a.text=="string"&&a.text!==""&&r.push({type:"text-delta",id:o,delta:a.text}),r.push({type:"text-end",id:o,...i});}else if(a.type==="reasoning"){let i=a.providerMetadata!==void 0?
|
|
49
|
+
{providerMetadata:a.providerMetadata}:{};r.push({type:"reasoning-start",id:o,...i}),typeof a.text=="string"&&a.text!==""&&r.push({type:"reasoning-delta",id:o,delta:a.text}),r.push({type:"reasoning-end",
|
|
50
|
+
id:o,...i});}else r.push(a);}),r.push({type:"finish",usage:e.usage,finishReason:e.finishReason,...e.providerMetadata!==void 0?{providerMetadata:e.providerMetadata}:{}}),r}function G(t){let e=0;return new ReadableStream(
|
|
51
|
+
{pull(n){e<t.length?n.enqueue(t[e++]):n.close();}})}function re(t){let e=String(t.modelId??"");if(e.includes("/"))return e;let n=String(t.provider??"").split(".")[0]??"";return n!==""?`${n}/${e}`:e}function oe(t){
|
|
52
|
+
return typeof t.provider=="string"&&t.provider.toLowerCase().startsWith("mock")}function S(t,e){return {...m(t)?t:{},bivelio:{savingsReport:e}}}var Ie=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,
|
|
53
|
+
4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,
|
|
54
|
+
1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,
|
|
55
|
+
1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),Ee=new TextEncoder;function h(t,e){return t>>>e|t<<32-e}function ae(t){let e=Ee.encode(t),n=e.length*
|
|
56
|
+
8,r=(e.length+8>>6)+1,a=new Uint8Array(r*64);a.set(e),a[e.length]=128;let s=new DataView(a.buffer);s.setUint32(a.length-8,Math.floor(n/4294967296)),s.setUint32(a.length-4,n>>>0);let o=new Uint32Array(
|
|
57
|
+
[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),i=new Uint32Array(64);for(let c=0;c<a.length;c+=64){for(let p=0;p<16;p++)i[p]=s.getUint32(c+p*4);for(let p=16;p<
|
|
58
|
+
64;p++){let A=i[p-15],k=i[p-2],C=h(A,7)^h(A,18)^A>>>3,I=h(k,17)^h(k,19)^k>>>10;i[p]=i[p-16]+C+i[p-7]+I|0;}let d=o[0],f=o[1],g=o[2],l=o[3],v=o[4],y=o[5],x=o[6],R=o[7];for(let p=0;p<64;p++){let A=h(v,6)^
|
|
59
|
+
h(v,11)^h(v,25),k=v&y^~v&x,C=R+A+k+Ie[p]+i[p]|0,I=h(d,2)^h(d,13)^h(d,22),fe=d&f^d&g^f&g,pe=I+fe|0;R=x,x=y,y=v,v=l+C|0,l=g,g=f,f=d,d=C+pe|0;}o[0]=o[0]+d|0,o[1]=o[1]+f|0,o[2]=o[2]+g|0,o[3]=o[3]+l|0,o[4]=
|
|
60
|
+
o[4]+v|0,o[5]=o[5]+y|0,o[6]=o[6]+x|0,o[7]=o[7]+R|0;}let u="";for(let c=0;c<8;c++)u+=(o[c]>>>0).toString(16).padStart(8,"0");return u}var je={router:false,compression:false,elision:false,serialization:false,toolDiscovery:false,modelCascade:"off",outputCodebook:false,deferrable:false,semanticCache:false,verification:false};function qe(t,e,n={}){let r=a=>t?.[a]!==
|
|
61
|
+
false&&e?.[a]!==false;return {...je,exactCache:r("exactCache")&&n.sinReutilizar!==true,singleflight:r("singleflight")&&n.sinReutilizar!==true,deterministicResolvers:r("deterministicResolvers")&&n.sinResolvers!==
|
|
62
|
+
true}}function Ue(t,e){let n=t.readOnlyTools;if(typeof n=="function")try{return n(e)===!0}catch{return false}return Array.isArray(n)?n.includes(e):false}function se(t,e){let n=e.delProveedor!==true&&Ue(t,e.nombre);
|
|
63
|
+
return {id:e.nombre,intents:[],risk:n?"read":"write",...e.parametros!==void 0&&e.parametros!==null&&typeof e.parametros=="object"?{parameters:e.parametros}:{},...typeof e.descripcion=="string"?{description:e.
|
|
64
|
+
descripcion}:{}}}function M(t,e,n){if(t===null)return null;switch(typeof t){case "string":case "boolean":return t;case "number":return Number.isFinite(t)?t:String(t);case "bigint":return `${t.toString()}n`;case "\
|
|
65
|
+
undefined":case "function":case "symbol":return}let r=t;if(r instanceof Uint8Array)return e.push(r),{$bytes:e.length-1};if(r instanceof ArrayBuffer)return e.push(new Uint8Array(r)),{$bytes:e.length-1};if(ArrayBuffer.
|
|
66
|
+
isView(r))return e.push(new Uint8Array(r.buffer,r.byteOffset,r.byteLength)),{$bytes:e.length-1};if(r instanceof URL)return {$url:r.href};if(r instanceof Date)return {$date:Number.isNaN(r.getTime())?"inv\
|
|
67
|
+
alid":r.toISOString()};if(n.has(r))return "$cycle";n.add(r);try{if(Array.isArray(r))return r.map(s=>{let o=M(s,e,n);return o===void 0?null:o});if(r instanceof Map)return {$map:[...r.entries()].map(s=>M(
|
|
68
|
+
s,e,n))};if(r instanceof Set)return {$set:[...r.values()].map(s=>M(s,e,n))};let a={};for(let s of Object.keys(r).sort()){let o=M(r[s],e,n);o!==void 0&&(a[s]=o);}return a}finally{n.delete(r);}}async function ie(t){
|
|
69
|
+
let e=globalThis.crypto?.subtle;if(e){let r=new Uint8Array(await e.digest("SHA-256",t));return Array.from(r,a=>a.toString(16).padStart(2,"0")).join("")}let n="";for(let r=0;r<t.length;r+=32768)n+=String.
|
|
70
|
+
fromCharCode(...t.subarray(r,r+32768));return ae(n)}async function Ne(t){try{let e=[],n=JSON.stringify(M(t,e,new WeakSet))??"null",r=await Promise.all(e.map(ie)),a=new TextEncoder().encode(`${n}|${r.join(
|
|
71
|
+
",")}`);return await ie(a)}catch{return null}}async function de(t,e){let n=await Ne(e.proyeccion),r=`${e.context?.authorizationScope??"default"}|bvsala-adapter:${n??"none"}`;return {model:e.model,messages:e.
|
|
72
|
+
messages,...e.tools.length>0?{tools:e.tools}:{},...typeof e.temperature=="number"?{temperature:e.temperature}:{},...typeof e.seed=="number"?{seed:e.seed}:{},context:{...e.context??{},authorizationScope:r},
|
|
73
|
+
savings:qe(t.savings,e.savings,{...e.restricciones,...n===null?{sinReutilizar:true}:{}})}}function ue(t,e){if(!(!t&&!e))return {...t??{},...e??{}}}function le(t){if(!t||typeof t!="object")return {};let e=t,
|
|
74
|
+
n={};return e.context&&typeof e.context=="object"&&(n.context=e.context),e.savings&&typeof e.savings=="object"&&(n.savings=e.savings),n}var $e="[bvsala] a streamed call finished but its savings report could not be produced; the model answer was delivered unchanged.";function dt(t){let e=Q("ai-sdk",t),n=t.reportInMetadata!==false;async function r(o,i){
|
|
75
|
+
let u=le(o.providerOptions?.bivelio),c;t.context&&(c=t.context({provider:i.provider,modelId:i.modelId,params:o}));let d=t.modelId?t.modelId({provider:i.provider,modelId:i.modelId}):re(i),f=(Array.isArray(
|
|
76
|
+
o.tools)?o.tools:[]).map(l=>se(t,{nombre:String(l.name??l.id??""),descripcion:typeof l.description=="string"?l.description:void 0,parametros:l.inputSchema??l.parameters,delProveedor:l.type==="provider"||
|
|
77
|
+
l.type==="provider-defined"}));return {req:await de(t,{model:d,messages:ee(o.prompt),tools:f,temperature:typeof o.temperature=="number"?o.temperature:void 0,seed:typeof o.seed=="number"?o.seed:void 0,context:ue(
|
|
78
|
+
c,u.context),savings:u.savings,proyeccion:{modelo:d,parametros:te(o)},restricciones:{sinResolvers:ne(o)}}),simulado:oe(i)}}function a(o){return {model:o.model,messages:o.messages,...o.tools?{tools:o.tools}:
|
|
79
|
+
{}}}return {specificationVersion:"v3",async wrapGenerate(o){let{req:i,simulado:u}=await r(o.params,o.model),c,d=j(a(i),async()=>(c=await P(d,()=>o.doGenerate()),q(c,u))),f=await e.generar(i,d);if(f.tipo===
|
|
80
|
+
"sin-informe")return c;let g=e.informe(f.result.report);if(f.tipo==="vivo"){let l=c;return n?{...l,providerMetadata:S(l.providerMetadata,g)}:l}return Ge(f.result,n?g:void 0,o.model)},async wrapStream(o){
|
|
81
|
+
let{req:i,simulado:u}=await r(o.params,o.model),{abierta:c,abrir:d}=X(),f,g,l=Object.assign(j(a(i),async()=>(f=await P(l,()=>o.doGenerate()),q(f,u)),()=>{let R=new L;return P(l,()=>o.doStream()).then(
|
|
82
|
+
p=>{g={...p,stream:ze(p.stream,R,e,l,u,n)},d();},p=>R.fail(p)),R}),{abierta:c}),v=o.params.abortSignal instanceof AbortSignal?o.params.abortSignal:void 0,y=await e.transmitir(i,l,v);if(y.tipo==="abiert\
|
|
83
|
+
o")return g;if(y.tipo==="sin-informe")return ce(f,void 0);let x=e.informe(y.result.report);return y.tipo==="entero"?ce(f,n?x:void 0):_e(y.result,n?x:void 0,o.model)},close(){e.close();}}}function ze(t,e,n,r,a,s){
|
|
84
|
+
let o=t.getReader(),i=new D;return new ReadableStream({async pull(u){let c;try{c=await o.read();}catch(l){e.fail(l),u.error(l);return}if(c.done){e.fail(new Error("[bvsala] the model stream ended withou\
|
|
85
|
+
t a finish part; nothing was measured.")),u.close();return}let d=c.value,f=i.anadir(d);if(d.type==="error"){e.fail(d.error??new Error("[bvsala] the model stream reported an error")),u.enqueue(d);return}
|
|
86
|
+
if(f!==void 0&&e.push({type:"text",delta:f}),d.type!=="finish"||e.cerrada){u.enqueue(d);return}e.push({type:"done",response:i.respuesta(d.usage,d.finishReason,a)}),e.end();let g=d;try{let l=await r.resultado,
|
|
87
|
+
v=n.informe(l.report);s&&(g={...d,providerMetadata:S(d.providerMetadata,v)});}catch{n.avisar("informe-del-stream",$e);}u.enqueue(g);},cancel(u){return e.fail(new Error("[bvsala] the stream was cancelled \
|
|
88
|
+
by its reader; nothing was measured.")),o.cancel(u)}})}function Ge(t,e,n){return {content:N(t),finishReason:$(t),usage:U,...e?{providerMetadata:S(void 0,e)}:{},response:{id:`bvsala-${t.requestId}`,modelId:n.
|
|
89
|
+
modelId,timestamp:new Date},warnings:[]}}function _e(t,e,n){let r=z(N(t),{usage:U,finishReason:$(t),...e?{providerMetadata:S(void 0,e)}:{}},{warnings:[],response:{id:`bvsala-${t.requestId}`,modelId:n.
|
|
90
|
+
modelId,timestamp:new Date}});return {stream:G(r)}}function ce(t,e){let n=t.response,r=z(Array.isArray(t.content)?t.content:[],{usage:t.usage,finishReason:t.finishReason,...e?{providerMetadata:S(t.providerMetadata,
|
|
82
91
|
e)}:t.providerMetadata!==void 0?{providerMetadata:t.providerMetadata}:{}},{warnings:t.warnings,response:n?Object.fromEntries(Object.entries(n).filter(([a])=>a!=="headers"&&a!=="body")):void 0});return {
|
|
83
|
-
stream:
|
|
84
|
-
object"||typeof n.requestId!="string"))return n}export{
|
|
92
|
+
stream:G(r),...t.request!==void 0?{request:t.request}:{},...n?.headers!==void 0?{response:{headers:n.headers}}:{}}}function ut(t){let n=t?.providerMetadata?.bivelio?.savingsReport;if(!(!n||typeof n!="\
|
|
93
|
+
object"||typeof n.requestId!="string"))return n}export{ut as getSavingsReport,dt as savingsMiddleware};
|
|
@@ -29,6 +29,19 @@ interface AnthropicSavings {
|
|
|
29
29
|
/**
|
|
30
30
|
* The savings layer as an Anthropic SDK middleware:
|
|
31
31
|
* `new Anthropic({ middleware: [savings.middleware] })`, last in the list.
|
|
32
|
+
*
|
|
33
|
+
* **Stop reasons.** The middleware speaks the official SDK's protocol to your
|
|
34
|
+
* code, so the `Message` you get keeps Anthropic's own `stop_reason`
|
|
35
|
+
* (`end_turn`, `max_tokens`, `stop_sequence`, `tool_use`, `pause_turn`,
|
|
36
|
+
* `refusal`, `model_context_window_exceeded`…) and `stop_details`, exactly as
|
|
37
|
+
* Anthropic sent them, in JSON and in stream. That is the SDK's contract and the
|
|
38
|
+
* layer does not rewrite it. An answer the layer served without calling
|
|
39
|
+
* Anthropic (from its cache or a local resolver) comes back as `end_turn`, or
|
|
40
|
+
* `tool_use` when it carries tool calls. What the layer normalises is its own report:
|
|
41
|
+
* {@link AnthropicSavings.reportFor} gives `qualityLedger.truncation.finishReason`
|
|
42
|
+
* in the closed set of 0.5 (`stop`, `length`, `tool_calls`, `content_filter`,
|
|
43
|
+
* `other`) and Anthropic's value, when it adds something, in
|
|
44
|
+
* `truncation.finishReasonDetail`.
|
|
32
45
|
*/
|
|
33
46
|
declare function anthropicSavings(options: AnthropicSavingsOptions): AnthropicSavings;
|
|
34
47
|
|