@bivelio/savings-layer 0.4.30 → 0.4.32

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
@@ -211,7 +211,8 @@ import { createSavingsLayer, OpenAICompatibleProvider } from "@bivelio/savings-l
211
211
  // Your provider. LLM traffic goes straight to it — the SDK never proxies it.
212
212
  // Any OpenAI-compatible endpoint works: OpenAI, Azure, vLLM, SGLang, a gateway.
213
213
  // Model ids are qualified (`openai/gpt-4o-mini`); the prefix is stripped on the
214
- // wire for OpenAI and Azure and kept for gateways — see `stripProviderPrefix`.
214
+ // wire for OpenAI, Azure and Google's Gemini API and kept for gateways — see
215
+ // `stripProviderPrefix`.
215
216
  const provider = new OpenAICompatibleProvider({
216
217
  baseUrl: "https://api.openai.com/v1",
217
218
  apiKey: process.env.OPENAI_API_KEY,
@@ -282,6 +283,46 @@ nothing either. The same rule applies in the gateway. Any other refusal is price
282
283
  its `usage` as usual. That covers `bio`, `frontier_llm` and `reasoning_extraction`, a
283
284
  refusal after partial output, and a category the table does not list.
284
285
 
286
+ Most refusals carry no signal from the API: the model writes "I can't help with that."
287
+ as ordinary text and ends with `end_turn` or `stop`. The layer also looks for these,
288
+ with a conservative text heuristic. It checks only the opening of the answer, or the
289
+ whole answer when it is short, and it needs a real refusal clause, such as "I'm sorry,
290
+ but I can't help with that", "I cannot assist", "I can't determine…" or "As an AI, I
291
+ cannot provide". After an apology, any verb counts ("I'm sorry, but I can't
292
+ determine…"), and so does a stated reason with no "I can't" ("I'm sorry, but
293
+ accessing … is illegal", "… would be a violation of…"). When the answer opens with
294
+ the refusal itself ("I can't", "I won't", "I'm not going to", "I'm unable to", and
295
+ "No puedo", "Je ne peux pas", "Ich kann … nicht"…), any verb counts too ("I can't
296
+ argue that…"), except for a tested list of idioms that are not refusals ("I can't
297
+ wait", "I won't lie", "I can't find any issues", "I can't be sure, but…").
298
+ A single word is not enough.
299
+ An answer that opens with empathy and, in its first two sentences, sends the user to
300
+ a mental health professional, a crisis line, emergency services or someone they
301
+ trust, instead of answering, counts too (rule `redirection`). It covers English,
302
+ Spanish, Catalan, French, German, Italian and Portuguese. A match is measured and
303
+ served as usual. It is not written to the exact or semantic cache, and it is not
304
+ replayed by reference. A concurrent identical request served from it is `estimated`.
305
+ The trace says why (`skipReason: "text_refusal"`, with the `rule`). A refusal
306
+ already stored by an earlier version is not served either. In the gateway, the
307
+ coalesced twin of such a response is `estimated` (`primary-text-refusal`). A false
308
+ positive costs one cache hit. A normal answer that starts with "Sorry for the delay,
309
+ here is…", praises with "I can't recommend this enough", has "I can't" later on, or
310
+ offers empathy with practical help and no referral ("I'm sorry to hear about your
311
+ flight; here are three options…") is cached as before.
312
+
313
+ **Sensitive topics.** A request whose user turns touch self-harm or suicide, a mental
314
+ health crisis or a medical emergency ("How do I commit suicide?", "I'm having a panic
315
+ attack", "my friend is not breathing") is never read from or written to the exact or
316
+ semantic cache, even when the answer is useful, and leaves no reference record. It is
317
+ measured and served as usual; a concurrent identical request served from it is
318
+ `estimated`. The `policy` and `cache-write` traces say why
319
+ (`skipReason: "sensitive_topic"`, with the `category`). The check is lexical and
320
+ conservative: phrases, not single words ("kill a Python process", "Suicide Squad" and
321
+ "cut my hair" do not count). It covers the same twelve languages as the freshness
322
+ and personalization checks, with shorter lists outside English, Spanish, Catalan,
323
+ French, German, Italian and Portuguese. In the gateway, the coalesced twin of such a
324
+ request is `estimated` (`sensitive-topic`). A false positive costs one cache hit.
325
+
285
326
  **Streaming.** `generateStream()` takes the same request and hands you the answer as
286
327
  the provider writes it, then the same `SavingsReport`:
287
328
 
@@ -438,6 +479,45 @@ It runs once per HTTP attempt, inside the SDK's retries: an attempt the provider
438
479
  rejects reaches the SDK unchanged and is not recorded. Only message creation goes
439
480
  through the layer; `countTokens`, batches, models and files pass untouched.
440
481
 
482
+ The middleware forwards your request body unchanged, history included, so it never
483
+ edits a turn before a thinking block. It also does not remove parameters the model
484
+ rejects. On Claude Sonnet 5.5, Opus 5.5, Fable 5.1 and Mythos 5.1 a forced
485
+ `tool_choice` (`any` or `tool`) returns a 400. On those models, and on Opus 4.7/4.8,
486
+ Opus 5, Sonnet 5 and Fable 5, so does a non-default `temperature`, `top_p` or `top_k`.
487
+ The middleware warns once per model and cause (`silenceWarnings` turns it off) and
488
+ the API's 400 reaches you unchanged.
489
+
490
+ <details>
491
+ <summary><b>Claude Sonnet 5.5, Opus 5.5, Fable 5.1: what <code>AnthropicProvider</code> sends instead</b></summary>
492
+
493
+ These models reject some request parameters with a 400 ([forcing tool
494
+ use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools#forcing-tool-use),
495
+ [Sonnet 5.5](https://platform.claude.com/docs/en/models/sonnet-5-5/overview)).
496
+ `AnthropicProvider` sends a request they accept instead of failing:
497
+
498
+ - **Output contract.** A forced `tool_choice` returns a 400 on these models, with or
499
+ without thinking. When your schema meets `strict` mode, the contract travels as
500
+ structured output (`output_config.format`). Without your tools, the provider still
501
+ enforces the contract. With your tools, they stay callable with `tool_choice: auto`
502
+ and the final text answer comes back in the contract's shape. When your schema does
503
+ not meet `strict`, the contract travels as a tool the model is not forced to call,
504
+ with one sentence in the system prompt that tells it to answer through that tool.
505
+ Models that support forced tool use (Opus 5, Sonnet 5 and the 4.x models) get the
506
+ same request as before.
507
+ - **`temperature`.** A non-default value is dropped, with one warning per model,
508
+ because it can only return a 400. The answer is then sampled, not deterministic.
509
+ `temperature: 1`, the API default, is sent as is.
510
+ - **A model the table does not list** (a new model or a gateway alias): when the API
511
+ rejects either parameter, the provider repeats the request once without it and
512
+ remembers the model for later requests. A 400 is not billed, so the retry is not
513
+ counted in `retries`.
514
+ - **Thinking blocks.** `ChatMessage` does not carry thinking blocks, so this adapter
515
+ never sends one. The preserved-thinking check, which returns a 400 when a turn
516
+ before a thinking block has been edited, has nothing to check on its requests, even
517
+ when the levers that rewrite history are on.
518
+
519
+ </details>
520
+
441
521
  ## What you get on every request
442
522
 
443
523
  A `SavingsReport` with the numbers behind every claim, kept in **four separate
@@ -666,7 +746,16 @@ const agentLayer = createSavingsLayer({
666
746
 
667
747
  By default the layer writes the provider's prompt cache at two fixed places: the end
668
748
  of the system header and the end of the history before your last user message, and
669
- stops marking a prefix whose measured hit rate does not pay the write premium.
749
+ stops marking a prefix whose measured hit rate does not pay the write premium. On
750
+ Anthropic, where a write costs 1.25x, the history and a tool catalogue sent without a
751
+ system header are marked only when the request itself shows they will be sent again:
752
+ a tool-loop step after your last user message, or a conversation already past its
753
+ second turn. The first follow-up of a conversation (`[question, answer, question]`)
754
+ marks only the system header, so two-turn chats pay no premium that nothing reads.
755
+ In an agent loop with no system header, the end of the tool list is marked once the
756
+ catalogue reaches the model's minimum cacheable size (512 tokens on Claude Sonnet 5.5
757
+ and Opus 5.5, 1,024 on Sonnet 5, 4,096 on Haiku 4.5). That discount is the provider's
758
+ cache on your bytes: it is never credited as the layer's saving.
670
759
 
671
760
  `cacheBreakpoints: "auto"` places them from what your traffic actually does. The layer
672
761
  compares each request's prefix with the ones it sent before, per model, tool set and
@@ -711,7 +800,11 @@ const placedLayer = createSavingsLayer({
711
800
  Calibrated reuse and `cacheBreakpoints: "auto"` learn from your traffic, and by default
712
801
  what they learn lives in the process. On serverless platforms (Vercel Functions, AWS
713
802
  Lambda) an instance may serve one request or live a few minutes, so neither would ever
714
- get past its starting point. Give each one somewhere to keep it:
803
+ get past its starting point. Give each one somewhere to keep it. Giving the layer a
804
+ `semanticCache` only says where reworded questions are kept; `semanticCacheDefault: true`
805
+ is what switches reuse on for every request (a request's own `savings.semanticCache`
806
+ still wins), and without it, or `savings.semanticCache` on each request, the cache
807
+ stays empty and learns nothing:
715
808
 
716
809
  ```ts
717
810
  import { InMemorySemanticCache } from "@bivelio/savings-layer";
@@ -731,6 +824,8 @@ async function serverlessLayer(kv: SharedKeyValue) {
731
824
  provider,
732
825
  licenseKey: process.env.BIVELIO_LICENSE_KEY,
733
826
  semanticCache,
827
+ // Passing the cache does not switch it on; this asks for it on every request.
828
+ semanticCacheDefault: true,
734
829
  cacheBreakpoints: "auto",
735
830
  cacheBreakpointStore: {
736
831
  get: (key) => kv.get(key),
@@ -802,6 +897,54 @@ console.log(data.answer); // 8
802
897
 
803
898
  </details>
804
899
 
900
+ <details>
901
+ <summary><b>Output cap — with or without a contract</b></summary>
902
+
903
+ `maxOutputTokens` on the request caps the answer of any request, free text
904
+ included. With `response.maxOutputTokens` as well, the smaller of the two is sent.
905
+
906
+ ```ts
907
+ const { text, finishReason } = await layer.generate({
908
+ model: "openai/gpt-5-mini",
909
+ messages: [{ role: "user", content: "Summarize this in two sentences: …" }],
910
+ maxOutputTokens: 300,
911
+ });
912
+ ```
913
+
914
+ On the wire it becomes Anthropic's `max_tokens`; on Chat Completions,
915
+ `max_completion_tokens` when `baseUrl` is OpenAI's own API (`max_tokens` is
916
+ deprecated there and its reasoning models, o-series and gpt-5.x, reject it) and
917
+ `max_tokens` on any other OpenAI-compatible endpoint, which is the field they all
918
+ understand. If an endpoint answers 400 naming the field it got as unsupported, the
919
+ request is repeated once with the other one (nothing was generated, so nothing is
920
+ billed twice) and the model is remembered. To choose the field yourself:
921
+ `new OpenAICompatibleProvider({ baseUrl, maxTokensParam: "max_completion_tokens" })`.
922
+
923
+ **OpenAI-compatible endpoints that are not OpenAI** (Gemini's
924
+ `generativelanguage.googleapis.com/v1beta/openai`, LiteLLM, vLLM, Ollama, a router).
925
+ `prompt_cache_key`, OpenAI's prefix-cache routing hint, goes only to OpenAI's own API:
926
+ Gemini answers 400 to a field it does not know, and up to 0.4.31 every request with a
927
+ cached prefix failed there. A proxy in front of OpenAI that forwards it can opt in with
928
+ `sendPromptCacheKey: true`. Any optional field an endpoint still rejects by name
929
+ (`prompt_cache_key`, `service_tier`, `seed`, `reasoning_effort`) is dropped, the request
930
+ repeated once and the model remembered; `reasoning_effort` is never dropped on OpenAI's
931
+ own API, where its 400 is the answer. Gemini leaves its thinking tokens out of
932
+ `completion_tokens` and bills them as output, so the layer counts output as
933
+ `total_tokens − prompt_tokens` whenever the total is larger (and reports the difference
934
+ as reasoning); on OpenAI's API `completion_tokens` already include reasoning and nothing
935
+ is added. Gemini stops a filtered answer with `finish_reason: "content_filter: OTHER"`
936
+ (or another reason): it is `finishReason: "content_filter"` (the adapter keeps the
937
+ reason in `finishReasonDetail` and the report's cache trace names it), and like every
938
+ provider refusal it is measured, never
939
+ cached and never credited. Google does not document that such refusals are free, so
940
+ they are costed from their `usage` like any call.
941
+
942
+ The cap is yours, not a saving: it is never credited as output avoided. An answer
943
+ it cut (`finishReason: "length"`) is not cached, and
944
+ `report.qualityLedger.truncation` says the limit was yours.
945
+
946
+ </details>
947
+
805
948
  <details>
806
949
  <summary><b>Tool calls</b></summary>
807
950
 
@@ -854,6 +997,18 @@ console.log(res.text);
854
997
  the SDK warns once.
855
998
  - **Errors.** When a tool fails, put the error in `content` and set `isError: true`.
856
999
  Anthropic receives it as `is_error`; providers without such a flag get the text.
1000
+ - **Gemini 3's thought signature.** Through its OpenAI-compatible endpoint Gemini
1001
+ returns each call with `extra_content.google.thought_signature` and rejects the next
1002
+ turn with a 400 if the call comes back without it. It arrives in `call.extraContent`;
1003
+ pushing `res.toolCalls` back as they came (as above) sends it back untouched. It is
1004
+ opaque and not part of any cache key.
1005
+ - **gpt-5.6-sol, gpt-5.6-terra and gpt-5.6-luna with tools need `reasoningEffort: "none"`.**
1006
+ On Chat Completions OpenAI rejects function tools for these models unless
1007
+ `reasoning_effort` is `"none"` («Function tools with reasoning_effort are not supported for gpt-5.6-sol in
1008
+ /v1/chat/completions»). Declare it on the request:
1009
+ `layer.generate({ model: "openai/gpt-5.6-sol", messages, tools, reasoningEffort: "none" })`.
1010
+ The layer never picks an effort itself: without the field nothing is sent. It is part
1011
+ of the cache key, like `temperature` and `seed`.
857
1012
 
858
1013
  A tool‑call turn is never served from cache and never counted as an avoided call:
859
1014
  an action that has not run yet cannot be a saving. The answer that follows a tool loop
@@ -862,13 +1017,21 @@ each result answers and its `isError`. Two conversations that differ only there
862
1017
  share a cached answer; the fresh call ids of a new run of the same loop are not a
863
1018
  difference.
864
1019
 
1020
+ **Which tools reach the model.** The layer never cuts a catalogue it cannot rank. If
1021
+ your tools declare no `intents` and no `risk` (the usual shape of MCP and OpenAI tool
1022
+ lists), or you pass `savings: { router: false }`, every tool goes to the provider
1023
+ exactly as you sent it, and the layer credits nothing for the tool block. Only when
1024
+ your tools declare `intents`/`risk` does the selector keep the relevant ones, up to
1025
+ `new ToolSelector({ maxTools })` (8 by default), and hold back write tools from a
1026
+ request that is not an action. Whatever it leaves out, the model cannot call in that
1027
+ request: the report's `tool-selector` trace lists it, the tokens count as eliminated
1028
+ input, and the SDK warns once per process (`silenceWarnings` turns the warning off).
1029
+
865
1030
  **Large catalogues: let the provider search them (opt‑in).** With hundreds of tools
866
1031
  (several MCP servers, say), `savings: { toolSearch: "auto" }` sends every tool deferred
867
- behind the provider's own tool search instead of letting the layer's selector keep a
868
- few. A catalogue that declares no `intents` or `risk` gives the selector nothing to go
869
- on, so it keeps the first ones and the model cannot call the rest; with the provider's
870
- search the model looks up what it needs, no tool you declared is out of reach, and the
871
- cached prompt prefix stays the same from one question to the next.
1032
+ behind the provider's own tool search instead of putting the whole catalogue in every
1033
+ request's prompt. The model looks up what it needs, no tool you declared is out of
1034
+ reach, and the cached prompt prefix stays the same from one question to the next.
872
1035
 
873
1036
  - **Where.** The Anthropic adapter, on models in Anthropic's tool search compatibility
874
1037
  table. OpenAI documents its tool search for the Responses and Agents APIs, not for
@@ -1,67 +1,73 @@
1
1
  import {createSavingsLayer,LicenseError,sha256,stableStringify}from'@bivelio/savings-layer';import {AsyncLocalStorage}from'async_hooks';var x=t=>typeof t=="number"&&Number.isFinite(t)&&t>0?t:0;function J(t){if(!Array.isArray(t))return null;let e={input:0,output:0,cacheRead:0,cacheWrite:0,cacheWrite1h:0,iteraciones:0};for(let n of t){if(n===
2
2
  null||typeof n!="object")continue;let r=n;if(r.type!=="compaction")continue;e.iteraciones++,e.input+=x(r.input_tokens),e.output+=x(r.output_tokens),e.cacheRead+=x(r.cache_read_input_tokens);let o=r.cache_creation,
3
3
  s=x(o?.ephemeral_5m_input_tokens),a=x(o?.ephemeral_1h_input_tokens),i=typeof r.cache_creation_input_tokens=="number"?x(r.cache_creation_input_tokens):s+a;e.cacheWrite+=i,e.cacheWrite1h+=Math.min(a,i);}
4
- return e.iteraciones>0?e:null}function B(t,e,n){let r=t??{},o=J(r.iterations),s=W(r.cache_read_input_tokens,o?.cacheRead),a=W(r.cache_creation_input_tokens,o?.cacheWrite),i=r.cache_creation?.ephemeral_1h_input_tokens,u=typeof i=="\
4
+ return e.iteraciones>0?e:null}function W(t,e,n){let r=t??{},o=J(r.iterations),s=F(r.cache_read_input_tokens,o?.cacheRead),a=F(r.cache_creation_input_tokens,o?.cacheWrite),i=r.cache_creation?.ephemeral_1h_input_tokens,l=typeof i=="\
5
5
  number"||(o?.cacheWrite1h??0)>0?Math.min(Math.max(0,(typeof i=="number"?i:0)+(o?.cacheWrite1h??0)),a??0):void 0,d=(r.input_tokens??0)+(o?.input??0)+(a??0)+(s??0),g=(e??0)+(o?.output??0),m=typeof r.input_tokens!=
6
- "number",h=typeof e!="number";return {usage:{inputTokens:d,outputTokens:g,...s!=null?{cachedInputTokens:s}:{},...a!=null?{cacheWriteInputTokens:a}:{},...u!==void 0?{cacheWrite1hInputTokens:u}:{},...n||
7
- h||o?{}:{reasoningTokens:0},...m||h?{complete:false}:{}},entradaAusente:m,salidaAusente:h}}function W(t,e){return e?(t??0)+e:t}function F(t){let e=t?.service_tier;return typeof e=="string"&&e!==""?e:void 0}
6
+ "number",h=typeof e!="number";return {usage:{inputTokens:d,outputTokens:g,...s!=null?{cachedInputTokens:s}:{},...a!=null?{cacheWriteInputTokens:a}:{},...l!==void 0?{cacheWrite1hInputTokens:l}:{},...n||
7
+ h||o?{}:{reasoningTokens:0},...m||h?{complete:false}:{}},entradaAusente:m,salidaAusente:h}}function F(t,e){return e?(t??0)+e:t}function B(t){let e=t?.service_tier;return typeof e=="string"&&e!==""?e:void 0}
8
8
  function q(t,e){let n=Object.fromEntries(Object.entries(e??{}).filter(([,o])=>o!=null)),r=t?.cache_creation||e?.cache_creation?{...t?.cache_creation??{},...e?.cache_creation??{}}:void 0;return {...t??{},
9
9
  ...n,...r?{cache_creation:r}:{}}}function V(t){return t==="thinking"||t==="redacted_thinking"}function G(t){switch(t){case "end_turn":return "stop";case "max_tokens":return "length";case "tool_use":return "\
10
- tool_calls";case "refusal":return "content_filter";default:return t}}var ye=new Set([null,"cyber","general_harms"]);function H(t){if(t.stopReason!=="refusal")return false;let e=t.stopDetails;if(e===null||typeof e!=
11
- "object"||Array.isArray(e))return false;let n=e;if(n.type!=="refusal"||!("category"in n))return false;let r=n.category;return !(r!==null&&typeof r!="string"||!ye.has(r)||t.bloques!==0||t.outputTokens!==0||Array.
12
- isArray(t.iterations)&&t.iterations.length>1)}var ve={"api.anthropic.com":"anthropic","api.openai.com":"openai","generativelanguage.googleapis.com":"google"};function be(t){if(typeof t!="string")return null;try{let e=new URL(t);return e.protocol!==
13
- "https:"||e.port!==""?null:ve[e.hostname.toLowerCase()]??null}catch{return null}}function K(t){return be(t)!==null?"oficial":"no-oficial"}var Z=Symbol.for("@bivelio/savings-layer:provider-origin");var L=class{decoder;resto="";crPendiente=false;alPrincipio=true;datos="";evento="";ultimoId;push(e){let n=typeof e=="string"?e:(this.decoder??=new TextDecoder("utf-8")).decode(e,{stream:true});return this.procesar(
10
+ tool_calls";case "refusal":return "content_filter";default:return t}}var be=new Set([null,"cyber","general_harms"]);function H(t){if(t.stopReason!=="refusal")return false;let e=t.stopDetails;if(e===null||typeof e!=
11
+ "object"||Array.isArray(e))return false;let n=e;if(n.type!=="refusal"||!("category"in n))return false;let r=n.category;return !(r!==null&&typeof r!="string"||!be.has(r)||t.bloques!==0||t.outputTokens!==0||Array.
12
+ isArray(t.iterations)&&t.iterations.length>1)}var Re=["claude-opus-5-5","claude-sonnet-5-5","claude-fable-5-1","claude-mythos-5-1"],we=["claude-opus-4-7","claude-opus-4-8","claude-opus-5","claude-sonnet-5","claude-fable-5","claude-mythos-5"];function Se(t){return /claude-[a-z]+-\d[a-z0-9-]*/.exec(t.toLowerCase())?.[0]}function K(t,e){let n=Se(t);return n===void 0?false:e.some(r=>n===r||n.startsWith(`${r}-`))}function Z(t){return K(t,Re)}function Q(t){
13
+ return K(t,we)}var xe={"api.anthropic.com":"anthropic","api.openai.com":"openai","generativelanguage.googleapis.com":"google"};function Ae(t){if(typeof t!="string")return null;try{let e=new URL(t);return e.protocol!==
14
+ "https:"||e.port!==""?null:xe[e.hostname.toLowerCase()]??null}catch{return null}}function X(t){return Ae(t)!==null?"oficial":"no-oficial"}var Y=Symbol.for("@bivelio/savings-layer:provider-origin");var O=class{decoder;resto="";crPendiente=false;alPrincipio=true;datos="";evento="";ultimoId;push(e){let n=typeof e=="string"?e:(this.decoder??=new TextDecoder("utf-8")).decode(e,{stream:true});return this.procesar(
14
15
  n)}end(){let e=[];if(this.decoder){let n=this.decoder.decode();n!==""&&e.push(...this.procesar(n));}return this.resto!==""&&(this.linea(this.resto,e),this.resto=""),this.despachar(e),this.crPendiente=false,
15
16
  e}procesar(e){let n=[];if(e==="")return n;let r=e;if(this.alPrincipio&&(this.alPrincipio=false,r.charCodeAt(0)===65279&&(r=r.slice(1)),r===""))return n;let o=0;this.crPendiente&&(this.crPendiente=false,r.charCodeAt(
16
17
  0)===10&&(o=1));let s=o;for(;o<r.length;){let a=r.charCodeAt(o);if(a!==10&&a!==13){o++;continue}this.linea(this.resto+r.slice(s,o),n),this.resto="",a===13&&(o+1<r.length?r.charCodeAt(o+1)===10&&o++:this.
17
18
  crPendiente=true),o++,s=o;}return this.resto+=r.slice(s),n}linea(e,n){if(e===""){this.despachar(n);return}if(e.charCodeAt(0)===58)return;let r=e.indexOf(":"),o,s;switch(r===-1?(o=e,s=""):(o=e.slice(0,r),
18
19
  s=e.slice(r+1),s.charCodeAt(0)===32&&(s=s.slice(1))),o){case "data":this.datos+=s+`
19
20
  `;break;case "event":this.evento=s;break;case "id":s.includes("\0")||(this.ultimoId=s);break;}}despachar(e){if(this.datos===""){this.evento="";return}e.push({event:this.evento===""?"message":
20
- this.evento,data:this.datos.slice(0,-1),...this.ultimoId!==void 0?{id:this.ultimoId}:{}}),this.datos="",this.evento="";}};var Q=new Set;function X(t,e,n){t===true||Q.has(e)||(Q.add(e),console.warn(n));}var Re="[bvsala] internal: the layer changed a request this adapter must forward unchanged; nothing was sent.",Se="[bvsala] internal: the layer asked for a second model call within one framework call;\
21
- nothing more was sent.",we="[bvsala] internal: the layer called the model outside a framework call; nothing was sent.";function U(t,e,n,r){return {renderizado:t,generar:e,...n?{transmitir:n}:{},invocada:false,
22
- completada:false,...r!==void 0?{origen:r}:{}}}function xe(t,e){if(t===e)return true;try{return stableStringify(t)===stableStringify(e)}catch{return false}}function ee(t,e){let n=t??[],r=e??[];return n.length===r.length&&n.every((o,s)=>xe(o,r[s]))}function Ae(t,e){return t.model===
23
- e.model&&ee(t.messages,e.messages)&&ee(t.tools,e.tools)}function te(t,e){let n=o=>{let s=e.getStore();if(!s)throw new Error(we);if(s.invocada)throw new Error(Se);if(!Ae(o,s.renderizado))throw new Error(
24
- Re);return s.invocada=true,s},r={id:`bivelio-adapter:${t}`,async generate(o,s){return n(o).generar(s?.signal)},async*generateStream(o,s){let a=n(o);if(a.transmitir){yield*a.transmitir(s?.signal);return}
25
- let i=await a.generar(s?.signal);i.text!==""&&(yield {type:"text",delta:i.text}),yield {type:"done",response:i};}};return Object.defineProperty(r,Z,{value:()=>e.getStore()?.origen}),r}function ne(){return new AsyncLocalStorage}var Ce=["licenseKey","licenseServerUrl","serviceAccountKey","licenseRefresh","licenseRevocation","licensePollIntervalSeconds","licenseFetch","metering","meteringUrl","meteringFetch","costModels","defa\
26
- ultCostModel","exactCache","exactCacheTtlMs","resolvers","exactTokenizer","silenceWarnings","failOpen"];function re(t,e){return e instanceof LicenseError||t.errorDelMarco&&t.errorDelMarco.error===e?false:t.invocada&&
27
- t.completada}var oe="[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 se(t,e){
28
- let n=ne(),r={};for(let a of Ce)e[a]!==void 0&&(r[a]=e[a]);let o=createSavingsLayer({...r,provider:te(t,n)}),s=(a,i)=>X(e.silenceWarnings,`${t}:${a}`,i);return {ejecutar(a,i){return n.run(i,()=>o.generate(a))},async generar(a,i){
29
- try{let u=await n.run(i,()=>o.generate(a));return i.invocada?{tipo:"vivo",result:u}:{tipo:"atajo",result:u}}catch(u){if(re(i,u))return s("sin-informe",oe),{tipo:"sin-informe"};throw u}},async transmitir(a,i,u){
30
- let g=n.run(i,()=>o.generateStream(a,u?{signal:u}:{})).result;i.resultado=g,g.catch(()=>{});let m;try{m=await Promise.race([i.abierta.then(()=>"abierta"),g.then(()=>"resuelta")]);}catch(_){if(re(i,_))return s(
31
- "sin-informe",oe),{tipo:"sin-informe"};throw _}if(m==="abierta")return {tipo:"abierto"};let h=await g;return i.invocada?{tipo:"entero",result:h}:{tipo:"atajo",result:h}},informe(a){let i=JSON.parse(JSON.
32
- stringify(a));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(){o.close();}}}function ae(){
21
+ this.evento,data:this.datos.slice(0,-1),...this.ultimoId!==void 0?{id:this.ultimoId}:{}}),this.datos="",this.evento="";}};var ee=new Set;function te(t,e,n){t===true||ee.has(e)||(ee.add(e),console.warn(n));}var De="[bvsala] internal: the layer changed a request this adapter must forward unchanged; nothing was sent.",Ce="[bvsala] internal: the layer asked for a second model call within one framework call;\
22
+ nothing more was sent.",Pe="[bvsala] internal: the layer called the model outside a framework call; nothing was sent.";function I(t,e,n,r){return {renderizado:t,generar:e,...n?{transmitir:n}:{},invocada:false,
23
+ completada:false,...r!==void 0?{origen:r}:{}}}function Oe(t,e){if(t===e)return true;try{return stableStringify(t)===stableStringify(e)}catch{return false}}function re(t,e){let n=t??[],r=e??[];return n.length===r.length&&n.every((o,s)=>Oe(o,r[s]))}function Te(t,e){return t.model===
24
+ e.model&&re(t.messages,e.messages)&&re(t.tools,e.tools)}function oe(t,e){let n=o=>{let s=e.getStore();if(!s)throw new Error(Pe);if(s.invocada)throw new Error(Ce);if(!Te(o,s.renderizado))throw new Error(
25
+ De);return s.invocada=true,s},r={id:`bivelio-adapter:${t}`,async generate(o,s){return n(o).generar(s?.signal)},async*generateStream(o,s){let a=n(o);if(a.transmitir){yield*a.transmitir(s?.signal);return}
26
+ let i=await a.generar(s?.signal);i.text!==""&&(yield {type:"text",delta:i.text}),yield {type:"done",response:i};}};return Object.defineProperty(r,Y,{value:()=>e.getStore()?.origen}),r}function se(){return new AsyncLocalStorage}var Le=["licenseKey","licenseServerUrl","serviceAccountKey","licenseRefresh","licenseRevocation","licensePollIntervalSeconds","licenseFetch","metering","meteringUrl","meteringFetch","costModels","defa\
27
+ ultCostModel","exactCache","exactCacheTtlMs","resolvers","exactTokenizer","silenceWarnings","failOpen"];function ae(t,e){return e instanceof LicenseError||t.errorDelMarco&&t.errorDelMarco.error===e?false:t.invocada&&
28
+ t.completada}var ie="[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 ce(t,e){
29
+ let n=se(),r={};for(let a of Le)e[a]!==void 0&&(r[a]=e[a]);let o=createSavingsLayer({...r,provider:oe(t,n)}),s=(a,i)=>te(e.silenceWarnings,`${t}:${a}`,i);return {ejecutar(a,i){return n.run(i,()=>o.generate(a))},async generar(a,i){
30
+ try{let l=await n.run(i,()=>o.generate(a));return i.invocada?{tipo:"vivo",result:l}:{tipo:"atajo",result:l}}catch(l){if(ae(i,l))return s("sin-informe",ie),{tipo:"sin-informe"};throw l}},async transmitir(a,i,l){
31
+ let g=n.run(i,()=>o.generateStream(a,l?{signal:l}:{})).result;i.resultado=g,g.catch(()=>{});let m;try{m=await Promise.race([i.abierta.then(()=>"abierta"),g.then(()=>"resuelta")]);}catch(b){if(ae(i,b))return s(
32
+ "sin-informe",ie),{tipo:"sin-informe"};throw b}if(m==="abierta")return {tipo:"abierto"};let h=await g;return i.invocada?{tipo:"entero",result:h}:{tipo:"atajo",result:h}},informe(a){let i=JSON.parse(JSON.
33
+ stringify(a));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(){o.close();}}}function le(){
33
34
  let t;return {abierta:new Promise(n=>{t=n;}),abrir:t}}var C=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.
34
35
  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||
35
36
  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](){
36
37
  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(
37
- (e,n)=>{this.esperando={resolver:e,rechazar:n};}),return:()=>(this.terminada=true,this.pendientes.length=0,Promise.resolve({value:void 0,done:true}))}}};var Le={router:false,compression:false,elision:false,serialization:false,toolDiscovery:false,modelCascade:"off",outputCodebook:false,deferrable:false,semanticCache:false,verification:false};
38
- function Me(t,e,n={}){let r=o=>t?.[o]!==false&&e?.[o]!==false;return {...Le,exactCache:r("exactCache")&&n.sinReutilizar!==true,singleflight:r("singleflight")&&n.sinReutilizar!==true,deterministicResolvers:r("det\
39
- erministicResolvers")&&n.sinResolvers!==true}}function Oe(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 ce(t,e){
40
- let n=e.delProveedor!==true&&Oe(t,e.nombre);return {id:e.nombre,intents:[],risk:n?"read":"write",...e.parametros!==void 0&&e.parametros!==null&&typeof e.parametros=="object"?{parameters:e.parametros}:{},
38
+ (e,n)=>{this.esperando={resolver:e,rechazar:n};}),return:()=>(this.terminada=true,this.pendientes.length=0,Promise.resolve({value:void 0,done:true}))}}};var qe={router:false,compression:false,elision:false,serialization:false,toolDiscovery:false,modelCascade:"off",outputCodebook:false,deferrable:false,semanticCache:false,verification:false};
39
+ function Ie(t,e,n={}){let r=o=>t?.[o]!==false&&e?.[o]!==false;return {...qe,exactCache:r("exactCache")&&n.sinReutilizar!==true,singleflight:r("singleflight")&&n.sinReutilizar!==true,deterministicResolvers:r("det\
40
+ erministicResolvers")&&n.sinResolvers!==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 de(t,e){
41
+ let n=e.delProveedor!==true&&Ue(t,e.nombre);return {id:e.nombre,intents:[],risk:n?"read":"write",...e.parametros!==void 0&&e.parametros!==null&&typeof e.parametros=="object"?{parameters:e.parametros}:{},
41
42
  ...typeof e.descripcion=="string"?{description:e.descripcion}:{}}}function P(t,e,n){if(t===null)return null;switch(typeof t){case "string":case "boolean":return t;case "number":return Number.isFinite(t)?
42
43
  t:String(t);case "bigint":return `${t.toString()}n`;case "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)
43
44
  return e.push(new Uint8Array(r)),{$bytes:e.length-1};if(ArrayBuffer.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};
44
45
  if(r instanceof Date)return {$date:Number.isNaN(r.getTime())?"invalid":r.toISOString()};if(n.has(r))return "$cycle";n.add(r);try{if(Array.isArray(r))return r.map(s=>{let a=P(s,e,n);return a===void 0?null:
45
46
  a});if(r instanceof Map)return {$map:[...r.entries()].map(s=>P(s,e,n))};if(r instanceof Set)return {$set:[...r.values()].map(s=>P(s,e,n))};let o={};for(let s of Object.keys(r).sort()){let a=P(r[s],e,n);
46
- a!==void 0&&(o[s]=a);}return o}finally{n.delete(r);}}async function ie(t){let e=globalThis.crypto?.subtle;if(e){let r=new Uint8Array(await e.digest("SHA-256",t));return Array.from(r,o=>o.toString(16).padStart(
47
- 2,"0")).join("")}let n="";for(let r=0;r<t.length;r+=32768)n+=String.fromCharCode(...t.subarray(r,r+32768));return sha256(n)}async function Te(t){try{let e=[],n=JSON.stringify(P(t,e,new WeakSet))??"null",r=await Promise.
48
- all(e.map(ie)),o=new TextEncoder().encode(`${n}|${r.join(",")}`);return await ie(o)}catch{return null}}async function ue(t,e){let n=await Te(e.proyeccion),r=`${e.context?.authorizationScope??"default"}\
47
+ a!==void 0&&(o[s]=a);}return o}finally{n.delete(r);}}async function ue(t){let e=globalThis.crypto?.subtle;if(e){let r=new Uint8Array(await e.digest("SHA-256",t));return Array.from(r,o=>o.toString(16).padStart(
48
+ 2,"0")).join("")}let n="";for(let r=0;r<t.length;r+=32768)n+=String.fromCharCode(...t.subarray(r,r+32768));return sha256(n)}async function ze(t){try{let e=[],n=JSON.stringify(P(t,e,new WeakSet))??"null",r=await Promise.
49
+ all(e.map(ue)),o=new TextEncoder().encode(`${n}|${r.join(",")}`);return await ue(o)}catch{return null}}async function pe(t,e){let n=await ze(e.proyeccion),r=`${e.context?.authorizationScope??"default"}\
49
50
  |bvsala-adapter:${n??"none"}`;return {model:e.model,messages:e.messages,...e.tools.length>0?{tools:e.tools}:{},...typeof e.temperature=="number"?{temperature:e.temperature}:{},...typeof e.seed=="number"?
50
- {seed:e.seed}:{},context:{...e.context??{},authorizationScope:r},savings:Me(t.savings,e.savings,{...e.restricciones,...n===null?{sinReutilizar:true}:{}})}}function le(t,e){if(!(!t&&!e))return {...t??{},...e??
51
- {}}}function de(t){if(!t||typeof t!="object")return {};let e=t,n={};return e.context&&typeof e.context=="object"&&(n.context=e.context),e.savings&&typeof e.savings=="object"&&(n.savings=e.savings),n}var I="[bvsala] could not read the request body; nothing was sent.";function p(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Ee(t){if((t.method??"GET").toUpperCase()!=="POST")return false;
52
- try{return new URL(t.url).pathname.replace(/\/+$/,"").endsWith("/v1/messages")}catch{return false}}function A(t){return typeof t=="string"?[{type:"text",text:t}]:Array.isArray(t)?t.filter(p):[]}function M(t){
51
+ {seed:e.seed}:{},context:{...e.context??{},authorizationScope:r},savings:Ie(t.savings,e.savings,{...e.restricciones,...n===null?{sinReutilizar:true}:{}})}}function fe(t,e){if(!(!t&&!e))return {...t??{},...e??
52
+ {}}}function ge(t){if(!t||typeof t!="object")return {};let e=t,n={};return e.context&&typeof e.context=="object"&&(n.context=e.context),e.savings&&typeof e.savings=="object"&&(n.savings=e.savings),n}var U="[bvsala] could not read the request body; nothing was sent.";function p(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Ne(t){if((t.method??"GET").toUpperCase()!=="POST")return false;
53
+ try{return new URL(t.url).pathname.replace(/\/+$/,"").endsWith("/v1/messages")}catch{return false}}function A(t){return typeof t=="string"?[{type:"text",text:t}]:Array.isArray(t)?t.filter(p):[]}function T(t){
53
54
  return t.filter(e=>e.type==="text"&&typeof e.text=="string").map(e=>e.text).join(`
54
- `)}function me(t){if(typeof t=="string")return t;try{return JSON.stringify(t??{})}catch{return "{}"}}function je(t){let e=[],n=t.system;(typeof n=="string"?n!=="":Array.isArray(n))&&e.push({role:"syste\
55
- m",content:typeof n=="string"?n:M(A(n))});for(let r of Array.isArray(t.messages)?t.messages:[]){if(!p(r))continue;let o=A(r.content);if(r.role==="assistant"){let a=o.filter(i=>i.type==="tool_use").map(
56
- i=>({...typeof i.id=="string"?{id:i.id}:{},name:String(i.name??""),arguments:me(i.input)}));e.push({role:"assistant",content:M(o),...a.length>0?{toolCalls:a}:{}});continue}for(let a of o)a.type==="too\
57
- l_result"&&e.push({role:"tool",content:typeof a.content=="string"?a.content:M(A(a.content)),...typeof a.tool_use_id=="string"?{toolCallId:a.tool_use_id}:{}});let s=M(o);(s!==""||!o.some(a=>a.type==="t\
58
- ool_result"))&&e.push({role:"user",content:s});}return e}function pe(t){let e={};for(let[n,r]of Object.entries(t))n==="id"||n==="tool_use_id"||n==="text"&&t.type==="text"||(e[n]=r);return e}function qe(t,e){
59
- let n={};for(let[r,o]of Object.entries(t))r==="stream"||r==="metadata"||r==="messages"||r==="system"||(n[r]=o);return n.system=typeof t.system=="string"?"$text":A(t.system).map(pe),n.messages=(Array.isArray(
60
- t.messages)?t.messages:[]).filter(p).map(r=>({role:r.role,content:A(r.content).map(pe)})),e&&(n["anthropic-beta"]=e),n}function Ue(t){let e=t.tool_choice;return p(e)&&(e.type==="any"||e.type==="tool")||
61
- p(t.output_config)&&t.output_config.format!==void 0?true:t.output_format!==void 0}var O=class{id;texto="";razono=false;reproducible=true;parada;detallesDeParada;bloquesVistos=0;usoInicio;usoDelta;vioDelta=false;vioStop=false;error;herramientas=new Map;toolCallsJson=[];bloque(e){
55
+ `)}function ve(t){if(typeof t=="string")return t;try{return JSON.stringify(t??{})}catch{return "{}"}}function Je(t){let e=[],n=t.system;(typeof n=="string"?n!=="":Array.isArray(n))&&e.push({role:"syste\
56
+ m",content:typeof n=="string"?n:T(A(n))});for(let r of Array.isArray(t.messages)?t.messages:[]){if(!p(r))continue;let o=A(r.content);if(r.role==="assistant"){let a=o.filter(i=>i.type==="tool_use").map(
57
+ i=>({...typeof i.id=="string"?{id:i.id}:{},name:String(i.name??""),arguments:ve(i.input)}));e.push({role:"assistant",content:T(o),...a.length>0?{toolCalls:a}:{}});continue}for(let a of o)a.type==="too\
58
+ l_result"&&e.push({role:"tool",content:typeof a.content=="string"?a.content:T(A(a.content)),...typeof a.tool_use_id=="string"?{toolCallId:a.tool_use_id}:{}});let s=T(o);(s!==""||!o.some(a=>a.type==="t\
59
+ ool_result"))&&e.push({role:"user",content:s});}return e}function me(t){let e={};for(let[n,r]of Object.entries(t))n==="id"||n==="tool_use_id"||n==="text"&&t.type==="text"||(e[n]=r);return e}function Fe(t,e){
60
+ let n={};for(let[r,o]of Object.entries(t))r==="stream"||r==="metadata"||r==="messages"||r==="system"||(n[r]=o);return n.system=typeof t.system=="string"?"$text":A(t.system).map(me),n.messages=(Array.isArray(
61
+ t.messages)?t.messages:[]).filter(p).map(r=>({role:r.role,content:A(r.content).map(me)})),e&&(n["anthropic-beta"]=e),n}function We(t){let e=t.tool_choice;return p(e)&&(e.type==="any"||e.type==="tool")||
62
+ p(t.output_config)&&t.output_config.format!==void 0?true:t.output_format!==void 0}function Be(t){let e=typeof t.model=="string"?t.model:"";if(e==="")return [];let n=[],r=t.tool_choice;p(r)&&(r.type==="an\
63
+ y"||r.type==="tool")&&Z(e)&&n.push({clave:`tool-choice-forzado:${e}`,mensaje:`[bvsala] Model "${e}" rejects a forced \`tool_choice\` (\`any\` or \`tool\`) with a 400, with or without thinking. This adapter \
64
+ forwards your request unchanged, so the API will reject it: use \`tool_choice: {type: "auto"}\` with \`strict: true\` tools, or \`output_config.format\` for a fixed JSON shape. See https://platform.claude.c\
65
+ om/docs/en/agents-and-tools/tool-use/define-tools#forcing-tool-use`});let o=["temperature","top_p","top_k"].filter(s=>typeof t[s]=="number"&&!(s==="temperature"&&t[s]===1));return o.length>0&&Q(e)&&n.
66
+ push({clave:`muestreo:${e}`,mensaje:`[bvsala] Model "${e}" rejects a non-default ${o.map(s=>`\`${s}\``).join(", ")} with a 400. This adapter forwards your request unchanged, so the API will reject it:\
67
+ drop the parameter for this model. See https://platform.claude.com/docs/en/models/sonnet-5-5/overview`}),n}var M=class{id;texto="";razono=false;reproducible=true;parada;detallesDeParada;bloquesVistos=0;usoInicio;usoDelta;vioDelta=false;vioStop=false;error;herramientas=new Map;toolCallsJson=[];bloque(e){
62
68
  this.bloquesVistos+=1,V(e.type)?(this.razono=true,this.reproducible=false):e.type==="text"?Array.isArray(e.citations)&&e.citations.length>0&&(this.reproducible=false):e.type!=="tool_use"&&(this.reproducible=false);}json(e){
63
69
  this.id=typeof e.id=="string"?e.id:void 0;for(let n of A(e.content))this.bloque(n),n.type==="text"&&typeof n.text=="string"&&(this.texto+=n.text),n.type==="tool_use"&&this.toolCallsJson.push({...typeof n.
64
- id=="string"?{id:n.id}:{},name:String(n.name??""),arguments:me(n.input)});this.parada=typeof e.stop_reason=="string"?e.stop_reason:void 0,this.detallesDeParada=e.stop_details,this.usoInicio=p(e.usage)?
70
+ id=="string"?{id:n.id}:{},name:String(n.name??""),arguments:ve(n.input)});this.parada=typeof e.stop_reason=="string"?e.stop_reason:void 0,this.detallesDeParada=e.stop_details,this.usoInicio=p(e.usage)?
65
71
  e.usage:void 0,this.usoDelta=this.usoInicio,this.vioDelta=true,this.vioStop=true;}evento(e){let n;try{n=JSON.parse(e.data);}catch{return}if(!p(n))return;switch(e.event!=="message"?e.event:String(n.type??e.event)){case "\
66
72
  message_start":{let o=p(n.message)?n.message:{};typeof o.id=="string"&&(this.id=o.id),p(o.usage)&&(this.usoInicio=o.usage);return}case "content_block_start":{let o=p(n.content_block)?n.content_block:{};
67
73
  this.bloque(o),o.type==="tool_use"&&typeof n.index=="number"&&this.herramientas.set(n.index,{...typeof o.id=="string"?{id:o.id}:{},name:String(o.name??""),json:""});return}case "content_block_delta":{let o=p(
@@ -69,36 +75,36 @@ n.delta)?n.delta:{};if(o.type==="text_delta"&&typeof o.text=="string")return thi
69
75
  "number"){let s=this.herramientas.get(n.index);s&&(s.json+=o.partial_json);}o.type==="citations_delta"&&(this.reproducible=false);return}case "message_delta":{this.vioDelta=true;let o=p(n.delta)?n.delta:{};typeof o.
70
76
  stop_reason=="string"&&(this.parada=o.stop_reason),"stop_details"in o&&(this.detallesDeParada=o.stop_details),p(n.usage)&&(this.usoDelta=q(this.usoDelta,n.usage));return}case "message_stop":this.vioStop=
71
77
  true;return;case "error":{let o=p(n.error)?n.error:{};this.error=`${String(o.type??"error")}: ${String(o.message??"")}`;return}default:return}}get toolCalls(){return this.toolCallsJson.length>0?this.toolCallsJson:
72
- [...this.herramientas.entries()].sort((e,n)=>e[0]-n[0]).map(([,e])=>({...e.id?{id:e.id}:{},name:e.name,arguments:Ie(e.json)})).filter(e=>e.name!=="")}respuesta(){let e=q(this.usoInicio,this.usoDelta),
73
- n=this.vioDelta?B(e,this.usoDelta?.output_tokens,this.razono).usage:{inputTokens:0,outputTokens:0,complete:false},r=e.iterations;Array.isArray(r)&&r.length>1&&(n.complete=false);let o=this.toolCalls,s=F(e);
78
+ [...this.herramientas.entries()].sort((e,n)=>e[0]-n[0]).map(([,e])=>({...e.id?{id:e.id}:{},name:e.name,arguments:Ve(e.json)})).filter(e=>e.name!=="")}respuesta(){let e=q(this.usoInicio,this.usoDelta),
79
+ n=this.vioDelta?W(e,this.usoDelta?.output_tokens,this.razono).usage:{inputTokens:0,outputTokens:0,complete:false},r=e.iterations;Array.isArray(r)&&r.length>1&&(n.complete=false);let o=this.toolCalls,s=B(e);
74
80
  return {text:this.texto,...o.length>0?{toolCalls:o}:{},...this.parada?{finishReason:G(this.parada)}:{},...this.vioDelta&&H({stopReason:this.parada,stopDetails:this.detallesDeParada,bloques:this.bloquesVistos,
75
- outputTokens:this.usoDelta?.output_tokens,iterations:r})?{unbilledRefusal:true}:{},...s?{servedServiceTier:s}:{},usage:n,...this.reproducible&&this.parada==="end_turn"?{}:{replayable:false}}}};function Ie(t){
76
- try{return JSON.stringify(JSON.parse(t===""?"{}":t))}catch{return t}}function ze(t,e){let n=[];return t.text!==""&&n.push({type:"text",text:t.text}),(t.toolCalls??[]).forEach((r,o)=>{let s={};try{s=JSON.
81
+ outputTokens:this.usoDelta?.output_tokens,iterations:r})?{unbilledRefusal:true}:{},...s?{servedServiceTier:s}:{},usage:n,...this.reproducible&&this.parada==="end_turn"?{}:{replayable:false}}}};function Ve(t){
82
+ try{return JSON.stringify(JSON.parse(t===""?"{}":t))}catch{return t}}function Ge(t,e){let n=[];return t.text!==""&&n.push({type:"text",text:t.text}),(t.toolCalls??[]).forEach((r,o)=>{let s={};try{s=JSON.
77
83
  parse(r.arguments||"{}");}catch{s={};}n.push({type:"tool_use",id:r.id??`toolu_bvsala_${t.requestId}_${o}`,name:r.name,input:s});}),{id:`msg_bvsala_${t.requestId}`,type:"message",role:"assistant",model:e,
78
- content:n,stop_reason:(t.toolCalls?.length??0)>0?"tool_use":"end_turn",stop_sequence:null,usage:{input_tokens:0,output_tokens:0}}}function fe(t,e,n){let r=ze(t,e),o={"request-id":`bvsala_${t.requestId}`};
79
- if(!n)return new Response(JSON.stringify(r),{status:200,headers:{...o,"content-type":"application/json"}});let s=(i,u)=>`event: ${i}
80
- data: ${JSON.stringify(u)}
84
+ content:n,stop_reason:(t.toolCalls?.length??0)>0?"tool_use":"end_turn",stop_sequence:null,usage:{input_tokens:0,output_tokens:0}}}function he(t,e,n){let r=Ge(t,e),o={"request-id":`bvsala_${t.requestId}`};
85
+ if(!n)return new Response(JSON.stringify(r),{status:200,headers:{...o,"content-type":"application/json"}});let s=(i,l)=>`event: ${i}
86
+ data: ${JSON.stringify(l)}
81
87
 
82
- `,a=s("message_start",{type:"message_start",message:{...r,content:[],stop_reason:null,stop_sequence:null}});return r.content.forEach((i,u)=>{i.type==="text"?(a+=s("content_block_start",{type:"content_\
83
- block_start",index:u,content_block:{type:"text",text:""}}),a+=s("content_block_delta",{type:"content_block_delta",index:u,delta:{type:"text_delta",text:i.text}})):(a+=s("content_block_start",{type:"co\
84
- ntent_block_start",index:u,content_block:{type:"tool_use",id:i.id,name:i.name,input:{}}}),a+=s("content_block_delta",{type:"content_block_delta",index:u,delta:{type:"input_json_delta",partial_json:JSON.
85
- stringify(i.input)}})),a+=s("content_block_stop",{type:"content_block_stop",index:u});}),a+=s("message_delta",{type:"message_delta",delta:{stop_reason:r.stop_reason,stop_sequence:null},usage:{output_tokens:0}}),
86
- a+=s("message_stop",{type:"message_stop"}),new Response(a,{status:200,headers:{...o,"content-type":"text/event-stream"}})}var T=class extends Error{constructor(n){super(`[bvsala] provider responded ${n.
87
- status}`);this.respuesta=n;}respuesta};function lt(t){let e=se("anthropic-sdk",t),n=Math.max(1,Math.floor(t.reportCacheSize??1e3)),r=new Map,o=(a,i)=>{if(a)for(r.delete(a),r.set(a,i);r.size>n;)r.delete(
88
- r.keys().next().value);};return {middleware:async(a,i,u)=>{if(!Ee(a))return i(a);if(typeof a.body!="string")throw new Error(I);let d;try{let c=JSON.parse(a.body);if(!p(c))throw new Error(I);d=c;}catch{throw new Error(
89
- I)}let g=u.options,m=de(g?.bivelio),h=t.context?.({body:d,requestOptions:g}),_=(Array.isArray(d.tools)?d.tools:[]).filter(p).map(c=>ce(t,{nombre:String(c.name??""),descripcion:typeof c.description=="s\
90
- tring"?c.description:void 0,parametros:c.input_schema,delProveedor:c.input_schema===void 0&&typeof c.type=="string"&&c.type!=="custom"})),l=await ue(t,{model:`anthropic/${String(d.model??"")}`,messages:je(
91
- d),tools:_,temperature:typeof d.temperature=="number"?d.temperature:void 0,context:le(h,m.context),savings:m.savings,proyeccion:qe(d,a.headers.get("anthropic-beta")),restricciones:{sinResolvers:Ue(d)}}),
92
- v={model:l.model,messages:l.messages,...l.tools?{tools:l.tools}:{}},b=K(a.url),R=async c=>{let f;try{f=await i(a);}catch(y){throw c.errorDelMarco={error:y},y}if(!f.ok){let y=new T(f);throw c.errorDelMarco=
93
- {error:y},y}return c.completada=true,f},z=c=>{if(c instanceof T)return c.respuesta;throw c};if(d.stream!==true){let c,f,y=U(v,async()=>{c=await R(y);let D=new O;return D.json(await c.clone().json()),f=D.id,
94
- D.respuesta()},void 0,b),w;try{w=await e.generar(l,y);}catch(D){return z(D)}if(w.tipo==="sin-informe")return c;let N=e.informe(w.result.report);return w.tipo==="atajo"?(o(`msg_bvsala_${w.result.requestId}`,
95
- N),fe(w.result,d.model,false)):(o(f,N),c)}let{abierta:he,abrir:$}=ae(),E,j,k=Object.assign(U(v,async()=>{let c=await R(k),f=new C;j=ge(c,f,e,k,o),$();for await(let y of f)if(y.type==="done")return y.response;
96
- throw new Error("[bvsala] the model stream ended before completion; nothing was measured.")},()=>{let c=new C;return R(k).then(f=>{E=ge(f,c,e,k,o),$();},f=>c.fail(f)),c},b),{abierta:he}),S;try{S=await e.
97
- transmitir(l,k,a.signal??void 0);}catch(c){return z(c)}if(S.tipo==="abierto")return E??j;if(S.tipo==="atajo"){let c=e.informe(S.result.report);return o(`msg_bvsala_${S.result.requestId}`,c),fe(S.result,
98
- d.model,true)}return E??j},reportFor(a){let i=typeof a=="string"?a:a?.id;return typeof i=="string"?r.get(i):void 0},close(){e.close();}}}function ge(t,e,n,r,o){let s=new O,a,i=async()=>{try{let l=await r.
99
- resultado;o(s.id,n.informe(l.report));}catch{}},u=()=>{e.cerrada||(s.error?e.fail(new Error(`[bvsala] provider stream error: ${s.error}`)):s.vioDelta||s.vioStop?(e.push({type:"done",response:s.respuesta()}),
100
- e.end(),a=i()):e.fail(new Error("[bvsala] the model stream ended before completion; nothing was measured.")));};if((t.headers.get("content-type")??"").includes("application/json"))return t.clone().json().
101
- then(l=>{s.json(p(l)?l:{}),s.texto!==""&&e.push({type:"text",delta:s.texto}),u();},l=>e.fail(l)),t;let d=t.body;if(!d)return e.fail(new Error("[bvsala] the model stream had no body; nothing was measure\
102
- d.")),t;let g=d.getReader(),m=new L,h=l=>{for(let v of l){let b=s.evento(v);b!==void 0&&e.push({type:"text",delta:b}),(s.vioStop||s.error)&&u();}},_=new ReadableStream({async pull(l){let v;try{v=await g.
103
- read();}catch(R){e.fail(R),l.error(R);return}if(v.done){h(m.end()),u(),await a,l.close();return}let b=v.value;l.enqueue(b),h(m.push(b));},cancel(l){return e.fail(new Error("[bvsala] the stream was cance\
104
- lled by its reader; nothing was measured.")),g.cancel(l)}});return new Response(_,{status:t.status,statusText:t.statusText,headers:t.headers})}export{lt as anthropicSavings};
88
+ `,a=s("message_start",{type:"message_start",message:{...r,content:[],stop_reason:null,stop_sequence:null}});return r.content.forEach((i,l)=>{i.type==="text"?(a+=s("content_block_start",{type:"content_\
89
+ block_start",index:l,content_block:{type:"text",text:""}}),a+=s("content_block_delta",{type:"content_block_delta",index:l,delta:{type:"text_delta",text:i.text}})):(a+=s("content_block_start",{type:"co\
90
+ ntent_block_start",index:l,content_block:{type:"tool_use",id:i.id,name:i.name,input:{}}}),a+=s("content_block_delta",{type:"content_block_delta",index:l,delta:{type:"input_json_delta",partial_json:JSON.
91
+ stringify(i.input)}})),a+=s("content_block_stop",{type:"content_block_stop",index:l});}),a+=s("message_delta",{type:"message_delta",delta:{stop_reason:r.stop_reason,stop_sequence:null},usage:{output_tokens:0}}),
92
+ a+=s("message_stop",{type:"message_stop"}),new Response(a,{status:200,headers:{...o,"content-type":"text/event-stream"}})}var E=class extends Error{constructor(n){super(`[bvsala] provider responded ${n.
93
+ status}`);this.respuesta=n;}respuesta};function bt(t){let e=ce("anthropic-sdk",t),n=Math.max(1,Math.floor(t.reportCacheSize??1e3)),r=new Map,o=(a,i)=>{if(a)for(r.delete(a),r.set(a,i);r.size>n;)r.delete(
94
+ r.keys().next().value);};return {middleware:async(a,i,l)=>{if(!Ne(a))return i(a);if(typeof a.body!="string")throw new Error(U);let d;try{let c=JSON.parse(a.body);if(!p(c))throw new Error(U);d=c;}catch{throw new Error(
95
+ U)}for(let c of Be(d))e.avisar(c.clave,c.mensaje);let g=l.options,m=ge(g?.bivelio),h=t.context?.({body:d,requestOptions:g}),b=(Array.isArray(d.tools)?d.tools:[]).filter(p).map(c=>de(t,{nombre:String(c.
96
+ name??""),descripcion:typeof c.description=="string"?c.description:void 0,parametros:c.input_schema,delProveedor:c.input_schema===void 0&&typeof c.type=="string"&&c.type!=="custom"})),u=await pe(t,{model:`\
97
+ anthropic/${String(d.model??"")}`,messages:Je(d),tools:b,temperature:typeof d.temperature=="number"?d.temperature:void 0,context:fe(h,m.context),savings:m.savings,proyeccion:Fe(d,a.headers.get("anthro\
98
+ pic-beta")),restricciones:{sinResolvers:We(d)}}),v={model:u.model,messages:u.messages,...u.tools?{tools:u.tools}:{}},_=X(a.url),R=async c=>{let f;try{f=await i(a);}catch(y){throw c.errorDelMarco={error:y},
99
+ y}if(!f.ok){let y=new E(f);throw c.errorDelMarco={error:y},y}return c.completada=true,f},z=c=>{if(c instanceof E)return c.respuesta;throw c};if(d.stream!==true){let c,f,y=I(v,async()=>{c=await R(y);let D=new M;
100
+ return D.json(await c.clone().json()),f=D.id,D.respuesta()},void 0,_),S;try{S=await e.generar(u,y);}catch(D){return z(D)}if(S.tipo==="sin-informe")return c;let N=e.informe(S.result.report);return S.tipo===
101
+ "atajo"?(o(`msg_bvsala_${S.result.requestId}`,N),he(S.result,d.model,false)):(o(f,N),c)}let{abierta:_e,abrir:$}=le(),L,j,k=Object.assign(I(v,async()=>{let c=await R(k),f=new C;j=ye(c,f,e,k,o),$();for await(let y of f)
102
+ if(y.type==="done")return y.response;throw new Error("[bvsala] the model stream ended before completion; nothing was measured.")},()=>{let c=new C;return R(k).then(f=>{L=ye(f,c,e,k,o),$();},f=>c.fail(f)),
103
+ c},_),{abierta:_e}),w;try{w=await e.transmitir(u,k,a.signal??void 0);}catch(c){return z(c)}if(w.tipo==="abierto")return L??j;if(w.tipo==="atajo"){let c=e.informe(w.result.report);return o(`msg_bvsala_${w.
104
+ result.requestId}`,c),he(w.result,d.model,true)}return L??j},reportFor(a){let i=typeof a=="string"?a:a?.id;return typeof i=="string"?r.get(i):void 0},close(){e.close();}}}function ye(t,e,n,r,o){let s=new M,
105
+ a,i=async()=>{try{let u=await r.resultado;o(s.id,n.informe(u.report));}catch{}},l=()=>{e.cerrada||(s.error?e.fail(new Error(`[bvsala] provider stream error: ${s.error}`)):s.vioDelta||s.vioStop?(e.push(
106
+ {type:"done",response:s.respuesta()}),e.end(),a=i()):e.fail(new Error("[bvsala] the model stream ended before completion; nothing was measured.")));};if((t.headers.get("content-type")??"").includes("ap\
107
+ plication/json"))return t.clone().json().then(u=>{s.json(p(u)?u:{}),s.texto!==""&&e.push({type:"text",delta:s.texto}),l();},u=>e.fail(u)),t;let d=t.body;if(!d)return e.fail(new Error("[bvsala] the mode\
108
+ l stream had no body; nothing was measured.")),t;let g=d.getReader(),m=new O,h=u=>{for(let v of u){let _=s.evento(v);_!==void 0&&e.push({type:"text",delta:_}),(s.vioStop||s.error)&&l();}},b=new ReadableStream(
109
+ {async pull(u){let v;try{v=await g.read();}catch(R){e.fail(R),u.error(R);return}if(v.done){h(m.end()),l(),await a,u.close();return}let _=v.value;u.enqueue(_),h(m.push(_));},cancel(u){return e.fail(new Error(
110
+ "[bvsala] the stream was cancelled by its reader; nothing was measured.")),g.cancel(u)}});return new Response(b,{status:t.status,statusText:t.statusText,headers:t.headers})}export{bt as anthropicSavings};