@anvaka/vue-llm 0.3.0 → 0.3.2
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 +17 -0
- package/dist/core/LLMClient.js +21 -18
- package/dist/pricing/rates.js +45 -35
- package/dist/providers/AnthropicProvider.js +140 -91
- package/dist/providers/BedrockProvider.js +103 -79
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Browser-only LLM client + Vue 3 plugin, provider adapters, and lightweight compo
|
|
|
7
7
|
- LocalStorage-based config store (custom storage adapter supported)
|
|
8
8
|
- Streaming + promise requests via `llmClient.stream()`
|
|
9
9
|
- Normalized usage + USD cost on every response (override built-in rates per app or per model)
|
|
10
|
+
- Automatic prompt caching for Claude (Anthropic + Bedrock) — caches the system+tools prefix, plus the rolling conversation in agent loops; opt out with `promptCache: false`
|
|
10
11
|
- Vue plugin for dependency injection
|
|
11
12
|
- `useLLM()` composable with reactive streaming state
|
|
12
13
|
- Ready-to-use components: `ProviderSelector`, `LLMConfigModal`, `StoredKeysManager`
|
|
@@ -157,6 +158,22 @@ const { messages, usage, cost } = await client.runAgentLoop({
|
|
|
157
158
|
})
|
|
158
159
|
```
|
|
159
160
|
|
|
161
|
+
### Prompt caching (Claude)
|
|
162
|
+
|
|
163
|
+
Anthropic and Bedrock requests are sent with `cache_control` markers by default, so repeated prefixes are read from cache instead of re-billed at full input price. Two prefixes are tagged:
|
|
164
|
+
|
|
165
|
+
- **System + tools** — on every Claude request. The static prefix recurs identically across calls and runs within the cache TTL (~5 min).
|
|
166
|
+
- **Rolling conversation** — added by `runAgentLoop` only, since it re-sends the whole growing transcript each turn. Iteration *N* reads iterations `1..N-1` from cache and only writes the new turn.
|
|
167
|
+
|
|
168
|
+
Cache hits and writes surface in the usual `usage` fields (`cachedInputTokens`, `cacheCreationInputTokens`) and are priced via the `cachedInput` / `cacheCreation` rate keys. No setup is required — prefixes under the model's minimum cacheable length simply aren't cached (no error).
|
|
169
|
+
|
|
170
|
+
Disable it per call or per provider config:
|
|
171
|
+
|
|
172
|
+
```js
|
|
173
|
+
client.stream({ messages: [...], promptCache: false }) // single request
|
|
174
|
+
configStore.saveConfig('claude', { ...cfg, promptCache: false }) // all requests for this provider
|
|
175
|
+
```
|
|
176
|
+
|
|
160
177
|
### Overriding rates
|
|
161
178
|
|
|
162
179
|
Built-in rates are sourced from public pricing pages and *will* drift. Three ways to override, in priority order:
|
package/dist/core/LLMClient.js
CHANGED
|
@@ -120,16 +120,16 @@ class P {
|
|
|
120
120
|
temperature: n,
|
|
121
121
|
model: o,
|
|
122
122
|
maxTokens: l,
|
|
123
|
-
enableThinking:
|
|
123
|
+
enableThinking: d
|
|
124
124
|
} = {}) {
|
|
125
125
|
if (await this.ensureInitialized(), !this.provider.hasCapability("tools"))
|
|
126
126
|
throw new Error("Configured provider does not support tools");
|
|
127
127
|
const c = t.slice();
|
|
128
|
-
let
|
|
128
|
+
let p = 0, m = null;
|
|
129
129
|
const f = { inputTokens: 0, outputTokens: 0, totalTokens: 0, cachedInputTokens: 0, cacheCreationInputTokens: 0, reasoningTokens: 0 };
|
|
130
130
|
let b = !1;
|
|
131
|
-
for (;
|
|
132
|
-
|
|
131
|
+
for (; p < e; ) {
|
|
132
|
+
p++, r && r({ type: "iter-start", iter: p });
|
|
133
133
|
const x = this.validateCapabilities({
|
|
134
134
|
messages: c,
|
|
135
135
|
tools: s,
|
|
@@ -137,7 +137,10 @@ class P {
|
|
|
137
137
|
model: o || this.config.model,
|
|
138
138
|
temperature: n ?? this.config.temperature,
|
|
139
139
|
maxTokens: l ?? this.config.maxTokens ?? 4096,
|
|
140
|
-
enableThinking:
|
|
140
|
+
enableThinking: d ?? !1,
|
|
141
|
+
// Re-sends the whole growing conversation each turn, so cache the
|
|
142
|
+
// rolling transcript prefix (Anthropic-family providers honor this).
|
|
143
|
+
cacheTranscript: !0,
|
|
141
144
|
requestId: this.generateRequestId()
|
|
142
145
|
}), h = await this.provider.streamRequest(c, x, (a) => {
|
|
143
146
|
a.content && r && r({ type: "text-delta", text: a.content }), a.toolCallDelta && r && r({ type: "tool-call-delta", delta: a.toolCallDelta });
|
|
@@ -171,7 +174,7 @@ class P {
|
|
|
171
174
|
}
|
|
172
175
|
m || (m = "max-iters");
|
|
173
176
|
const g = b ? f : null, v = this.costFor(g, { provider: this.config.provider, model: o || this.config.model });
|
|
174
|
-
return r && r({ type: "stop", reason: m, iterations:
|
|
177
|
+
return r && r({ type: "stop", reason: m, iterations: p, usage: g, cost: v }), { messages: c, iterations: p, stopReason: m, usage: g, cost: v };
|
|
175
178
|
}
|
|
176
179
|
generateRequestId() {
|
|
177
180
|
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -256,8 +259,8 @@ class $ {
|
|
|
256
259
|
};
|
|
257
260
|
try {
|
|
258
261
|
if (this.targetNode) {
|
|
259
|
-
const
|
|
260
|
-
return await this._streamIntoTarget(e,
|
|
262
|
+
const d = r({ ...n, stream: !0 });
|
|
263
|
+
return await this._streamIntoTarget(e, d, s, i);
|
|
261
264
|
}
|
|
262
265
|
const l = r({ ...n, stream: !1 });
|
|
263
266
|
return await this._promiseResponse(e, l, s, i);
|
|
@@ -275,8 +278,8 @@ class $ {
|
|
|
275
278
|
throw new Error("Provider presets require a configured ConfigStore instance");
|
|
276
279
|
const s = (e = (r = this.client).getConfigByName) == null ? void 0 : e.call(r, t);
|
|
277
280
|
if (!s) {
|
|
278
|
-
const l = (((o = (n = this.client.configStore).getEnabledConfigs) == null ? void 0 : o.call(n)) || []).map((c) => c.name || `${c.provider} (${c.baseUrl})`).filter(Boolean),
|
|
279
|
-
throw new Error(`Provider preset '${t}' not found.${
|
|
281
|
+
const l = (((o = (n = this.client.configStore).getEnabledConfigs) == null ? void 0 : o.call(n)) || []).map((c) => c.name || `${c.provider} (${c.baseUrl})`).filter(Boolean), d = l.length ? ` Available presets: ${l.join(", ")}` : " No configured providers found.";
|
|
282
|
+
throw new Error(`Provider preset '${t}' not found.${d}`);
|
|
280
283
|
}
|
|
281
284
|
const i = U(s.provider, s);
|
|
282
285
|
return await i.initialize(), { provider: i, config: s, cleanup: () => {
|
|
@@ -298,9 +301,9 @@ class $ {
|
|
|
298
301
|
}
|
|
299
302
|
}
|
|
300
303
|
async _streamIntoTarget(t, s, i, r) {
|
|
301
|
-
var
|
|
304
|
+
var p, m, f, b, g, v, x, h, q, y, C, w, k, a, R, T;
|
|
302
305
|
let e, n;
|
|
303
|
-
typeof this.targetNode == "string" ? (n = this.targetNode, e = this.contextNode.createChild(n), (
|
|
306
|
+
typeof this.targetNode == "string" ? (n = this.targetNode, e = this.contextNode.createChild(n), (p = e.setSelected) == null || p.call(e)) : (e = this.targetNode, n = ((m = e.getText) == null ? void 0 : m.call(e)) || ""), this._applyAttributes(e);
|
|
304
307
|
const o = r == null ? void 0 : r.name;
|
|
305
308
|
o && e.addTag && e.addTag("provider", o), (f = e.addLLMLog) == null || f.call(e, this.operationName || "streaming-request", {
|
|
306
309
|
provider: r == null ? void 0 : r.provider,
|
|
@@ -308,26 +311,26 @@ class $ {
|
|
|
308
311
|
messages: t,
|
|
309
312
|
options: s
|
|
310
313
|
}), (b = e.setStreamingState) == null || b.call(e, !0), e._activeRequestId = s.requestId;
|
|
311
|
-
let l = "",
|
|
314
|
+
let l = "", d = null, c = null;
|
|
312
315
|
try {
|
|
313
316
|
await i.streamRequest(t, s, (_) => {
|
|
314
317
|
var I, S;
|
|
315
|
-
_.content && (l = _.fullContent, (I = e.setText) == null || I.call(e, l)), _.fullUsage && (c = _.fullUsage), _.finishReason && (
|
|
318
|
+
_.content && (l = _.fullContent, (I = e.setText) == null || I.call(e, l)), _.fullUsage && (c = _.fullUsage), _.finishReason && (d = _.finishReason), _.done && ((S = e.setStreamingState) == null || S.call(e, !1), e._activeRequestId = null);
|
|
316
319
|
});
|
|
317
320
|
const u = (v = (g = this.client).costFor) == null ? void 0 : v.call(g, c, { provider: r == null ? void 0 : r.provider, model: s.model });
|
|
318
|
-
return (x = e.addLLMLog) == null || x.call(e, (this.operationName || "streaming-request") + "-response", { requestId: s.requestId }, { content: l, usage: c, cost: u }),
|
|
321
|
+
return (x = e.addLLMLog) == null || x.call(e, (this.operationName || "streaming-request") + "-response", { requestId: s.requestId }, { content: l, usage: c, cost: u }), d === "length" ? ((h = e.setAttribute) == null || h.call(e, "_truncated", !0), (q = e.addLog) == null || q.call(e, "Response truncated. Increase Max Tokens.", "warn", { finish_reason: "length" })) : (y = e.setAttribute) == null || y.call(e, "_truncated", !1), await ((C = e.persistNow) == null ? void 0 : C.call(e)), e;
|
|
319
322
|
} catch (u) {
|
|
320
323
|
throw (w = e.addLLMLog) == null || w.call(e, (this.operationName || "streaming-request") + "-error", { requestId: s.requestId }, null, u), (k = e.setStreamingState) == null || k.call(e, !1), e._activeRequestId = null, (a = e.setText) == null || a.call(e, `Error: ${u.message}`), (R = e.setAttribute) == null || R.call(e, "_truncated", !1), await ((T = e.persistNow) == null ? void 0 : T.call(e)), u;
|
|
321
324
|
}
|
|
322
325
|
}
|
|
323
326
|
async _promiseResponse(t, s, i, r) {
|
|
324
|
-
var
|
|
327
|
+
var d, c, p, m, f, b, g;
|
|
325
328
|
const e = i.prepareRequest(t, s), n = await i.makeRequest(e), o = i.processResponse(n);
|
|
326
|
-
if ((o.finishReason || ((c = (
|
|
329
|
+
if ((o.finishReason || ((c = (d = n == null ? void 0 : n.choices) == null ? void 0 : d[0]) == null ? void 0 : c.finish_reason) || null) === "length")
|
|
327
330
|
try {
|
|
328
331
|
this.contextNode.setAttribute("_truncated", !0);
|
|
329
332
|
} catch (v) {
|
|
330
|
-
(m = (
|
|
333
|
+
(m = (p = this.client.logger) == null ? void 0 : p.warn) == null || m.call(p, "Unable to mark node as truncated", { error: v });
|
|
331
334
|
}
|
|
332
335
|
else
|
|
333
336
|
try {
|
package/dist/pricing/rates.js
CHANGED
|
@@ -1,69 +1,79 @@
|
|
|
1
1
|
const t = {
|
|
2
2
|
openai: {
|
|
3
|
-
|
|
4
|
-
"gpt-5-
|
|
5
|
-
"gpt-5
|
|
3
|
+
// Flagship + workhorse (April–May 2026 lineup)
|
|
4
|
+
"gpt-5.5-pro": { input: 5, output: 30, cachedInput: 0.5 },
|
|
5
|
+
"gpt-5.5": { input: 5, output: 30, cachedInput: 0.5 },
|
|
6
|
+
"gpt-5.4-pro": { input: 30, output: 180 },
|
|
6
7
|
"gpt-5.4": { input: 2.5, output: 15, cachedInput: 0.25 },
|
|
7
8
|
"gpt-5.4-mini": { input: 0.75, output: 4.5, cachedInput: 0.075 },
|
|
8
9
|
"gpt-5.4-nano": { input: 0.2, output: 1.25, cachedInput: 0.02 },
|
|
9
|
-
|
|
10
|
-
"gpt-
|
|
11
|
-
"gpt-
|
|
12
|
-
"gpt-
|
|
13
|
-
"gpt-
|
|
14
|
-
"gpt-
|
|
15
|
-
"gpt-
|
|
16
|
-
"gpt-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
// GPT-5.x family — still widely deployed
|
|
11
|
+
"gpt-5.3": { input: 1.75, output: 14, cachedInput: 0.175 },
|
|
12
|
+
"gpt-5.2-pro": { input: 10.5, output: 84 },
|
|
13
|
+
"gpt-5.2": { input: 1.75, output: 14, cachedInput: 0.175 },
|
|
14
|
+
"gpt-5.1": { input: 0.625, output: 5, cachedInput: 0.125 },
|
|
15
|
+
"gpt-5-chat": { input: 1.25, output: 10, cachedInput: 0.125 },
|
|
16
|
+
"gpt-5": { input: 0.625, output: 5, cachedInput: 0.125 },
|
|
17
|
+
"gpt-5-mini": { input: 0.25, output: 2, cachedInput: 0.025 },
|
|
18
|
+
"gpt-5-nano": { input: 0.05, output: 0.4, cachedInput: 5e-3 },
|
|
19
|
+
// Reasoning models
|
|
20
|
+
"o4-mini": { input: 1.1, output: 4.4, cachedInput: 0.275 },
|
|
19
21
|
o3: { input: 2, output: 8, cachedInput: 0.5 },
|
|
20
22
|
"o3-mini": { input: 1.1, output: 4.4, cachedInput: 0.55 },
|
|
21
|
-
|
|
23
|
+
// Codex variants
|
|
24
|
+
"gpt-5.1-codex": { input: 1.25, output: 10, cachedInput: 0.125 },
|
|
25
|
+
"gpt-5.1-codex-mini": { input: 0.25, output: 2, cachedInput: 0.025 },
|
|
26
|
+
"gpt-5-codex": { input: 1.25, output: 10, cachedInput: 0.125 }
|
|
22
27
|
},
|
|
23
28
|
anthropic: {
|
|
29
|
+
"claude-opus-4-8": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
|
|
24
30
|
"claude-opus-4-7": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
|
|
25
31
|
"claude-opus-4-6": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
|
|
26
32
|
"claude-sonnet-4-6": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
|
|
27
33
|
"claude-sonnet-4-5": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
|
|
28
|
-
"claude-haiku-4-5": { input: 1, output: 5, cachedInput: 0.1, cacheCreation: 1.25 }
|
|
29
|
-
"claude-3-5-sonnet": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
|
|
30
|
-
"claude-3-5-haiku": { input: 0.8, output: 4, cachedInput: 0.08, cacheCreation: 1 },
|
|
31
|
-
"claude-3-opus": { input: 15, output: 75 },
|
|
32
|
-
"claude-3-haiku": { input: 0.25, output: 1.25 }
|
|
34
|
+
"claude-haiku-4-5": { input: 1, output: 5, cachedInput: 0.1, cacheCreation: 1.25 }
|
|
33
35
|
},
|
|
34
36
|
// Bedrock charges the same per-token rates as Anthropic direct for the
|
|
35
37
|
// Claude inference profiles; the model IDs differ (us.anthropic.* prefix).
|
|
36
38
|
bedrock: {
|
|
39
|
+
"us.anthropic.claude-opus-4-8": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
|
|
37
40
|
"us.anthropic.claude-opus-4-7": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
|
|
38
41
|
"us.anthropic.claude-opus-4-6": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
|
|
39
42
|
"us.anthropic.claude-sonnet-4-6": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
|
|
40
43
|
"us.anthropic.claude-sonnet-4-5": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
|
|
41
|
-
"us.anthropic.claude-haiku-4-5": { input: 1, output: 5, cachedInput: 0.1, cacheCreation: 1.25 }
|
|
42
|
-
"us.anthropic.claude-opus-4-1": { input: 15, output: 75 }
|
|
44
|
+
"us.anthropic.claude-haiku-4-5": { input: 1, output: 5, cachedInput: 0.1, cacheCreation: 1.25 }
|
|
43
45
|
},
|
|
44
46
|
gemini: {
|
|
47
|
+
// Gemini 3.x — current lineup (May 2026)
|
|
48
|
+
"gemini-3.5-flash": { input: 1.5, output: 9, cachedInput: 0.15 },
|
|
49
|
+
"gemini-3.1-pro-preview": { input: 2, output: 12, cachedInput: 0.2 },
|
|
50
|
+
"gemini-3.1-flash-lite-preview": { input: 0.25, output: 1.5, cachedInput: 0.025 },
|
|
51
|
+
"gemini-3-pro-preview": { input: 2, output: 12 },
|
|
52
|
+
"gemini-3-flash-preview": { input: 0.5, output: 3, cachedInput: 0.05 },
|
|
53
|
+
// Gemini 2.5 — still in active use
|
|
45
54
|
"gemini-2.5-pro": { input: 1, output: 10, cachedInput: 0.125 },
|
|
46
55
|
"gemini-2.5-flash": { input: 0.3, output: 2.5, cachedInput: 0.03 },
|
|
47
|
-
"gemini-2.5-flash-lite": { input: 0.1, output: 0.4, cachedInput: 0.01 }
|
|
48
|
-
"gemini-2.0-flash": { input: 0.1, output: 0.4, cachedInput: 0.025 },
|
|
49
|
-
"gemini-2.0-flash-lite": { input: 0.075, output: 0.3 },
|
|
50
|
-
"gemini-1.5-pro": { input: 1.25, output: 5 },
|
|
51
|
-
"gemini-1.5-flash": { input: 0.075, output: 0.3 }
|
|
56
|
+
"gemini-2.5-flash-lite": { input: 0.1, output: 0.4, cachedInput: 0.01 }
|
|
52
57
|
},
|
|
53
58
|
grok: {
|
|
54
|
-
|
|
59
|
+
// Grok 4.3 (April 30, 2026 release) — current primary, 1M context
|
|
60
|
+
"grok-4.3": { input: 1.25, output: 2.5, cachedInput: 0.2 },
|
|
61
|
+
"grok-4.20-0309-reasoning": { input: 1.25, output: 2.5, cachedInput: 0.2 },
|
|
62
|
+
"grok-4.20-0309-non-reasoning": { input: 1.25, output: 2.5, cachedInput: 0.2 },
|
|
63
|
+
"grok-4.20-multi-agent-0309": { input: 1.25, output: 2.5, cachedInput: 0.2 },
|
|
64
|
+
"grok-4.20": { input: 1.25, output: 2.5, cachedInput: 0.2 },
|
|
65
|
+
"grok-build-0.1": { input: 1, output: 2 },
|
|
66
|
+
// Cheap fast tier
|
|
55
67
|
"grok-4-fast": { input: 0.2, output: 0.5 },
|
|
56
|
-
"grok-
|
|
57
|
-
"grok-3-fast": { input: 5, output: 25 },
|
|
58
|
-
"grok-3-mini": { input: 0.25, output: 0.5 },
|
|
59
|
-
"grok-code-fast-1": { input: 0.2, output: 1.5 },
|
|
60
|
-
"grok-2": { input: 2, output: 10 }
|
|
68
|
+
"grok-code-fast-1": { input: 0.2, output: 1.5 }
|
|
61
69
|
},
|
|
62
70
|
deepseek: {
|
|
63
|
-
"deepseek-
|
|
64
|
-
"deepseek-reasoner": { input: 0.55, output: 2 },
|
|
71
|
+
"deepseek-v4-pro": { input: 0.435, output: 0.87, cachedInput: 36e-4 },
|
|
65
72
|
"deepseek-v4-flash": { input: 0.1, output: 0.2, cachedInput: 28e-4 },
|
|
66
|
-
"deepseek-
|
|
73
|
+
"deepseek-v3.2": { input: 0.252, output: 0.378, cachedInput: 0.0252 },
|
|
74
|
+
"deepseek-v3.2-thinking": { input: 0.252, output: 0.378, cachedInput: 0.0252 },
|
|
75
|
+
"deepseek-chat": { input: 0.014, output: 0.028 },
|
|
76
|
+
"deepseek-reasoner": { input: 0.55, output: 2 }
|
|
67
77
|
},
|
|
68
78
|
// OpenRouter prices vary per upstream model and include their own margin —
|
|
69
79
|
// ship empty; callers can either register their own rates or use
|
|
@@ -1,77 +1,86 @@
|
|
|
1
|
-
import { BaseProvider as
|
|
2
|
-
class
|
|
1
|
+
import { BaseProvider as g } from "./BaseProvider.js";
|
|
2
|
+
class b extends g {
|
|
3
3
|
async detectCapabilities() {
|
|
4
|
-
var
|
|
5
|
-
((
|
|
6
|
-
}
|
|
7
|
-
prepareRequest(
|
|
8
|
-
const
|
|
9
|
-
model:
|
|
10
|
-
max_tokens:
|
|
11
|
-
messages:
|
|
12
|
-
stream:
|
|
4
|
+
var t, e, o, s;
|
|
5
|
+
((t = this.config.model) != null && t.includes("claude-3") || (e = this.config.model) != null && e.includes("claude-sonnet") || (o = this.config.model) != null && o.includes("claude-opus") || (s = this.config.model) != null && s.includes("claude-haiku")) && (this.capabilities.add("vision"), this.capabilities.add("tools"));
|
|
6
|
+
}
|
|
7
|
+
prepareRequest(t, e) {
|
|
8
|
+
const o = m(t), s = e.model || this.config.model || "claude-3-sonnet-20240229", r = {
|
|
9
|
+
model: s,
|
|
10
|
+
max_tokens: e.maxTokens || 1e3,
|
|
11
|
+
messages: o,
|
|
12
|
+
stream: e.stream || !1
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
const c =
|
|
16
|
-
return c && (
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
_(s) || (r.temperature = e.temperature ?? 0.7);
|
|
15
|
+
const c = t.find((i) => i.role === "system");
|
|
16
|
+
return c && (r.system = c.content), e.tools && this.capabilities.has("tools") && (r.tools = y(e.tools), e.tool_choice && (r.tool_choice = e.tool_choice)), this.promptCachingEnabled(e) && k(r, e), r;
|
|
17
|
+
}
|
|
18
|
+
// Prompt caching is on by default for the Claude/Anthropic-family path
|
|
19
|
+
// (Bedrock inherits this method) because it's strictly cheaper and degrades
|
|
20
|
+
// gracefully — a prefix under the model's minimum cacheable length is simply
|
|
21
|
+
// not cached, with no error. Disable per-call with options.promptCache:false
|
|
22
|
+
// or per-config with config.promptCache:false.
|
|
23
|
+
promptCachingEnabled(t) {
|
|
24
|
+
var e;
|
|
25
|
+
return (t == null ? void 0 : t.promptCache) !== !1 && ((e = this.config) == null ? void 0 : e.promptCache) !== !1;
|
|
26
|
+
}
|
|
27
|
+
processMessages(t, e) {
|
|
28
|
+
return e.images && this.capabilities.has("vision") ? this.addImagesToMessages(t, e.images) : t;
|
|
29
|
+
}
|
|
30
|
+
addImagesToMessages(t, e) {
|
|
31
|
+
const o = t[t.length - 1];
|
|
32
|
+
if (o && o.role === "user") {
|
|
33
|
+
const s = [{ type: "text", text: o.content }];
|
|
34
|
+
e.forEach((r) => {
|
|
35
|
+
s.push({
|
|
27
36
|
type: "image",
|
|
28
|
-
source: { type: "base64", media_type: "image/jpeg", data: typeof
|
|
37
|
+
source: { type: "base64", media_type: "image/jpeg", data: typeof r == "string" ? r : r.data }
|
|
29
38
|
});
|
|
30
|
-
}),
|
|
39
|
+
}), o.content = s;
|
|
31
40
|
}
|
|
32
|
-
return
|
|
41
|
+
return t;
|
|
33
42
|
}
|
|
34
|
-
processResponse(
|
|
35
|
-
const
|
|
43
|
+
processResponse(t) {
|
|
44
|
+
const e = h(t.stop_reason), o = t.content || [], s = o.find((i) => i.type === "text"), c = o.filter((i) => i.type === "tool_use").map((i) => ({ id: i.id, name: i.name, args: i.input || {} }));
|
|
36
45
|
return {
|
|
37
|
-
content: (
|
|
38
|
-
usage:
|
|
39
|
-
finishReason:
|
|
46
|
+
content: (s == null ? void 0 : s.text) || "",
|
|
47
|
+
usage: f(t.usage),
|
|
48
|
+
finishReason: e,
|
|
40
49
|
toolCalls: c
|
|
41
50
|
};
|
|
42
51
|
}
|
|
43
|
-
parseStreamingLine(
|
|
44
|
-
if (!
|
|
45
|
-
const
|
|
46
|
-
if (
|
|
52
|
+
parseStreamingLine(t) {
|
|
53
|
+
if (!t.startsWith("data: ")) return null;
|
|
54
|
+
const e = t.slice(6).trim();
|
|
55
|
+
if (e === "[DONE]") return { done: !0 };
|
|
47
56
|
try {
|
|
48
|
-
return JSON.parse(
|
|
57
|
+
return JSON.parse(e);
|
|
49
58
|
} catch {
|
|
50
59
|
return null;
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
|
-
extractStreamingContent(
|
|
54
|
-
var
|
|
55
|
-
if (
|
|
56
|
-
if (
|
|
57
|
-
const a = ((
|
|
58
|
-
throw u.code = a,
|
|
62
|
+
extractStreamingContent(t) {
|
|
63
|
+
var e, o, s, r, c, i, d, p;
|
|
64
|
+
if (t.done) return { done: !0 };
|
|
65
|
+
if (t.type === "error") {
|
|
66
|
+
const a = ((e = t.error) == null ? void 0 : e.type) || "anthropic_error", u = new Error(((o = t.error) == null ? void 0 : o.message) || "Anthropic streaming error");
|
|
67
|
+
throw u.code = a, t.request_id && (u.requestId = t.request_id), u;
|
|
59
68
|
}
|
|
60
|
-
if (
|
|
61
|
-
return { content: "", thinking: "", done: !1, usage:
|
|
62
|
-
if (
|
|
63
|
-
const a =
|
|
69
|
+
if (t.type === "message_start")
|
|
70
|
+
return { content: "", thinking: "", done: !1, usage: f((s = t.message) == null ? void 0 : s.usage), finishReason: null };
|
|
71
|
+
if (t.type === "content_block_start") {
|
|
72
|
+
const a = t.content_block;
|
|
64
73
|
return (a == null ? void 0 : a.type) === "tool_use" ? {
|
|
65
74
|
content: "",
|
|
66
75
|
done: !1,
|
|
67
|
-
toolCallDelta: { index:
|
|
76
|
+
toolCallDelta: { index: t.index, id: a.id, name: a.name, argsTextDelta: "" }
|
|
68
77
|
} : null;
|
|
69
78
|
}
|
|
70
|
-
return
|
|
79
|
+
return t.type === "content_block_delta" ? ((r = t.delta) == null ? void 0 : r.type) === "text_delta" ? { content: ((c = t.delta) == null ? void 0 : c.text) || "", thinking: "", done: !1, usage: null, finishReason: null } : ((i = t.delta) == null ? void 0 : i.type) === "input_json_delta" ? {
|
|
71
80
|
content: "",
|
|
72
81
|
done: !1,
|
|
73
|
-
toolCallDelta: { index:
|
|
74
|
-
} : null :
|
|
82
|
+
toolCallDelta: { index: t.index, argsTextDelta: ((d = t.delta) == null ? void 0 : d.partial_json) || "" }
|
|
83
|
+
} : null : t.type === "message_delta" ? { content: "", thinking: "", done: !1, usage: f(t.usage), finishReason: h((p = t.delta) == null ? void 0 : p.stop_reason) } : t.type === "message_stop" ? { content: "", thinking: "", done: !0, usage: null, finishReason: h(t.stop_reason) } : null;
|
|
75
84
|
}
|
|
76
85
|
getApiPath() {
|
|
77
86
|
return "/v1/messages";
|
|
@@ -86,67 +95,107 @@ class y extends p {
|
|
|
86
95
|
return this.config.apiKey;
|
|
87
96
|
}
|
|
88
97
|
buildHeaders() {
|
|
89
|
-
const
|
|
90
|
-
return this.requiresAuth() && (
|
|
98
|
+
const t = super.buildHeaders();
|
|
99
|
+
return this.requiresAuth() && (t["anthropic-version"] = "2023-06-01", t["anthropic-dangerous-direct-browser-access"] = "true"), t;
|
|
91
100
|
}
|
|
92
101
|
getModelsEndpoint() {
|
|
93
102
|
return `${this.config.baseUrl}/v1/models`;
|
|
94
103
|
}
|
|
95
|
-
parseModelsResponse(
|
|
96
|
-
var
|
|
97
|
-
return ((
|
|
104
|
+
parseModelsResponse(t) {
|
|
105
|
+
var e;
|
|
106
|
+
return ((e = t.data) == null ? void 0 : e.map((o) => o.id)) || [];
|
|
98
107
|
}
|
|
99
108
|
}
|
|
100
|
-
function
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
function _(n) {
|
|
110
|
+
return /claude-opus-4-[789]/.test(n);
|
|
111
|
+
}
|
|
112
|
+
function h(n) {
|
|
113
|
+
if (!n) return null;
|
|
114
|
+
const t = String(n).toLowerCase();
|
|
115
|
+
return t === "max_tokens" ? "length" : t;
|
|
104
116
|
}
|
|
105
|
-
function
|
|
106
|
-
if (!
|
|
107
|
-
const
|
|
108
|
-
return
|
|
117
|
+
function f(n) {
|
|
118
|
+
if (!n) return null;
|
|
119
|
+
const t = n.input_tokens ?? 0, e = n.cache_read_input_tokens ?? 0, o = n.cache_creation_input_tokens ?? 0, r = n.input_tokens != null || n.cache_read_input_tokens != null || n.cache_creation_input_tokens != null ? t + e + o : 0, c = n.output_tokens ?? 0, i = { inputTokens: r, outputTokens: c, totalTokens: r + c, raw: n };
|
|
120
|
+
return n.cache_read_input_tokens != null && (i.cachedInputTokens = e), n.cache_creation_input_tokens != null && (i.cacheCreationInputTokens = o), i;
|
|
109
121
|
}
|
|
110
|
-
function
|
|
111
|
-
const
|
|
112
|
-
for (const
|
|
113
|
-
if (
|
|
114
|
-
if (
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
for (const
|
|
118
|
-
|
|
122
|
+
function m(n) {
|
|
123
|
+
const t = [];
|
|
124
|
+
for (const e of n)
|
|
125
|
+
if (e.role !== "system") {
|
|
126
|
+
if (e.role === "assistant" && Array.isArray(e.tool_calls) && e.tool_calls.length) {
|
|
127
|
+
const o = [];
|
|
128
|
+
e.content && o.push({ type: "text", text: e.content });
|
|
129
|
+
for (const s of e.tool_calls)
|
|
130
|
+
o.push({
|
|
119
131
|
type: "tool_use",
|
|
120
|
-
id:
|
|
121
|
-
name:
|
|
122
|
-
input:
|
|
132
|
+
id: s.id,
|
|
133
|
+
name: s.name,
|
|
134
|
+
input: s.args || {}
|
|
123
135
|
});
|
|
124
|
-
|
|
136
|
+
t.push({ role: "assistant", content: o });
|
|
125
137
|
continue;
|
|
126
138
|
}
|
|
127
|
-
if (
|
|
128
|
-
|
|
139
|
+
if (e.role === "tool") {
|
|
140
|
+
t.push({
|
|
129
141
|
role: "user",
|
|
130
142
|
content: [{
|
|
131
143
|
type: "tool_result",
|
|
132
|
-
tool_use_id:
|
|
133
|
-
content: String(
|
|
144
|
+
tool_use_id: e.tool_call_id,
|
|
145
|
+
content: String(e.content ?? "")
|
|
134
146
|
}]
|
|
135
147
|
});
|
|
136
148
|
continue;
|
|
137
149
|
}
|
|
138
|
-
|
|
150
|
+
t.push({ role: e.role, content: e.content });
|
|
151
|
+
}
|
|
152
|
+
return t;
|
|
153
|
+
}
|
|
154
|
+
function y(n) {
|
|
155
|
+
return n.map((t) => t.type === "function" && t.function ? {
|
|
156
|
+
name: t.function.name,
|
|
157
|
+
description: t.function.description,
|
|
158
|
+
input_schema: t.function.parameters || { type: "object", properties: {} }
|
|
159
|
+
} : t);
|
|
160
|
+
}
|
|
161
|
+
const l = { type: "ephemeral" };
|
|
162
|
+
function k(n, t) {
|
|
163
|
+
if (n.system)
|
|
164
|
+
n.system = x(n.system);
|
|
165
|
+
else if (Array.isArray(n.tools) && n.tools.length) {
|
|
166
|
+
const e = n.tools.length - 1;
|
|
167
|
+
n.tools[e] = { ...n.tools[e], cache_control: l };
|
|
168
|
+
}
|
|
169
|
+
if (t != null && t.cacheTranscript) {
|
|
170
|
+
const e = n.messages;
|
|
171
|
+
if (Array.isArray(e) && e.length) {
|
|
172
|
+
const o = e[e.length - 1];
|
|
173
|
+
o.content = A(o.content);
|
|
139
174
|
}
|
|
140
|
-
|
|
175
|
+
}
|
|
176
|
+
return n;
|
|
177
|
+
}
|
|
178
|
+
function x(n) {
|
|
179
|
+
let t;
|
|
180
|
+
if (typeof n == "string")
|
|
181
|
+
t = [{ type: "text", text: n }];
|
|
182
|
+
else if (Array.isArray(n) && n.length)
|
|
183
|
+
t = n.map((e) => typeof e == "string" ? { type: "text", text: e } : { ...e });
|
|
184
|
+
else
|
|
185
|
+
return n;
|
|
186
|
+
return t[t.length - 1] = { ...t[t.length - 1], cache_control: l }, t;
|
|
141
187
|
}
|
|
142
|
-
function
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
188
|
+
function A(n) {
|
|
189
|
+
if (typeof n == "string")
|
|
190
|
+
return [{ type: "text", text: n, cache_control: l }];
|
|
191
|
+
if (Array.isArray(n) && n.length) {
|
|
192
|
+
const t = n.slice(), e = t.length - 1, o = t[e];
|
|
193
|
+
return t[e] = typeof o == "string" ? { type: "text", text: o, cache_control: l } : { ...o, cache_control: l }, t;
|
|
194
|
+
}
|
|
195
|
+
return n;
|
|
148
196
|
}
|
|
149
197
|
export {
|
|
150
|
-
|
|
151
|
-
|
|
198
|
+
b as AnthropicProvider,
|
|
199
|
+
f as normalizeAnthropicUsage,
|
|
200
|
+
_ as samplingParamsRemoved
|
|
152
201
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseProvider as y } from "./BaseProvider.js";
|
|
2
2
|
import { AnthropicProvider as w } from "./AnthropicProvider.js";
|
|
3
|
-
const
|
|
3
|
+
const p = [
|
|
4
|
+
"us.anthropic.claude-opus-4-8",
|
|
4
5
|
"us.anthropic.claude-opus-4-7",
|
|
5
6
|
"us.anthropic.claude-sonnet-4-6",
|
|
6
7
|
"us.anthropic.claude-haiku-4-5-20251001-v1:0",
|
|
@@ -9,10 +10,10 @@ const g = [
|
|
|
9
10
|
"us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
10
11
|
"us.anthropic.claude-opus-4-1-20250805-v1:0"
|
|
11
12
|
];
|
|
12
|
-
class
|
|
13
|
-
prepareRequest(
|
|
14
|
-
const
|
|
15
|
-
return delete
|
|
13
|
+
class A extends w {
|
|
14
|
+
prepareRequest(n, t) {
|
|
15
|
+
const r = super.prepareRequest(n, t);
|
|
16
|
+
return delete r.stream, r.anthropic_version = "bedrock-2023-05-31", r;
|
|
16
17
|
}
|
|
17
18
|
buildHeaders() {
|
|
18
19
|
return y.prototype.buildHeaders.call(this);
|
|
@@ -26,147 +27,170 @@ class R extends w {
|
|
|
26
27
|
requiresAuth() {
|
|
27
28
|
return !!this.config.apiKey;
|
|
28
29
|
}
|
|
29
|
-
async makeRequest(
|
|
30
|
-
const e =
|
|
30
|
+
async makeRequest(n, t, r) {
|
|
31
|
+
const e = n.model, d = { ...n };
|
|
31
32
|
delete d.model;
|
|
32
|
-
const
|
|
33
|
-
|
|
33
|
+
const i = `${this.config.baseUrl}/model/${encodeURIComponent(e)}/invoke`, l = t ? { signal: t } : new AbortController();
|
|
34
|
+
t || (r = r || this.generateRequestId(), this.activeRequests.set(r, l));
|
|
34
35
|
try {
|
|
35
|
-
const
|
|
36
|
+
const o = await fetch(i, {
|
|
36
37
|
method: "POST",
|
|
37
38
|
headers: this.buildHeaders(),
|
|
38
39
|
body: JSON.stringify(d),
|
|
39
|
-
signal:
|
|
40
|
+
signal: l.signal || t
|
|
40
41
|
});
|
|
41
|
-
if (!
|
|
42
|
-
const
|
|
43
|
-
throw new Error(`Bedrock API Error (${
|
|
42
|
+
if (!o.ok) {
|
|
43
|
+
const h = await o.text();
|
|
44
|
+
throw new Error(`Bedrock API Error (${o.status}): ${h}`);
|
|
44
45
|
}
|
|
45
|
-
return
|
|
46
|
+
return o.json();
|
|
46
47
|
} finally {
|
|
47
|
-
!
|
|
48
|
+
!t && r && this.activeRequests.delete(r);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
|
-
async makeStreamingRequest(
|
|
51
|
-
const
|
|
51
|
+
async makeStreamingRequest(n, t) {
|
|
52
|
+
const r = n.model, e = { ...n };
|
|
52
53
|
delete e.model;
|
|
53
|
-
const d = `${this.config.baseUrl}/model/${encodeURIComponent(
|
|
54
|
+
const d = `${this.config.baseUrl}/model/${encodeURIComponent(r)}/invoke-with-response-stream`, i = await fetch(d, {
|
|
54
55
|
method: "POST",
|
|
55
56
|
headers: this.buildHeaders(),
|
|
56
57
|
body: JSON.stringify(e),
|
|
57
|
-
signal:
|
|
58
|
+
signal: t
|
|
58
59
|
});
|
|
59
|
-
if (!
|
|
60
|
-
const
|
|
61
|
-
throw new Error(`Bedrock API Error (${
|
|
60
|
+
if (!i.ok) {
|
|
61
|
+
const c = await i.text();
|
|
62
|
+
throw new Error(`Bedrock API Error (${i.status}): ${c}`);
|
|
62
63
|
}
|
|
63
|
-
const
|
|
64
|
-
async pull(
|
|
64
|
+
const l = i.body.getReader(), o = new v(), h = new TextEncoder(), f = new ReadableStream({
|
|
65
|
+
async pull(c) {
|
|
65
66
|
try {
|
|
66
|
-
const { done: a, value:
|
|
67
|
+
const { done: a, value: g } = await l.read();
|
|
67
68
|
if (a) {
|
|
68
|
-
|
|
69
|
+
c.close();
|
|
69
70
|
return;
|
|
70
71
|
}
|
|
71
|
-
const
|
|
72
|
-
for (const
|
|
73
|
-
if (
|
|
74
|
-
|
|
72
|
+
const m = o.feed(g);
|
|
73
|
+
for (const u of m) {
|
|
74
|
+
if (u.kind === "error") {
|
|
75
|
+
c.error(new Error(u.message));
|
|
75
76
|
return;
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
+
c.enqueue(h.encode(`data: ${JSON.stringify(u.payload)}
|
|
78
79
|
`));
|
|
79
80
|
}
|
|
80
81
|
} catch (a) {
|
|
81
|
-
|
|
82
|
+
c.error(a);
|
|
82
83
|
}
|
|
83
84
|
},
|
|
84
|
-
cancel(
|
|
85
|
+
cancel(c) {
|
|
85
86
|
try {
|
|
86
|
-
|
|
87
|
+
l.cancel(c);
|
|
87
88
|
} catch {
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
});
|
|
91
92
|
return new Response(f, { status: 200, headers: { "Content-Type": "text/event-stream" } });
|
|
92
93
|
}
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
// Live discovery is opt-in via config.liveModelDiscovery. A Bedrock API key
|
|
95
|
+
// authenticates against the control plane with Bearer auth (no SigV4), and
|
|
96
|
+
// the control-plane host returns permissive CORS headers, so a browser fetch
|
|
97
|
+
// works. When disabled (default) or on any failure, fall back to the static
|
|
98
|
+
// list — existing apps keep working with zero surprise network calls.
|
|
99
|
+
async discoverModels(n = 1e4) {
|
|
100
|
+
if (!this.config.liveModelDiscovery || !this.getModelsEndpoint())
|
|
101
|
+
return p.slice();
|
|
102
|
+
try {
|
|
103
|
+
const t = await super.discoverModels(n);
|
|
104
|
+
return t.length ? t : p.slice();
|
|
105
|
+
} catch {
|
|
106
|
+
return p.slice();
|
|
107
|
+
}
|
|
97
108
|
}
|
|
109
|
+
// The control plane lives at the same host with the `-runtime` segment
|
|
110
|
+
// stripped: bedrock-runtime.{region}.amazonaws.com (invoke) ->
|
|
111
|
+
// bedrock.{region}.amazonaws.com (ListInferenceProfiles). Returns null when
|
|
112
|
+
// no distinct control-plane host can be derived (custom/relative baseUrl),
|
|
113
|
+
// which disables live discovery and leaves the static fallback in place.
|
|
98
114
|
getModelsEndpoint() {
|
|
99
|
-
|
|
115
|
+
const n = this.config.baseUrl || "", t = n.replace("bedrock-runtime.", "bedrock.");
|
|
116
|
+
return !t || t === n ? null : `${t}/inference-profiles`;
|
|
100
117
|
}
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
// ListInferenceProfiles returns
|
|
119
|
+
// { inferenceProfileSummaries: [{ inferenceProfileId, ... }] }
|
|
120
|
+
// Keep only Anthropic Claude profiles (us.* and global.*) — those ids are
|
|
121
|
+
// exactly what InvokeModel expects in the URL path.
|
|
122
|
+
parseModelsResponse(n) {
|
|
123
|
+
const t = n == null ? void 0 : n.inferenceProfileSummaries;
|
|
124
|
+
if (!Array.isArray(t)) return p.slice();
|
|
125
|
+
const r = t.map((e) => e == null ? void 0 : e.inferenceProfileId).filter((e) => typeof e == "string" && e.includes("anthropic.claude"));
|
|
126
|
+
return r.length ? r : p.slice();
|
|
103
127
|
}
|
|
104
128
|
}
|
|
105
129
|
class v {
|
|
106
130
|
constructor() {
|
|
107
131
|
this.buf = new Uint8Array(0), this.textDecoder = new TextDecoder();
|
|
108
132
|
}
|
|
109
|
-
feed(
|
|
110
|
-
if (
|
|
111
|
-
const
|
|
112
|
-
|
|
133
|
+
feed(n) {
|
|
134
|
+
if (n && n.length) {
|
|
135
|
+
const r = new Uint8Array(this.buf.length + n.length);
|
|
136
|
+
r.set(this.buf, 0), r.set(n, this.buf.length), this.buf = r;
|
|
113
137
|
}
|
|
114
|
-
const
|
|
138
|
+
const t = [];
|
|
115
139
|
for (; this.buf.length >= 12; ) {
|
|
116
|
-
const
|
|
140
|
+
const r = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength), e = r.getUint32(0, !1), d = r.getUint32(4, !1);
|
|
117
141
|
if (e < 16 || e > 16 * 1024 * 1024)
|
|
118
142
|
throw new Error(`Bedrock event stream: invalid frame length ${e}`);
|
|
119
143
|
if (this.buf.length < e) break;
|
|
120
|
-
const
|
|
144
|
+
const i = 12, l = i + d, o = l, h = e - 4, f = k(this.buf.subarray(i, l)), c = this.textDecoder.decode(this.buf.subarray(o, h));
|
|
121
145
|
this.buf = this.buf.subarray(e);
|
|
122
146
|
let a;
|
|
123
147
|
try {
|
|
124
|
-
a = JSON.parse(
|
|
148
|
+
a = JSON.parse(c);
|
|
125
149
|
} catch {
|
|
126
150
|
a = null;
|
|
127
151
|
}
|
|
128
|
-
const
|
|
129
|
-
if (
|
|
130
|
-
const
|
|
131
|
-
|
|
152
|
+
const g = f[":message-type"], m = f[":exception-type"];
|
|
153
|
+
if (g === "exception" || m) {
|
|
154
|
+
const u = m || f[":event-type"] || "BedrockStreamException", b = (a == null ? void 0 : a.message) || c || "unknown error";
|
|
155
|
+
t.push({ kind: "error", message: `${u}: ${b}` });
|
|
132
156
|
continue;
|
|
133
157
|
}
|
|
134
158
|
if (a && typeof a.bytes == "string")
|
|
135
159
|
try {
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
} catch (
|
|
139
|
-
|
|
160
|
+
const u = x(a.bytes), b = JSON.parse(u);
|
|
161
|
+
t.push({ kind: "event", payload: b });
|
|
162
|
+
} catch (u) {
|
|
163
|
+
t.push({ kind: "error", message: `Bedrock event-stream decode failed: ${u.message}` });
|
|
140
164
|
}
|
|
141
165
|
}
|
|
142
|
-
return
|
|
166
|
+
return t;
|
|
143
167
|
}
|
|
144
168
|
}
|
|
145
|
-
function k(
|
|
146
|
-
const
|
|
169
|
+
function k(s) {
|
|
170
|
+
const n = {}, t = new DataView(s.buffer, s.byteOffset, s.byteLength), r = new TextDecoder();
|
|
147
171
|
let e = 0;
|
|
148
|
-
for (; e <
|
|
149
|
-
const d =
|
|
150
|
-
if (e += 1, e + d >
|
|
151
|
-
const
|
|
152
|
-
if (e += d, e >=
|
|
153
|
-
const
|
|
154
|
-
if (e += 1,
|
|
155
|
-
if (e + 2 >
|
|
156
|
-
const
|
|
157
|
-
if (e += 2, e +
|
|
158
|
-
|
|
172
|
+
for (; e < s.length; ) {
|
|
173
|
+
const d = s[e];
|
|
174
|
+
if (e += 1, e + d > s.length) break;
|
|
175
|
+
const i = r.decode(s.subarray(e, e + d));
|
|
176
|
+
if (e += d, e >= s.length) break;
|
|
177
|
+
const l = s[e];
|
|
178
|
+
if (e += 1, l === 7) {
|
|
179
|
+
if (e + 2 > s.length) break;
|
|
180
|
+
const o = t.getUint16(e, !1);
|
|
181
|
+
if (e += 2, e + o > s.length) break;
|
|
182
|
+
n[i] = r.decode(s.subarray(e, e + o)), e += o;
|
|
159
183
|
} else
|
|
160
184
|
break;
|
|
161
185
|
}
|
|
162
|
-
return
|
|
186
|
+
return n;
|
|
163
187
|
}
|
|
164
|
-
function x(
|
|
165
|
-
const
|
|
166
|
-
for (let
|
|
167
|
-
return new TextDecoder().decode(
|
|
188
|
+
function x(s) {
|
|
189
|
+
const n = atob(s), t = new Uint8Array(n.length);
|
|
190
|
+
for (let r = 0; r < n.length; r++) t[r] = n.charCodeAt(r);
|
|
191
|
+
return new TextDecoder().decode(t);
|
|
168
192
|
}
|
|
169
193
|
export {
|
|
170
|
-
|
|
171
|
-
|
|
194
|
+
p as BEDROCK_CLAUDE_MODELS,
|
|
195
|
+
A as BedrockProvider
|
|
172
196
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anvaka/vue-llm",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Browser-only LLM client with provider adapters and Vue 3 components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "vite build",
|
|
11
11
|
"dev": "vite build --watch",
|
|
12
|
-
"test:providers": "node test/providers.mjs"
|
|
12
|
+
"test:providers": "node test/providers.mjs",
|
|
13
|
+
"test:caching": "node test/caching.mjs"
|
|
13
14
|
},
|
|
14
15
|
"exports": {
|
|
15
16
|
".": {
|