@bivelio/savings-layer 0.4.31 → 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 +117 -12
- package/dist/adapters/anthropic-sdk.js +75 -69
- package/dist/gateway/bin.js +846 -725
- package/dist/index.d.ts +101 -6
- package/dist/index.js +1552 -1387
- package/package.json +6 -2
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
|
|
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,
|
|
@@ -286,16 +287,41 @@ Most refusals carry no signal from the API: the model writes "I can't help with
|
|
|
286
287
|
as ordinary text and ends with `end_turn` or `stop`. The layer also looks for these,
|
|
287
288
|
with a conservative text heuristic. It checks only the opening of the answer, or the
|
|
288
289
|
whole answer when it is short, and it needs a real refusal clause, such as "I'm sorry,
|
|
289
|
-
but I can't help with that", "I cannot assist" or "As an AI, I
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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.
|
|
299
325
|
|
|
300
326
|
**Streaming.** `generateStream()` takes the same request and hands you the answer as
|
|
301
327
|
the provider writes it, then the same `SavingsReport`:
|
|
@@ -453,6 +479,45 @@ It runs once per HTTP attempt, inside the SDK's retries: an attempt the provider
|
|
|
453
479
|
rejects reaches the SDK unchanged and is not recorded. Only message creation goes
|
|
454
480
|
through the layer; `countTokens`, batches, models and files pass untouched.
|
|
455
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
|
+
|
|
456
521
|
## What you get on every request
|
|
457
522
|
|
|
458
523
|
A `SavingsReport` with the numbers behind every claim, kept in **four separate
|
|
@@ -681,7 +746,16 @@ const agentLayer = createSavingsLayer({
|
|
|
681
746
|
|
|
682
747
|
By default the layer writes the provider's prompt cache at two fixed places: the end
|
|
683
748
|
of the system header and the end of the history before your last user message, and
|
|
684
|
-
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.
|
|
685
759
|
|
|
686
760
|
`cacheBreakpoints: "auto"` places them from what your traffic actually does. The layer
|
|
687
761
|
compares each request's prefix with the ones it sent before, per model, tool set and
|
|
@@ -846,6 +920,25 @@ request is repeated once with the other one (nothing was generated, so nothing i
|
|
|
846
920
|
billed twice) and the model is remembered. To choose the field yourself:
|
|
847
921
|
`new OpenAICompatibleProvider({ baseUrl, maxTokensParam: "max_completion_tokens" })`.
|
|
848
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
|
+
|
|
849
942
|
The cap is yours, not a saving: it is never credited as output avoided. An answer
|
|
850
943
|
it cut (`finishReason: "length"`) is not cached, and
|
|
851
944
|
`report.qualityLedger.truncation` says the limit was yours.
|
|
@@ -904,6 +997,18 @@ console.log(res.text);
|
|
|
904
997
|
the SDK warns once.
|
|
905
998
|
- **Errors.** When a tool fails, put the error in `content` and set `isError: true`.
|
|
906
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`.
|
|
907
1012
|
|
|
908
1013
|
A tool‑call turn is never served from cache and never counted as an avoided call:
|
|
909
1014
|
an action that has not run yet cannot be a saving. The answer that follows a tool loop
|
|
@@ -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
|
|
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}:{},...
|
|
7
|
-
h||o?{}:{reasoningTokens:0},...m||h?{complete:false}:{}},entradaAusente:m,salidaAusente:h}}function
|
|
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
|
|
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"||!
|
|
12
|
-
isArray(t.iterations)&&t.iterations.length>1)}var
|
|
13
|
-
|
|
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
|
|
21
|
-
nothing more was sent.",
|
|
22
|
-
completada:false,...r!==void 0?{origen:r}:{}}}function
|
|
23
|
-
e.model&&
|
|
24
|
-
|
|
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,
|
|
26
|
-
ultCostModel","exactCache","exactCacheTtlMs","resolvers","exactTokenizer","silenceWarnings","failOpen"];function
|
|
27
|
-
t.completada}var
|
|
28
|
-
let n=
|
|
29
|
-
try{let
|
|
30
|
-
let g=n.run(i,()=>o.generateStream(a,
|
|
31
|
-
"sin-informe",
|
|
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
|
|
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
|
|
38
|
-
function
|
|
39
|
-
erministicResolvers")&&n.sinResolvers!==true}}function
|
|
40
|
-
let n=e.delProveedor!==true&&
|
|
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
|
|
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
|
|
48
|
-
all(e.map(
|
|
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:
|
|
51
|
-
{}}}function
|
|
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
|
|
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
|
|
55
|
-
m",content:typeof n=="string"?n:
|
|
56
|
-
i=>({...typeof i.id=="string"?{id:i.id}:{},name:String(i.name??""),arguments:
|
|
57
|
-
l_result"&&e.push({role:"tool",content:typeof a.content=="string"?a.content:
|
|
58
|
-
ool_result"))&&e.push({role:"user",content:s});}return e}function
|
|
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(
|
|
60
|
-
t.messages)?t.messages:[]).filter(p).map(r=>({role:r.role,content:A(r.content).map(
|
|
61
|
-
p(t.output_config)&&t.output_config.format!==void 0?true:t.output_format!==void 0}
|
|
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:
|
|
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:
|
|
73
|
-
n=this.vioDelta?
|
|
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
|
|
76
|
-
try{return JSON.stringify(JSON.parse(t===""?"{}":t))}catch{return t}}function
|
|
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
|
|
79
|
-
if(!n)return new Response(JSON.stringify(r),{status:200,headers:{...o,"content-type":"application/json"}});let s=(i,
|
|
80
|
-
data: ${JSON.stringify(
|
|
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,
|
|
83
|
-
block_start",index:
|
|
84
|
-
ntent_block_start",index:
|
|
85
|
-
stringify(i.input)}})),a+=s("content_block_stop",{type:"content_block_stop",index:
|
|
86
|
-
a+=s("message_stop",{type:"message_stop"}),new Response(a,{status:200,headers:{...o,"content-type":"text/event-stream"}})}var
|
|
87
|
-
status}`);this.respuesta=n;}respuesta};function
|
|
88
|
-
r.keys().next().value);};return {middleware:async(a,i,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
d),tools:
|
|
92
|
-
v={model:
|
|
93
|
-
{error:y},y}return c.completada=true,f},z=c=>{if(c instanceof
|
|
94
|
-
D.respuesta()},void 0,
|
|
95
|
-
N),
|
|
96
|
-
throw new Error("[bvsala] the model stream ended before completion; nothing was measured.")},()=>{let c=new C;return R(k).then(f=>{
|
|
97
|
-
transmitir(
|
|
98
|
-
d.model,true)}return
|
|
99
|
-
resultado;o(s.id,n.informe(
|
|
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("
|
|
101
|
-
then(
|
|
102
|
-
|
|
103
|
-
read();}catch(R){e.fail(R),
|
|
104
|
-
|
|
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};
|