@anvaka/vue-llm 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,8 @@
3
3
  Browser-only LLM client + Vue 3 plugin, provider adapters, and lightweight components.
4
4
 
5
5
  ## Features
6
- - Provider factory with 10 built-in providers (OpenAI, Anthropic, Bedrock, Grok, Gemini, Ollama, Llama Server, OpenRouter, DeepSeek, Custom) – extend with `registerProvider()`
6
+ - Provider factory with 10 built-in providers (OpenAI, Anthropic, AWS, Grok, Gemini, Ollama, Llama Server, OpenRouter, DeepSeek, Custom) – extend with `registerProvider()`
7
+ - **AWS** runs on the Bedrock Mantle endpoint and exposes the entire catalog (Claude, GPT-OSS, Qwen, Mistral, Gemma, …) from one model list — each request is routed to the right API surface automatically (Claude → Anthropic Messages, everything else → OpenAI Chat Completions)
7
8
  - LocalStorage-based config store (custom storage adapter supported)
8
9
  - Streaming + promise requests via `llmClient.stream()`
9
10
  - Normalized usage + USD cost on every response (override built-in rates per app or per model)
@@ -33,15 +33,30 @@ const t = {
33
33
  "claude-sonnet-4-5": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
34
34
  "claude-haiku-4-5": { input: 1, output: 5, cachedInput: 0.1, cacheCreation: 1.25 }
35
35
  },
36
- // Bedrock charges the same per-token rates as Anthropic direct for the
37
- // Claude inference profiles; the model IDs differ (us.anthropic.* prefix).
36
+ // Bedrock charges the same per-token rates as Anthropic direct for the Claude
37
+ // models; only the id form differs by backend. bedrock-runtime uses the
38
+ // cross-region inference profiles (us.anthropic.*); bedrock-mantle uses the
39
+ // Anthropic-native ids (anthropic.claude-*-v1). Both backends share this
40
+ // provider type ('bedrock'), so both id forms live here. Keys omit any -v1
41
+ // suffix so lookupRates' prefix match catches versioned ids.
38
42
  bedrock: {
39
43
  "us.anthropic.claude-opus-4-8": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
40
44
  "us.anthropic.claude-opus-4-7": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
41
45
  "us.anthropic.claude-opus-4-6": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
42
46
  "us.anthropic.claude-sonnet-4-6": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
43
47
  "us.anthropic.claude-sonnet-4-5": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
44
- "us.anthropic.claude-haiku-4-5": { input: 1, output: 5, cachedInput: 0.1, cacheCreation: 1.25 }
48
+ "us.anthropic.claude-haiku-4-5": { input: 1, output: 5, cachedInput: 0.1, cacheCreation: 1.25 },
49
+ // bedrock-mantle ids
50
+ "anthropic.claude-opus-4-8": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
51
+ "anthropic.claude-opus-4-7": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
52
+ "anthropic.claude-opus-4-6": { input: 5, output: 25, cachedInput: 0.5, cacheCreation: 6.25 },
53
+ "anthropic.claude-sonnet-5": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
54
+ "anthropic.claude-sonnet-4-6": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
55
+ "anthropic.claude-sonnet-4-5": { input: 3, output: 15, cachedInput: 0.3, cacheCreation: 3.75 },
56
+ "anthropic.claude-haiku-4-5": { input: 1, output: 5, cachedInput: 0.1, cacheCreation: 1.25 },
57
+ // OpenAI frontier via /openai/v1/responses (usage billed on input/output tokens)
58
+ "openai.gpt-5.5": { input: 5, output: 30, cachedInput: 0.5 },
59
+ "openai.gpt-5.4": { input: 5, output: 30, cachedInput: 0.5 }
45
60
  },
46
61
  gemini: {
47
62
  // Gemini 3.x — current lineup (May 2026)
@@ -0,0 +1,265 @@
1
+ import { BaseProvider as d } from "./BaseProvider.js";
2
+ import { OpenAIProvider as h } from "./OpenAIProvider.js";
3
+ import { AnthropicProvider as f } from "./AnthropicProvider.js";
4
+ const l = [
5
+ "anthropic.claude-opus-4-8",
6
+ "anthropic.claude-opus-4-7",
7
+ "anthropic.claude-sonnet-5",
8
+ "anthropic.claude-haiku-4-5"
9
+ ];
10
+ function _(s) {
11
+ return typeof s == "string" && s.includes("anthropic.claude");
12
+ }
13
+ function m(s) {
14
+ return typeof s == "string" && (/openai\.gpt-5/.test(s) || /codex/.test(s));
15
+ }
16
+ function g(s) {
17
+ return /does not support the '[^']*' API/i.test((s == null ? void 0 : s.message) || "");
18
+ }
19
+ function y(s) {
20
+ const e = (s == null ? void 0 : s.message) || "";
21
+ if (/not available for this account|Berm is not enabled|access_denied|permission_(error|denied)/i.test(e)) {
22
+ const t = new Error(`This model isn't enabled for your AWS account — request access in the Amazon Bedrock console, then try again. (${e})`);
23
+ return t.cause = s, t;
24
+ }
25
+ return s;
26
+ }
27
+ class b extends f {
28
+ getApiPath() {
29
+ return "/anthropic/v1/messages";
30
+ }
31
+ buildHeaders() {
32
+ const e = super.buildHeaders();
33
+ return delete e["anthropic-dangerous-direct-browser-access"], e;
34
+ }
35
+ }
36
+ class R extends h {
37
+ // /v1/chat/completions + Bearer + /v1/models are inherited. Only discovery
38
+ // differs: list EVERY available model so the single dropdown offers the whole
39
+ // catalog (the router, not this class, decides each model's transport).
40
+ async detectCapabilities() {
41
+ await super.detectCapabilities(), this.capabilities.add("tools");
42
+ }
43
+ parseModelsResponse(e) {
44
+ return ((e == null ? void 0 : e.data) || []).filter((t) => t && typeof t.id == "string" && (t.status == null || t.status === "available")).map((t) => t.id).sort();
45
+ }
46
+ }
47
+ const k = 16;
48
+ class p extends d {
49
+ constructor(e, t) {
50
+ super(e), this._apiPath = t || "/v1/responses";
51
+ }
52
+ getApiPath() {
53
+ return this._apiPath;
54
+ }
55
+ requiresAuth() {
56
+ return !!this.config.apiKey;
57
+ }
58
+ // Bearer (BaseProvider default)
59
+ async detectCapabilities() {
60
+ const e = (this.config.model || "").toLowerCase();
61
+ this.capabilities.add("tools"), (e.includes("gpt-5") || e.includes("codex") || /(^|\.)o[13]/.test(e)) && this.capabilities.add("thinking");
62
+ }
63
+ prepareRequest(e, t) {
64
+ const r = {
65
+ model: t.model || this.config.model,
66
+ input: v(e),
67
+ // The Responses API rejects max_output_tokens < 16 (Chat Completions and
68
+ // Messages accept less), so clamp — e.g. testConnection sends 10.
69
+ max_output_tokens: Math.max(k, t.maxTokens || 1e3),
70
+ stream: t.stream || !1
71
+ }, i = x(t.tools);
72
+ return i && (r.tools = i), r;
73
+ }
74
+ processResponse(e) {
75
+ let t = "", n = "";
76
+ const r = [];
77
+ for (const o of e.output || [])
78
+ if (o.type === "message")
79
+ for (const a of o.content || []) a.type === "output_text" && (t += a.text || "");
80
+ else if (o.type === "reasoning")
81
+ for (const a of o.content || []) a.type === "reasoning_text" && (n += a.text || "");
82
+ else o.type === "function_call" && r.push({ id: o.call_id || o.id, name: o.name, args: A(o.arguments) });
83
+ const i = {
84
+ content: t,
85
+ usage: u(e.usage),
86
+ finishReason: c(e.status)
87
+ };
88
+ return n && (i.thinking = n), r.length && (i.toolCalls = r), i;
89
+ }
90
+ // Responses streams plain `data: {json}` SSE (no [DONE]); events carry a
91
+ // `type`. AnthropicProvider/OpenAIProvider use the same `data: ` line format.
92
+ parseStreamingLine(e) {
93
+ if (!e.startsWith("data: ")) return null;
94
+ const t = e.slice(6).trim();
95
+ if (t === "[DONE]") return { done: !0 };
96
+ try {
97
+ return JSON.parse(t);
98
+ } catch {
99
+ return null;
100
+ }
101
+ }
102
+ extractStreamingContent(e) {
103
+ var t, n, r, i;
104
+ if (e.done) return { done: !0 };
105
+ switch (e.type) {
106
+ case "response.output_text.delta":
107
+ return { content: e.delta || "", done: !1 };
108
+ case "response.reasoning_text.delta":
109
+ return { thinking: e.delta || "", done: !1 };
110
+ // A function_call item opens with output_item.added (carrying the call_id
111
+ // and name), then streams its JSON arguments as function_call_arguments.delta
112
+ // fragments. We seed id/name on `added` and stitch arg text on each delta;
113
+ // BaseProvider's accumulator keys them by output_index and parses at done.
114
+ case "response.output_item.added": {
115
+ const o = e.item;
116
+ return o && o.type === "function_call" ? { content: "", done: !1, toolCallDelta: { index: e.output_index ?? 0, id: o.call_id, name: o.name, argsTextDelta: "" } } : null;
117
+ }
118
+ case "response.function_call_arguments.delta":
119
+ return { content: "", done: !1, toolCallDelta: { index: e.output_index ?? 0, argsTextDelta: e.delta || "" } };
120
+ case "response.completed":
121
+ return { done: !0, usage: u((t = e.response) == null ? void 0 : t.usage), finishReason: c((n = e.response) == null ? void 0 : n.status) };
122
+ case "response.incomplete":
123
+ case "response.failed":
124
+ return { done: !0, usage: u((r = e.response) == null ? void 0 : r.usage), finishReason: c((i = e.response) == null ? void 0 : i.status) };
125
+ default:
126
+ return null;
127
+ }
128
+ }
129
+ }
130
+ class S extends d {
131
+ constructor(e) {
132
+ super(e), this._claude = new b(e), this._chat = new R(e), this._responses = new p(e, "/v1/responses"), this._openaiResponses = new p(e, "/openai/v1/responses"), this._resolved = /* @__PURE__ */ new Map();
133
+ }
134
+ _subs() {
135
+ return [this._claude, this._chat, this._responses, this._openaiResponses];
136
+ }
137
+ // Ordered candidate transports for a model; first that isn't rejected with
138
+ // "does not support" wins and is cached.
139
+ _order(e) {
140
+ const t = e || this.config.model || "";
141
+ if (_(t)) return [this._claude];
142
+ const n = this._resolved.get(t);
143
+ return n ? [n] : m(t) ? [this._openaiResponses, this._responses, this._chat] : [this._chat, this._responses, this._openaiResponses];
144
+ }
145
+ _active() {
146
+ return this._order(this.config.model)[0];
147
+ }
148
+ async initialize() {
149
+ const e = this._active();
150
+ await e.initialize(), this.capabilities = e.capabilities;
151
+ }
152
+ async detectCapabilities() {
153
+ const e = this._active();
154
+ await e.detectCapabilities(), this.capabilities = e.capabilities;
155
+ }
156
+ hasCapability(e) {
157
+ return this._active().hasCapability(e);
158
+ }
159
+ // Defer real preparation to makeRequest/streamRequest so we can fall back
160
+ // across API surfaces (a model's supported API isn't advertised anywhere).
161
+ prepareRequest(e, t) {
162
+ return { __mantle: { messages: e, options: t } };
163
+ }
164
+ async makeRequest(e, t, n) {
165
+ if (e && e.__mantle) {
166
+ const { messages: r, options: i } = e.__mantle;
167
+ return this._runWithFallback((o) => o.makeRequest(o.prepareRequest(r, i), t, n), i == null ? void 0 : i.model);
168
+ }
169
+ return this._subForShape(e).makeRequest(e, t, n);
170
+ }
171
+ async streamRequest(e, t, n) {
172
+ return this._runWithFallback((r) => r.streamRequest(e, t, n), t == null ? void 0 : t.model);
173
+ }
174
+ async _runWithFallback(e, t) {
175
+ const n = t || this.config.model;
176
+ let r;
177
+ for (const i of this._order(n))
178
+ try {
179
+ const o = await e(i);
180
+ return this._resolved.set(n, i), o;
181
+ } catch (o) {
182
+ if (g(o)) {
183
+ r = o;
184
+ continue;
185
+ }
186
+ throw y(o);
187
+ }
188
+ throw r || new Error(`No compatible Mantle API for model '${n}'`);
189
+ }
190
+ processResponse(e) {
191
+ return this._subForShape(e).processResponse(e);
192
+ }
193
+ _subForShape(e) {
194
+ return e != null && e.choices ? this._chat : e != null && e.output || e != null && e.status ? this._responses : Array.isArray(e == null ? void 0 : e.content) || e != null && e.stop_reason ? this._claude : this._active();
195
+ }
196
+ async discoverModels(e = 1e4, t) {
197
+ try {
198
+ const n = await this._chat.discoverModels(e, t);
199
+ return n.length ? n : l.slice();
200
+ } catch {
201
+ return l.slice();
202
+ }
203
+ }
204
+ cancelAllRequests() {
205
+ for (const e of this._subs()) e.cancelAllRequests();
206
+ }
207
+ cancelRequest(e) {
208
+ for (const t of this._subs()) t.cancelRequest(e);
209
+ }
210
+ }
211
+ function v(s) {
212
+ const e = [];
213
+ for (const t of s) {
214
+ if (t.role === "tool") {
215
+ e.push({ type: "function_call_output", call_id: t.tool_call_id, output: String(t.content ?? "") });
216
+ continue;
217
+ }
218
+ if (t.role === "assistant" && Array.isArray(t.tool_calls) && t.tool_calls.length) {
219
+ t.content && e.push({ role: "assistant", content: t.content });
220
+ for (const n of t.tool_calls)
221
+ e.push({
222
+ type: "function_call",
223
+ call_id: n.id,
224
+ name: n.name,
225
+ arguments: typeof n.args == "string" ? n.args : JSON.stringify(n.args || {})
226
+ });
227
+ continue;
228
+ }
229
+ e.push({ role: t.role, content: t.content });
230
+ }
231
+ return e;
232
+ }
233
+ function x(s) {
234
+ if (!(!Array.isArray(s) || !s.length))
235
+ return s.map((e) => {
236
+ if (e && e.type === "function" && e.function) {
237
+ const t = e.function;
238
+ return { type: "function", name: t.name, description: t.description, parameters: t.parameters };
239
+ }
240
+ return e;
241
+ });
242
+ }
243
+ function c(s) {
244
+ return s === "completed" ? "stop" : s === "incomplete" ? "length" : s || null;
245
+ }
246
+ function u(s) {
247
+ var o, a;
248
+ if (!s) return null;
249
+ const e = s.input_tokens ?? 0, t = s.output_tokens ?? 0, n = { inputTokens: e, outputTokens: t, totalTokens: s.total_tokens ?? e + t, raw: s }, r = (o = s.input_tokens_details) == null ? void 0 : o.cached_tokens, i = (a = s.output_tokens_details) == null ? void 0 : a.reasoning_tokens;
250
+ return r != null && (n.cachedInputTokens = r), i != null && (n.reasoningTokens = i), n;
251
+ }
252
+ function A(s) {
253
+ if (!s) return {};
254
+ try {
255
+ return JSON.parse(s);
256
+ } catch {
257
+ return { __parseError: !0, raw: s };
258
+ }
259
+ }
260
+ export {
261
+ l as BEDROCK_MANTLE_CLAUDE_MODELS,
262
+ S as BedrockMantleProvider,
263
+ _ as isMantleClaudeModel,
264
+ u as normalizeResponsesUsage
265
+ };
@@ -11,9 +11,9 @@ const p = [
11
11
  "us.anthropic.claude-opus-4-1-20250805-v1:0"
12
12
  ];
13
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;
14
+ prepareRequest(r, n) {
15
+ const t = super.prepareRequest(r, n);
16
+ return delete t.stream, t.anthropic_version = "bedrock-2023-05-31", t;
17
17
  }
18
18
  buildHeaders() {
19
19
  return y.prototype.buildHeaders.call(this);
@@ -27,17 +27,17 @@ class A extends w {
27
27
  requiresAuth() {
28
28
  return !!this.config.apiKey;
29
29
  }
30
- async makeRequest(n, t, r) {
31
- const e = n.model, d = { ...n };
30
+ async makeRequest(r, n, t) {
31
+ const e = r.model, d = { ...r };
32
32
  delete d.model;
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));
33
+ const i = `${this.config.baseUrl}/model/${encodeURIComponent(e)}/invoke`, l = n ? { signal: n } : new AbortController();
34
+ n || (t = t || this.generateRequestId(), this.activeRequests.set(t, l));
35
35
  try {
36
36
  const o = await fetch(i, {
37
37
  method: "POST",
38
38
  headers: this.buildHeaders(),
39
39
  body: JSON.stringify(d),
40
- signal: l.signal || t
40
+ signal: l.signal || n
41
41
  });
42
42
  if (!o.ok) {
43
43
  const h = await o.text();
@@ -45,17 +45,17 @@ class A extends w {
45
45
  }
46
46
  return o.json();
47
47
  } finally {
48
- !t && r && this.activeRequests.delete(r);
48
+ !n && t && this.activeRequests.delete(t);
49
49
  }
50
50
  }
51
- async makeStreamingRequest(n, t) {
52
- const r = n.model, e = { ...n };
51
+ async makeStreamingRequest(r, n) {
52
+ const t = r.model, e = { ...r };
53
53
  delete e.model;
54
- const d = `${this.config.baseUrl}/model/${encodeURIComponent(r)}/invoke-with-response-stream`, i = await fetch(d, {
54
+ const d = `${this.config.baseUrl}/model/${encodeURIComponent(t)}/invoke-with-response-stream`, i = await fetch(d, {
55
55
  method: "POST",
56
56
  headers: this.buildHeaders(),
57
57
  body: JSON.stringify(e),
58
- signal: t
58
+ signal: n
59
59
  });
60
60
  if (!i.ok) {
61
61
  const c = await i.text();
@@ -96,11 +96,15 @@ class A extends w {
96
96
  // the control-plane host returns permissive CORS headers, so a browser fetch
97
97
  // works. When disabled (default) or on any failure, fall back to the static
98
98
  // list — existing apps keep working with zero surprise network calls.
99
- async discoverModels(n = 1e4) {
100
- if (!this.config.liveModelDiscovery || !this.getModelsEndpoint())
99
+ // `force` is set when the user explicitly clicks Refresh in the UI; it
100
+ // bypasses the opt-in `liveModelDiscovery` gate so the button actually queries
101
+ // the control plane. Automatic loads (provider change / edit) leave `force`
102
+ // unset and keep the "no surprise network calls" default.
103
+ async discoverModels(r = 1e4, { force: n = !1 } = {}) {
104
+ if (!n && !this.config.liveModelDiscovery || !this.getModelsEndpoint())
101
105
  return p.slice();
102
106
  try {
103
- const t = await super.discoverModels(n);
107
+ const t = await super.discoverModels(r);
104
108
  return t.length ? t : p.slice();
105
109
  } catch {
106
110
  return p.slice();
@@ -112,32 +116,32 @@ class A extends w {
112
116
  // no distinct control-plane host can be derived (custom/relative baseUrl),
113
117
  // which disables live discovery and leaves the static fallback in place.
114
118
  getModelsEndpoint() {
115
- const n = this.config.baseUrl || "", t = n.replace("bedrock-runtime.", "bedrock.");
116
- return !t || t === n ? null : `${t}/inference-profiles`;
119
+ const r = this.config.baseUrl || "", n = r.replace("bedrock-runtime.", "bedrock.");
120
+ return !n || n === r ? null : `${n}/inference-profiles`;
117
121
  }
118
122
  // ListInferenceProfiles returns
119
123
  // { inferenceProfileSummaries: [{ inferenceProfileId, ... }] }
120
124
  // Keep only Anthropic Claude profiles (us.* and global.*) — those ids are
121
125
  // 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();
126
+ parseModelsResponse(r) {
127
+ const n = r == null ? void 0 : r.inferenceProfileSummaries;
128
+ if (!Array.isArray(n)) return p.slice();
129
+ const t = n.map((e) => e == null ? void 0 : e.inferenceProfileId).filter((e) => typeof e == "string" && e.includes("anthropic.claude"));
130
+ return t.length ? t : p.slice();
127
131
  }
128
132
  }
129
133
  class v {
130
134
  constructor() {
131
135
  this.buf = new Uint8Array(0), this.textDecoder = new TextDecoder();
132
136
  }
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;
137
+ feed(r) {
138
+ if (r && r.length) {
139
+ const t = new Uint8Array(this.buf.length + r.length);
140
+ t.set(this.buf, 0), t.set(r, this.buf.length), this.buf = t;
137
141
  }
138
- const t = [];
142
+ const n = [];
139
143
  for (; this.buf.length >= 12; ) {
140
- const r = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength), e = r.getUint32(0, !1), d = r.getUint32(4, !1);
144
+ const t = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength), e = t.getUint32(0, !1), d = t.getUint32(4, !1);
141
145
  if (e < 16 || e > 16 * 1024 * 1024)
142
146
  throw new Error(`Bedrock event stream: invalid frame length ${e}`);
143
147
  if (this.buf.length < e) break;
@@ -152,43 +156,43 @@ class v {
152
156
  const g = f[":message-type"], m = f[":exception-type"];
153
157
  if (g === "exception" || m) {
154
158
  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}` });
159
+ n.push({ kind: "error", message: `${u}: ${b}` });
156
160
  continue;
157
161
  }
158
162
  if (a && typeof a.bytes == "string")
159
163
  try {
160
164
  const u = x(a.bytes), b = JSON.parse(u);
161
- t.push({ kind: "event", payload: b });
165
+ n.push({ kind: "event", payload: b });
162
166
  } catch (u) {
163
- t.push({ kind: "error", message: `Bedrock event-stream decode failed: ${u.message}` });
167
+ n.push({ kind: "error", message: `Bedrock event-stream decode failed: ${u.message}` });
164
168
  }
165
169
  }
166
- return t;
170
+ return n;
167
171
  }
168
172
  }
169
173
  function k(s) {
170
- const n = {}, t = new DataView(s.buffer, s.byteOffset, s.byteLength), r = new TextDecoder();
174
+ const r = {}, n = new DataView(s.buffer, s.byteOffset, s.byteLength), t = new TextDecoder();
171
175
  let e = 0;
172
176
  for (; e < s.length; ) {
173
177
  const d = s[e];
174
178
  if (e += 1, e + d > s.length) break;
175
- const i = r.decode(s.subarray(e, e + d));
179
+ const i = t.decode(s.subarray(e, e + d));
176
180
  if (e += d, e >= s.length) break;
177
181
  const l = s[e];
178
182
  if (e += 1, l === 7) {
179
183
  if (e + 2 > s.length) break;
180
- const o = t.getUint16(e, !1);
184
+ const o = n.getUint16(e, !1);
181
185
  if (e += 2, e + o > s.length) break;
182
- n[i] = r.decode(s.subarray(e, e + o)), e += o;
186
+ r[i] = t.decode(s.subarray(e, e + o)), e += o;
183
187
  } else
184
188
  break;
185
189
  }
186
- return n;
190
+ return r;
187
191
  }
188
192
  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);
193
+ const r = atob(s), n = new Uint8Array(r.length);
194
+ for (let t = 0; t < r.length; t++) n[t] = r.charCodeAt(t);
195
+ return new TextDecoder().decode(n);
192
196
  }
193
197
  export {
194
198
  p as BEDROCK_CLAUDE_MODELS,
@@ -1,14 +1,15 @@
1
- import { OpenAIProvider as i } from "./OpenAIProvider.js";
2
- import { AnthropicProvider as s } from "./AnthropicProvider.js";
3
- import { BedrockProvider as n } from "./BedrockProvider.js";
1
+ import { OpenAIProvider as o } from "./OpenAIProvider.js";
2
+ import { AnthropicProvider as n } from "./AnthropicProvider.js";
3
+ import { BedrockProvider as i } from "./BedrockProvider.js";
4
+ import { BedrockMantleProvider as p } from "./BedrockMantleProvider.js";
4
5
  import { GrokProvider as m } from "./GrokProvider.js";
5
- import { GeminiProvider as p } from "./GeminiProvider.js";
6
- import { OllamaProvider as u } from "./OllamaProvider.js";
6
+ import { GeminiProvider as u } from "./GeminiProvider.js";
7
+ import { OllamaProvider as l } from "./OllamaProvider.js";
7
8
  import { LlamaServerProvider as E } from "./LlamaServerProvider.js";
8
- import { OpenRouterProvider as l } from "./OpenRouterProvider.js";
9
- import { DeepSeekProvider as A } from "./DeepSeekProvider.js";
10
- import { CustomProvider as O } from "./CustomProvider.js";
11
- const e = {
9
+ import { OpenRouterProvider as A } from "./OpenRouterProvider.js";
10
+ import { DeepSeekProvider as O } from "./DeepSeekProvider.js";
11
+ import { CustomProvider as c } from "./CustomProvider.js";
12
+ const r = {
12
13
  OPENAI: "openai",
13
14
  ANTHROPIC: "anthropic",
14
15
  BEDROCK: "bedrock",
@@ -20,60 +21,93 @@ const e = {
20
21
  DEEPSEEK: "deepseek",
21
22
  CUSTOM: "custom"
22
23
  }, S = {
23
- [e.OPENAI]: { name: "OpenAI", baseUrl: "https://api.openai.com", requiresApiKey: !0 },
24
- [e.ANTHROPIC]: { name: "Anthropic", baseUrl: "https://api.anthropic.com", requiresApiKey: !0 },
25
- [e.BEDROCK]: { name: "AWS Bedrock", baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com", requiresApiKey: !0 },
26
- [e.GROK]: { name: "Grok", baseUrl: "https://api.x.ai", requiresApiKey: !0 },
27
- [e.GEMINI]: { name: "Google Gemini", baseUrl: "https://generativelanguage.googleapis.com", requiresApiKey: !0 },
28
- [e.OLLAMA]: { name: "Ollama (Native)", baseUrl: "http://localhost:11434", requiresApiKey: !1 },
29
- [e.LLAMA_SERVER]: { name: "Local Llama Server", baseUrl: "http://localhost:8080", requiresApiKey: !1 },
30
- [e.OPENROUTER]: { name: "OpenRouter", baseUrl: "https://openrouter.ai/api", requiresApiKey: !0 },
31
- [e.DEEPSEEK]: { name: "DeepSeek", baseUrl: "https://api.deepseek.com", requiresApiKey: !0 },
32
- [e.CUSTOM]: { name: "Custom OpenAI Compatible", baseUrl: "", requiresApiKey: !1 }
24
+ [r.OPENAI]: { name: "OpenAI", baseUrl: "https://api.openai.com", requiresApiKey: !0 },
25
+ [r.ANTHROPIC]: { name: "Anthropic", baseUrl: "https://api.anthropic.com", requiresApiKey: !0 },
26
+ [r.BEDROCK]: {
27
+ name: "AWS",
28
+ // Two backends, chosen by a UI toggle. Mantle (default) serves the whole
29
+ // catalog behind one model list via BedrockMantleProvider's auto-routing
30
+ // (Claude -> Anthropic Messages, the rest -> OpenAI Chat Completions).
31
+ // Bedrock is the classic Claude-only bedrock-runtime transport. `baseUrl`
32
+ // is derived from (backend, region) via the templates below, and
33
+ // `createProvider` picks the class from `config.backend`. The region list
34
+ // is valid on both.
35
+ baseUrl: "https://bedrock-mantle.us-east-1.api.aws",
36
+ baseUrlTemplate: "https://bedrock-mantle.{region}.api.aws",
37
+ defaultBackend: "mantle",
38
+ backends: {
39
+ mantle: { label: "Mantle", baseUrlTemplate: "https://bedrock-mantle.{region}.api.aws" },
40
+ runtime: { label: "Bedrock", baseUrlTemplate: "https://bedrock-runtime.{region}.amazonaws.com" }
41
+ },
42
+ regions: [
43
+ "us-east-1",
44
+ "us-east-2",
45
+ "us-west-2",
46
+ "eu-central-1",
47
+ "eu-west-1",
48
+ "eu-west-2",
49
+ "eu-north-1",
50
+ "eu-south-1",
51
+ "ap-northeast-1",
52
+ "ap-south-1",
53
+ "ap-southeast-2",
54
+ "ap-southeast-3",
55
+ "sa-east-1"
56
+ ],
57
+ defaultRegion: "us-east-1",
58
+ requiresApiKey: !0
59
+ },
60
+ [r.GROK]: { name: "Grok", baseUrl: "https://api.x.ai", requiresApiKey: !0 },
61
+ [r.GEMINI]: { name: "Google Gemini", baseUrl: "https://generativelanguage.googleapis.com", requiresApiKey: !0 },
62
+ [r.OLLAMA]: { name: "Ollama (Native)", baseUrl: "http://localhost:11434", requiresApiKey: !1 },
63
+ [r.LLAMA_SERVER]: { name: "Local Llama Server", baseUrl: "http://localhost:8080", requiresApiKey: !1 },
64
+ [r.OPENROUTER]: { name: "OpenRouter", baseUrl: "https://openrouter.ai/api", requiresApiKey: !0 },
65
+ [r.DEEPSEEK]: { name: "DeepSeek", baseUrl: "https://api.deepseek.com", requiresApiKey: !0 },
66
+ [r.CUSTOM]: { name: "Custom OpenAI Compatible", baseUrl: "", requiresApiKey: !1 }
33
67
  };
34
- function c(t, r) {
68
+ function d(t, e) {
35
69
  switch (t) {
36
- case e.OPENAI:
37
- return new i(r);
38
- case e.ANTHROPIC:
39
- return new s(r);
40
- case e.BEDROCK:
41
- return new n(r);
42
- case e.GROK:
43
- return new m(r);
44
- case e.GEMINI:
45
- return new p(r);
46
- case e.OLLAMA:
47
- return new u(r);
48
- case e.LLAMA_SERVER:
49
- return new E(r);
50
- case e.OPENROUTER:
51
- return new l(r);
52
- case e.DEEPSEEK:
53
- return new A(r);
54
- case e.CUSTOM:
55
- return new O(r);
70
+ case r.OPENAI:
71
+ return new o(e);
72
+ case r.ANTHROPIC:
73
+ return new n(e);
74
+ case r.BEDROCK:
75
+ return (e == null ? void 0 : e.backend) === "runtime" ? new i(e) : new p(e);
76
+ case r.GROK:
77
+ return new m(e);
78
+ case r.GEMINI:
79
+ return new u(e);
80
+ case r.OLLAMA:
81
+ return new l(e);
82
+ case r.LLAMA_SERVER:
83
+ return new E(e);
84
+ case r.OPENROUTER:
85
+ return new A(e);
86
+ case r.DEEPSEEK:
87
+ return new O(e);
88
+ case r.CUSTOM:
89
+ return new c(e);
56
90
  default:
57
91
  throw new Error(`Unknown provider type: ${t}`);
58
92
  }
59
93
  }
60
94
  const a = /* @__PURE__ */ new Map();
61
- function b(t, r) {
62
- if (typeof t != "string" || !r)
95
+ function M(t, e) {
96
+ if (typeof t != "string" || !e)
63
97
  throw new Error("registerProvider requires a type string and a class reference");
64
- a.set(t, r);
98
+ a.set(t, e);
65
99
  }
66
- function N(t, r) {
100
+ function N(t, e) {
67
101
  if (a.has(t)) {
68
- const o = a.get(t);
69
- return new o(r);
102
+ const s = a.get(t);
103
+ return new s(e);
70
104
  }
71
- return c(t, r);
105
+ return d(t, e);
72
106
  }
73
107
  export {
74
108
  S as DEFAULT_CONFIGS,
75
- e as PROVIDERS,
76
- c as createProvider,
109
+ r as PROVIDERS,
110
+ d as createProvider,
77
111
  N as createProviderFlexible,
78
- b as registerProvider
112
+ M as registerProvider
79
113
  };