@anvaka/vue-llm 0.1.2 → 0.3.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 +64 -3
- package/dist/core/LLMClient.js +141 -46
- package/dist/index.js +37 -29
- package/dist/pricing/calculate.js +58 -0
- package/dist/pricing/index.js +10 -0
- package/dist/pricing/rates.js +80 -0
- package/dist/providers/AnthropicProvider.js +90 -26
- package/dist/providers/BaseProvider.js +91 -54
- package/dist/providers/BedrockProvider.js +172 -0
- package/dist/providers/CustomProvider.js +69 -28
- package/dist/providers/DeepSeekProvider.js +115 -0
- package/dist/providers/GeminiProvider.js +143 -111
- package/dist/providers/GrokProvider.js +75 -38
- package/dist/providers/LlamaServerProvider.js +72 -31
- package/dist/providers/OllamaProvider.js +117 -41
- package/dist/providers/OpenAIProvider.js +92 -38
- package/dist/providers/OpenRouterProvider.js +71 -38
- package/dist/providers/factory.js +28 -18
- package/dist/providers/index.js +13 -6
- package/dist/vue/components/LLMConfigModal.vue.js +27 -27
- package/dist/vue/components/ProviderSelector.vue.js +3 -3
- package/dist/vue/components/StoredKeysManager.vue.js +8 -8
- package/package.json +7 -2
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { BaseProvider as
|
|
2
|
-
class
|
|
1
|
+
import { BaseProvider as p } from "./BaseProvider.js";
|
|
2
|
+
class y extends p {
|
|
3
3
|
async detectCapabilities() {
|
|
4
|
-
var e;
|
|
5
|
-
(e = this.config.model) != null && e.includes("claude-3") && this.capabilities.add("vision");
|
|
4
|
+
var e, t, n, o;
|
|
5
|
+
((e = this.config.model) != null && e.includes("claude-3") || (t = this.config.model) != null && t.includes("claude-sonnet") || (n = this.config.model) != null && n.includes("claude-opus") || (o = this.config.model) != null && o.includes("claude-haiku")) && (this.capabilities.add("vision"), this.capabilities.add("tools"));
|
|
6
6
|
}
|
|
7
7
|
prepareRequest(e, t) {
|
|
8
|
-
const n = {
|
|
9
|
-
model:
|
|
8
|
+
const n = _(e), o = t.model || this.config.model || "claude-3-sonnet-20240229", i = {
|
|
9
|
+
model: o,
|
|
10
10
|
max_tokens: t.maxTokens || 1e3,
|
|
11
|
-
|
|
12
|
-
messages: e.filter((s) => s.role !== "system"),
|
|
11
|
+
messages: n,
|
|
13
12
|
stream: t.stream || !1
|
|
14
|
-
}
|
|
15
|
-
|
|
13
|
+
};
|
|
14
|
+
o.includes("claude-opus-4-7") || (i.temperature = t.temperature ?? 0.7);
|
|
15
|
+
const c = e.find((r) => r.role === "system");
|
|
16
|
+
return c && (i.system = c.content), t.tools && this.capabilities.has("tools") && (i.tools = g(t.tools), t.tool_choice && (i.tool_choice = t.tool_choice)), i;
|
|
16
17
|
}
|
|
17
18
|
processMessages(e, t) {
|
|
18
19
|
return t.images && this.capabilities.has("vision") ? this.addImagesToMessages(e, t.images) : e;
|
|
@@ -20,20 +21,24 @@ class d extends c {
|
|
|
20
21
|
addImagesToMessages(e, t) {
|
|
21
22
|
const n = e[e.length - 1];
|
|
22
23
|
if (n && n.role === "user") {
|
|
23
|
-
const
|
|
24
|
-
t.forEach((
|
|
25
|
-
|
|
24
|
+
const o = [{ type: "text", text: n.content }];
|
|
25
|
+
t.forEach((i) => {
|
|
26
|
+
o.push({
|
|
26
27
|
type: "image",
|
|
27
|
-
source: { type: "base64", media_type: "image/jpeg", data: typeof
|
|
28
|
+
source: { type: "base64", media_type: "image/jpeg", data: typeof i == "string" ? i : i.data }
|
|
28
29
|
});
|
|
29
|
-
}), n.content =
|
|
30
|
+
}), n.content = o;
|
|
30
31
|
}
|
|
31
32
|
return e;
|
|
32
33
|
}
|
|
33
34
|
processResponse(e) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const t = l(e.stop_reason), n = e.content || [], o = n.find((r) => r.type === "text"), c = n.filter((r) => r.type === "tool_use").map((r) => ({ id: r.id, name: r.name, args: r.input || {} }));
|
|
36
|
+
return {
|
|
37
|
+
content: (o == null ? void 0 : o.text) || "",
|
|
38
|
+
usage: d(e.usage),
|
|
39
|
+
finishReason: t,
|
|
40
|
+
toolCalls: c
|
|
41
|
+
};
|
|
37
42
|
}
|
|
38
43
|
parseStreamingLine(e) {
|
|
39
44
|
if (!e.startsWith("data: ")) return null;
|
|
@@ -46,13 +51,27 @@ class d extends c {
|
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
extractStreamingContent(e) {
|
|
49
|
-
var t, n, r,
|
|
54
|
+
var t, n, o, i, c, r, h, f;
|
|
50
55
|
if (e.done) return { done: !0 };
|
|
51
56
|
if (e.type === "error") {
|
|
52
|
-
const
|
|
53
|
-
throw
|
|
57
|
+
const a = ((t = e.error) == null ? void 0 : t.type) || "anthropic_error", u = new Error(((n = e.error) == null ? void 0 : n.message) || "Anthropic streaming error");
|
|
58
|
+
throw u.code = a, e.request_id && (u.requestId = e.request_id), u;
|
|
54
59
|
}
|
|
55
|
-
|
|
60
|
+
if (e.type === "message_start")
|
|
61
|
+
return { content: "", thinking: "", done: !1, usage: d((o = e.message) == null ? void 0 : o.usage), finishReason: null };
|
|
62
|
+
if (e.type === "content_block_start") {
|
|
63
|
+
const a = e.content_block;
|
|
64
|
+
return (a == null ? void 0 : a.type) === "tool_use" ? {
|
|
65
|
+
content: "",
|
|
66
|
+
done: !1,
|
|
67
|
+
toolCallDelta: { index: e.index, id: a.id, name: a.name, argsTextDelta: "" }
|
|
68
|
+
} : null;
|
|
69
|
+
}
|
|
70
|
+
return e.type === "content_block_delta" ? ((i = e.delta) == null ? void 0 : i.type) === "text_delta" ? { content: ((c = e.delta) == null ? void 0 : c.text) || "", thinking: "", done: !1, usage: null, finishReason: null } : ((r = e.delta) == null ? void 0 : r.type) === "input_json_delta" ? {
|
|
71
|
+
content: "",
|
|
72
|
+
done: !1,
|
|
73
|
+
toolCallDelta: { index: e.index, argsTextDelta: ((h = e.delta) == null ? void 0 : h.partial_json) || "" }
|
|
74
|
+
} : null : e.type === "message_delta" ? { content: "", thinking: "", done: !1, usage: d(e.usage), finishReason: l((f = e.delta) == null ? void 0 : f.stop_reason) } : e.type === "message_stop" ? { content: "", thinking: "", done: !0, usage: null, finishReason: l(e.stop_reason) } : null;
|
|
56
75
|
}
|
|
57
76
|
getApiPath() {
|
|
58
77
|
return "/v1/messages";
|
|
@@ -78,11 +97,56 @@ class d extends c {
|
|
|
78
97
|
return ((t = e.data) == null ? void 0 : t.map((n) => n.id)) || [];
|
|
79
98
|
}
|
|
80
99
|
}
|
|
81
|
-
function
|
|
82
|
-
if (!
|
|
83
|
-
const e = String(
|
|
100
|
+
function l(s) {
|
|
101
|
+
if (!s) return null;
|
|
102
|
+
const e = String(s).toLowerCase();
|
|
84
103
|
return e === "max_tokens" ? "length" : e;
|
|
85
104
|
}
|
|
105
|
+
function d(s) {
|
|
106
|
+
if (!s) return null;
|
|
107
|
+
const e = s.input_tokens ?? 0, t = s.cache_read_input_tokens ?? 0, n = s.cache_creation_input_tokens ?? 0, i = s.input_tokens != null || s.cache_read_input_tokens != null || s.cache_creation_input_tokens != null ? e + t + n : 0, c = s.output_tokens ?? 0, r = { inputTokens: i, outputTokens: c, totalTokens: i + c, raw: s };
|
|
108
|
+
return s.cache_read_input_tokens != null && (r.cachedInputTokens = t), s.cache_creation_input_tokens != null && (r.cacheCreationInputTokens = n), r;
|
|
109
|
+
}
|
|
110
|
+
function _(s) {
|
|
111
|
+
const e = [];
|
|
112
|
+
for (const t of s)
|
|
113
|
+
if (t.role !== "system") {
|
|
114
|
+
if (t.role === "assistant" && Array.isArray(t.tool_calls) && t.tool_calls.length) {
|
|
115
|
+
const n = [];
|
|
116
|
+
t.content && n.push({ type: "text", text: t.content });
|
|
117
|
+
for (const o of t.tool_calls)
|
|
118
|
+
n.push({
|
|
119
|
+
type: "tool_use",
|
|
120
|
+
id: o.id,
|
|
121
|
+
name: o.name,
|
|
122
|
+
input: o.args || {}
|
|
123
|
+
});
|
|
124
|
+
e.push({ role: "assistant", content: n });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (t.role === "tool") {
|
|
128
|
+
e.push({
|
|
129
|
+
role: "user",
|
|
130
|
+
content: [{
|
|
131
|
+
type: "tool_result",
|
|
132
|
+
tool_use_id: t.tool_call_id,
|
|
133
|
+
content: String(t.content ?? "")
|
|
134
|
+
}]
|
|
135
|
+
});
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
e.push({ role: t.role, content: t.content });
|
|
139
|
+
}
|
|
140
|
+
return e;
|
|
141
|
+
}
|
|
142
|
+
function g(s) {
|
|
143
|
+
return s.map((e) => e.type === "function" && e.function ? {
|
|
144
|
+
name: e.function.name,
|
|
145
|
+
description: e.function.description,
|
|
146
|
+
input_schema: e.function.parameters || { type: "object", properties: {} }
|
|
147
|
+
} : e);
|
|
148
|
+
}
|
|
86
149
|
export {
|
|
87
|
-
|
|
150
|
+
y as AnthropicProvider,
|
|
151
|
+
d as normalizeAnthropicUsage
|
|
88
152
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class A {
|
|
2
2
|
constructor(e) {
|
|
3
3
|
this.config = e, this.capabilities = /* @__PURE__ */ new Set(), this.activeRequests = /* @__PURE__ */ new Map();
|
|
4
4
|
}
|
|
@@ -13,73 +13,102 @@ class R {
|
|
|
13
13
|
processResponse(e) {
|
|
14
14
|
throw new Error("processResponse must be implemented by subclass");
|
|
15
15
|
}
|
|
16
|
-
async streamRequest(e, t,
|
|
17
|
-
const
|
|
18
|
-
this.activeRequests.set(
|
|
16
|
+
async streamRequest(e, t, n) {
|
|
17
|
+
const r = this.prepareRequest(e, t), o = new AbortController(), l = t.requestId || this.generateRequestId();
|
|
18
|
+
this.activeRequests.set(l, o);
|
|
19
19
|
try {
|
|
20
|
-
const
|
|
21
|
-
let
|
|
20
|
+
const k = (await this.makeStreamingRequest(r, o.signal)).body.getReader(), E = new TextDecoder();
|
|
21
|
+
let m = "", f = "", g = null, u = "";
|
|
22
|
+
const w = /* @__PURE__ */ new Map(), b = () => Array.from(w.values()).sort((a, s) => a.index - s.index).map((a) => {
|
|
23
|
+
let s = {};
|
|
24
|
+
if (a.argsText)
|
|
25
|
+
try {
|
|
26
|
+
s = JSON.parse(a.argsText);
|
|
27
|
+
} catch {
|
|
28
|
+
s = { __parseError: !0, raw: a.argsText };
|
|
29
|
+
}
|
|
30
|
+
return { id: a.id, name: a.name, args: s };
|
|
31
|
+
}), R = (p) => {
|
|
32
|
+
if (!p.trim()) return null;
|
|
33
|
+
const a = this.parseStreamingLine(p);
|
|
34
|
+
if (!a) return null;
|
|
35
|
+
const s = this.extractStreamingContent(a);
|
|
36
|
+
if (!s) return null;
|
|
37
|
+
s.content && (m += s.content), s.thinking && (f += s.thinking), s.usage && (g = q(g, s.usage));
|
|
38
|
+
const y = Array.isArray(s.toolCallDeltas) ? s.toolCallDeltas : s.toolCallDelta ? [s.toolCallDelta] : [];
|
|
39
|
+
for (const i of y) {
|
|
40
|
+
let d = w.get(i.index);
|
|
41
|
+
d ? (i.id && (d.id = i.id), i.name && (d.name = i.name)) : (d = { index: i.index, id: i.id || null, name: i.name || "", argsText: "" }, w.set(i.index, d)), i.argsTextDelta && (d.argsText += i.argsTextDelta);
|
|
42
|
+
}
|
|
43
|
+
const T = s.done || !1, C = T ? b() : null;
|
|
44
|
+
return n({
|
|
45
|
+
content: s.content || "",
|
|
46
|
+
thinking: s.thinking || "",
|
|
47
|
+
fullContent: m,
|
|
48
|
+
fullThinking: f,
|
|
49
|
+
done: T,
|
|
50
|
+
usage: s.usage || null,
|
|
51
|
+
fullUsage: g,
|
|
52
|
+
finishReason: s.finishReason || null,
|
|
53
|
+
toolCallDelta: s.toolCallDelta || null,
|
|
54
|
+
toolCalls: C
|
|
55
|
+
}), T ? "done" : null;
|
|
56
|
+
};
|
|
22
57
|
for (; ; ) {
|
|
23
|
-
const { done:
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
fullThinking: h,
|
|
36
|
-
done: o.done || !1,
|
|
37
|
-
usage: o.usage || null,
|
|
38
|
-
finishReason: o.finishReason || null
|
|
39
|
-
}), o.done))
|
|
40
|
-
return c;
|
|
58
|
+
const { done: p, value: a } = await k.read();
|
|
59
|
+
if (p) {
|
|
60
|
+
u.length > 0 && R(u);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
u += E.decode(a, { stream: !0 });
|
|
64
|
+
let s;
|
|
65
|
+
for (; (s = u.indexOf(`
|
|
66
|
+
`)) !== -1; ) {
|
|
67
|
+
const y = u.slice(0, s);
|
|
68
|
+
if (u = u.slice(s + 1), R(y) === "done")
|
|
69
|
+
return { content: m, thinking: f, toolCalls: b(), usage: g };
|
|
41
70
|
}
|
|
42
71
|
}
|
|
43
|
-
return
|
|
44
|
-
} catch (
|
|
45
|
-
throw
|
|
72
|
+
return { content: m, thinking: f, toolCalls: b(), usage: g };
|
|
73
|
+
} catch (h) {
|
|
74
|
+
throw h.name === "AbortError" ? new Error("Request cancelled") : h;
|
|
46
75
|
} finally {
|
|
47
|
-
this.activeRequests.delete(
|
|
76
|
+
this.activeRequests.delete(l);
|
|
48
77
|
}
|
|
49
78
|
}
|
|
50
|
-
async makeRequest(e, t,
|
|
51
|
-
const
|
|
52
|
-
t || (
|
|
79
|
+
async makeRequest(e, t, n) {
|
|
80
|
+
const r = t ? { signal: t } : new AbortController();
|
|
81
|
+
t || (n = n || this.generateRequestId(), this.activeRequests.set(n, r));
|
|
53
82
|
try {
|
|
54
|
-
const
|
|
83
|
+
const o = this.buildHeaders(), l = await fetch(this.getEndpoint(), {
|
|
55
84
|
method: "POST",
|
|
56
|
-
headers:
|
|
85
|
+
headers: o,
|
|
57
86
|
body: JSON.stringify(e),
|
|
58
|
-
signal:
|
|
87
|
+
signal: r.signal || t
|
|
59
88
|
});
|
|
60
|
-
if (!
|
|
61
|
-
const
|
|
62
|
-
throw new Error(`LLM API Error (${
|
|
89
|
+
if (!l.ok) {
|
|
90
|
+
const h = await l.text();
|
|
91
|
+
throw new Error(`LLM API Error (${l.status}): ${h}`);
|
|
63
92
|
}
|
|
64
|
-
return
|
|
65
|
-
} catch (
|
|
66
|
-
throw
|
|
93
|
+
return l.json();
|
|
94
|
+
} catch (o) {
|
|
95
|
+
throw o.name === "AbortError" ? new Error("Request cancelled") : o;
|
|
67
96
|
} finally {
|
|
68
|
-
!t &&
|
|
97
|
+
!t && n && this.activeRequests.delete(n);
|
|
69
98
|
}
|
|
70
99
|
}
|
|
71
100
|
async makeStreamingRequest(e, t) {
|
|
72
|
-
const
|
|
101
|
+
const n = this.buildHeaders(), r = await fetch(this.getStreamingEndpoint(), {
|
|
73
102
|
method: "POST",
|
|
74
|
-
headers:
|
|
103
|
+
headers: n,
|
|
75
104
|
body: JSON.stringify(e),
|
|
76
105
|
signal: t
|
|
77
106
|
});
|
|
78
|
-
if (!
|
|
79
|
-
const
|
|
80
|
-
throw new Error(`LLM API Error (${
|
|
107
|
+
if (!r.ok) {
|
|
108
|
+
const o = await r.text();
|
|
109
|
+
throw new Error(`LLM API Error (${r.status}): ${o}`);
|
|
81
110
|
}
|
|
82
|
-
return
|
|
111
|
+
return r;
|
|
83
112
|
}
|
|
84
113
|
buildHeaders() {
|
|
85
114
|
const e = { "Content-Type": "application/json" };
|
|
@@ -130,15 +159,15 @@ class R {
|
|
|
130
159
|
// Discover available models (override in subclass if needed)
|
|
131
160
|
async discoverModels(e = 1e4) {
|
|
132
161
|
try {
|
|
133
|
-
const t = this.buildHeaders(),
|
|
162
|
+
const t = this.buildHeaders(), n = new AbortController(), r = setTimeout(() => n.abort(), e), o = await fetch(this.getModelsEndpoint(), {
|
|
134
163
|
method: "GET",
|
|
135
164
|
headers: t,
|
|
136
|
-
signal:
|
|
165
|
+
signal: n.signal
|
|
137
166
|
});
|
|
138
|
-
if (clearTimeout(
|
|
139
|
-
throw new Error(`Failed to fetch models: ${
|
|
140
|
-
const
|
|
141
|
-
return this.parseModelsResponse(
|
|
167
|
+
if (clearTimeout(r), !o.ok)
|
|
168
|
+
throw new Error(`Failed to fetch models: ${o.status} ${o.statusText}`);
|
|
169
|
+
const l = await o.json();
|
|
170
|
+
return this.parseModelsResponse(l);
|
|
142
171
|
} catch (t) {
|
|
143
172
|
throw t.name === "AbortError" ? new Error("Model discovery timeout - please check your connection") : t;
|
|
144
173
|
}
|
|
@@ -150,6 +179,14 @@ class R {
|
|
|
150
179
|
throw new Error("parseModelsResponse must be implemented by subclass");
|
|
151
180
|
}
|
|
152
181
|
}
|
|
182
|
+
function q(c, e) {
|
|
183
|
+
if (!e) return c;
|
|
184
|
+
if (!c) return { ...e };
|
|
185
|
+
const t = { ...c }, n = ["inputTokens", "outputTokens", "totalTokens", "cachedInputTokens", "cacheCreationInputTokens", "reasoningTokens"];
|
|
186
|
+
for (const r of n)
|
|
187
|
+
e[r] != null && (t[r] = c[r] != null ? Math.max(c[r], e[r]) : e[r]);
|
|
188
|
+
return e.raw && (t.raw = e.raw), t.totalTokens == null && t.inputTokens != null && t.outputTokens != null && (t.totalTokens = t.inputTokens + t.outputTokens), t;
|
|
189
|
+
}
|
|
153
190
|
export {
|
|
154
|
-
|
|
191
|
+
A as BaseProvider
|
|
155
192
|
};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { BaseProvider as y } from "./BaseProvider.js";
|
|
2
|
+
import { AnthropicProvider as w } from "./AnthropicProvider.js";
|
|
3
|
+
const g = [
|
|
4
|
+
"us.anthropic.claude-opus-4-7",
|
|
5
|
+
"us.anthropic.claude-sonnet-4-6",
|
|
6
|
+
"us.anthropic.claude-haiku-4-5-20251001-v1:0",
|
|
7
|
+
"us.anthropic.claude-opus-4-6-v1",
|
|
8
|
+
"us.anthropic.claude-opus-4-5-20251101-v1:0",
|
|
9
|
+
"us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
10
|
+
"us.anthropic.claude-opus-4-1-20250805-v1:0"
|
|
11
|
+
];
|
|
12
|
+
class R extends w {
|
|
13
|
+
prepareRequest(r, n) {
|
|
14
|
+
const t = super.prepareRequest(r, n);
|
|
15
|
+
return delete t.stream, t.anthropic_version = "bedrock-2023-05-31", t;
|
|
16
|
+
}
|
|
17
|
+
buildHeaders() {
|
|
18
|
+
return y.prototype.buildHeaders.call(this);
|
|
19
|
+
}
|
|
20
|
+
getAuthHeaderName() {
|
|
21
|
+
return "Authorization";
|
|
22
|
+
}
|
|
23
|
+
getAuthHeaderValue() {
|
|
24
|
+
return `Bearer ${this.config.apiKey}`;
|
|
25
|
+
}
|
|
26
|
+
requiresAuth() {
|
|
27
|
+
return !!this.config.apiKey;
|
|
28
|
+
}
|
|
29
|
+
async makeRequest(r, n, t) {
|
|
30
|
+
const e = r.model, d = { ...r };
|
|
31
|
+
delete d.model;
|
|
32
|
+
const c = `${this.config.baseUrl}/model/${encodeURIComponent(e)}/invoke`, u = n ? { signal: n } : new AbortController();
|
|
33
|
+
n || (t = t || this.generateRequestId(), this.activeRequests.set(t, u));
|
|
34
|
+
try {
|
|
35
|
+
const s = await fetch(c, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: this.buildHeaders(),
|
|
38
|
+
body: JSON.stringify(d),
|
|
39
|
+
signal: u.signal || n
|
|
40
|
+
});
|
|
41
|
+
if (!s.ok) {
|
|
42
|
+
const l = await s.text();
|
|
43
|
+
throw new Error(`Bedrock API Error (${s.status}): ${l}`);
|
|
44
|
+
}
|
|
45
|
+
return s.json();
|
|
46
|
+
} finally {
|
|
47
|
+
!n && t && this.activeRequests.delete(t);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async makeStreamingRequest(r, n) {
|
|
51
|
+
const t = r.model, e = { ...r };
|
|
52
|
+
delete e.model;
|
|
53
|
+
const d = `${this.config.baseUrl}/model/${encodeURIComponent(t)}/invoke-with-response-stream`, c = await fetch(d, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: this.buildHeaders(),
|
|
56
|
+
body: JSON.stringify(e),
|
|
57
|
+
signal: n
|
|
58
|
+
});
|
|
59
|
+
if (!c.ok) {
|
|
60
|
+
const i = await c.text();
|
|
61
|
+
throw new Error(`Bedrock API Error (${c.status}): ${i}`);
|
|
62
|
+
}
|
|
63
|
+
const u = c.body.getReader(), s = new v(), l = new TextEncoder(), f = new ReadableStream({
|
|
64
|
+
async pull(i) {
|
|
65
|
+
try {
|
|
66
|
+
const { done: a, value: m } = await u.read();
|
|
67
|
+
if (a) {
|
|
68
|
+
i.close();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const p = s.feed(m);
|
|
72
|
+
for (const h of p) {
|
|
73
|
+
if (h.kind === "error") {
|
|
74
|
+
i.error(new Error(h.message));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
i.enqueue(l.encode(`data: ${JSON.stringify(h.payload)}
|
|
78
|
+
`));
|
|
79
|
+
}
|
|
80
|
+
} catch (a) {
|
|
81
|
+
i.error(a);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
cancel(i) {
|
|
85
|
+
try {
|
|
86
|
+
u.cancel(i);
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return new Response(f, { status: 200, headers: { "Content-Type": "text/event-stream" } });
|
|
92
|
+
}
|
|
93
|
+
// Bedrock control plane needs SigV4; Bearer auth can't list models.
|
|
94
|
+
// Return the hardcoded list so the dropdown still populates.
|
|
95
|
+
async discoverModels() {
|
|
96
|
+
return g.slice();
|
|
97
|
+
}
|
|
98
|
+
getModelsEndpoint() {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
parseModelsResponse() {
|
|
102
|
+
return g.slice();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
class v {
|
|
106
|
+
constructor() {
|
|
107
|
+
this.buf = new Uint8Array(0), this.textDecoder = new TextDecoder();
|
|
108
|
+
}
|
|
109
|
+
feed(r) {
|
|
110
|
+
if (r && r.length) {
|
|
111
|
+
const t = new Uint8Array(this.buf.length + r.length);
|
|
112
|
+
t.set(this.buf, 0), t.set(r, this.buf.length), this.buf = t;
|
|
113
|
+
}
|
|
114
|
+
const n = [];
|
|
115
|
+
for (; this.buf.length >= 12; ) {
|
|
116
|
+
const t = new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength), e = t.getUint32(0, !1), d = t.getUint32(4, !1);
|
|
117
|
+
if (e < 16 || e > 16 * 1024 * 1024)
|
|
118
|
+
throw new Error(`Bedrock event stream: invalid frame length ${e}`);
|
|
119
|
+
if (this.buf.length < e) break;
|
|
120
|
+
const c = 12, u = c + d, s = u, l = e - 4, f = k(this.buf.subarray(c, u)), i = this.textDecoder.decode(this.buf.subarray(s, l));
|
|
121
|
+
this.buf = this.buf.subarray(e);
|
|
122
|
+
let a;
|
|
123
|
+
try {
|
|
124
|
+
a = JSON.parse(i);
|
|
125
|
+
} catch {
|
|
126
|
+
a = null;
|
|
127
|
+
}
|
|
128
|
+
const m = f[":message-type"], p = f[":exception-type"];
|
|
129
|
+
if (m === "exception" || p) {
|
|
130
|
+
const h = p || f[":event-type"] || "BedrockStreamException", b = (a == null ? void 0 : a.message) || i || "unknown error";
|
|
131
|
+
n.push({ kind: "error", message: `${h}: ${b}` });
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (a && typeof a.bytes == "string")
|
|
135
|
+
try {
|
|
136
|
+
const h = x(a.bytes), b = JSON.parse(h);
|
|
137
|
+
n.push({ kind: "event", payload: b });
|
|
138
|
+
} catch (h) {
|
|
139
|
+
n.push({ kind: "error", message: `Bedrock event-stream decode failed: ${h.message}` });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return n;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function k(o) {
|
|
146
|
+
const r = {}, n = new DataView(o.buffer, o.byteOffset, o.byteLength), t = new TextDecoder();
|
|
147
|
+
let e = 0;
|
|
148
|
+
for (; e < o.length; ) {
|
|
149
|
+
const d = o[e];
|
|
150
|
+
if (e += 1, e + d > o.length) break;
|
|
151
|
+
const c = t.decode(o.subarray(e, e + d));
|
|
152
|
+
if (e += d, e >= o.length) break;
|
|
153
|
+
const u = o[e];
|
|
154
|
+
if (e += 1, u === 7) {
|
|
155
|
+
if (e + 2 > o.length) break;
|
|
156
|
+
const s = n.getUint16(e, !1);
|
|
157
|
+
if (e += 2, e + s > o.length) break;
|
|
158
|
+
r[c] = t.decode(o.subarray(e, e + s)), e += s;
|
|
159
|
+
} else
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
return r;
|
|
163
|
+
}
|
|
164
|
+
function x(o) {
|
|
165
|
+
const r = atob(o), n = new Uint8Array(r.length);
|
|
166
|
+
for (let t = 0; t < r.length; t++) n[t] = r.charCodeAt(t);
|
|
167
|
+
return new TextDecoder().decode(n);
|
|
168
|
+
}
|
|
169
|
+
export {
|
|
170
|
+
g as BEDROCK_CLAUDE_MODELS,
|
|
171
|
+
R as BedrockProvider
|
|
172
|
+
};
|
|
@@ -1,33 +1,66 @@
|
|
|
1
|
-
import { BaseProvider as
|
|
2
|
-
|
|
1
|
+
import { BaseProvider as d } from "./BaseProvider.js";
|
|
2
|
+
import { convertMessagesToOpenAI as g, normalizeOpenAIUsage as u } from "./OpenAIProvider.js";
|
|
3
|
+
class A extends d {
|
|
3
4
|
async detectCapabilities() {
|
|
5
|
+
this.capabilities.add("tools");
|
|
4
6
|
}
|
|
5
|
-
prepareRequest(
|
|
6
|
-
|
|
7
|
-
model:
|
|
8
|
-
messages:
|
|
9
|
-
temperature:
|
|
10
|
-
max_tokens:
|
|
11
|
-
stream:
|
|
7
|
+
prepareRequest(n, e) {
|
|
8
|
+
const t = {
|
|
9
|
+
model: e.model || this.config.model || "gpt-3.5-turbo",
|
|
10
|
+
messages: g(n),
|
|
11
|
+
temperature: e.temperature ?? 0.7,
|
|
12
|
+
max_tokens: e.maxTokens || 1e3,
|
|
13
|
+
stream: e.stream || !1
|
|
12
14
|
};
|
|
15
|
+
return t.stream && (t.stream_options = { include_usage: !0 }), e.tools && this.capabilities.has("tools") && (t.tools = e.tools, e.tool_choice && (t.tool_choice = e.tool_choice)), t;
|
|
13
16
|
}
|
|
14
|
-
processResponse(
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
+
processResponse(n) {
|
|
18
|
+
var s, o, i, a;
|
|
19
|
+
const e = (o = (s = n.choices) == null ? void 0 : s[0]) == null ? void 0 : o.message, t = {
|
|
20
|
+
content: (e == null ? void 0 : e.content) || "",
|
|
21
|
+
usage: u(n.usage),
|
|
22
|
+
finishReason: c((a = (i = n.choices) == null ? void 0 : i[0]) == null ? void 0 : a.finish_reason)
|
|
23
|
+
};
|
|
24
|
+
return Array.isArray(e == null ? void 0 : e.tool_calls) && (t.toolCalls = e.tool_calls.map((l) => {
|
|
25
|
+
var f, m;
|
|
26
|
+
return {
|
|
27
|
+
id: l.id,
|
|
28
|
+
name: (f = l.function) == null ? void 0 : f.name,
|
|
29
|
+
args: h((m = l.function) == null ? void 0 : m.arguments)
|
|
30
|
+
};
|
|
31
|
+
})), t;
|
|
17
32
|
}
|
|
18
|
-
parseStreamingLine(
|
|
19
|
-
if (!
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
33
|
+
parseStreamingLine(n) {
|
|
34
|
+
if (!n.startsWith("data: ")) return null;
|
|
35
|
+
const e = n.slice(6).trim();
|
|
36
|
+
if (e === "[DONE]") return { done: !0 };
|
|
22
37
|
try {
|
|
23
|
-
return JSON.parse(
|
|
38
|
+
return JSON.parse(e);
|
|
24
39
|
} catch {
|
|
25
40
|
return null;
|
|
26
41
|
}
|
|
27
42
|
}
|
|
28
|
-
extractStreamingContent(
|
|
29
|
-
var
|
|
30
|
-
|
|
43
|
+
extractStreamingContent(n) {
|
|
44
|
+
var s, o, i;
|
|
45
|
+
if (n.done) return { done: !0 };
|
|
46
|
+
const e = (s = n.choices) == null ? void 0 : s[0], t = e == null ? void 0 : e.delta;
|
|
47
|
+
if (t && Array.isArray(t.tool_calls) && t.tool_calls.length) {
|
|
48
|
+
const a = t.tool_calls[0];
|
|
49
|
+
return {
|
|
50
|
+
content: t.content || "",
|
|
51
|
+
thinking: "",
|
|
52
|
+
done: !1,
|
|
53
|
+
usage: u(n.usage),
|
|
54
|
+
finishReason: c(e == null ? void 0 : e.finish_reason),
|
|
55
|
+
toolCallDelta: {
|
|
56
|
+
index: a.index ?? 0,
|
|
57
|
+
id: a.id || void 0,
|
|
58
|
+
name: ((o = a.function) == null ? void 0 : o.name) || void 0,
|
|
59
|
+
argsTextDelta: ((i = a.function) == null ? void 0 : i.arguments) || ""
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return { content: (t == null ? void 0 : t.content) || "", thinking: "", done: !1, usage: u(n.usage), finishReason: c(e == null ? void 0 : e.finish_reason) };
|
|
31
64
|
}
|
|
32
65
|
getApiPath() {
|
|
33
66
|
return "/v1/chat/completions";
|
|
@@ -38,16 +71,24 @@ class l extends u {
|
|
|
38
71
|
getModelsEndpoint() {
|
|
39
72
|
return `${this.config.baseUrl}/v1/models`;
|
|
40
73
|
}
|
|
41
|
-
parseModelsResponse(
|
|
42
|
-
var
|
|
43
|
-
return ((
|
|
74
|
+
parseModelsResponse(n) {
|
|
75
|
+
var e, t;
|
|
76
|
+
return ((t = (e = n.data) == null ? void 0 : e.map((s) => s.id)) == null ? void 0 : t.sort()) || [];
|
|
44
77
|
}
|
|
45
78
|
}
|
|
46
|
-
function
|
|
47
|
-
if (!
|
|
48
|
-
const
|
|
49
|
-
return
|
|
79
|
+
function c(r) {
|
|
80
|
+
if (!r) return null;
|
|
81
|
+
const n = String(r).toLowerCase();
|
|
82
|
+
return n === "max_tokens" ? "length" : n;
|
|
83
|
+
}
|
|
84
|
+
function h(r) {
|
|
85
|
+
if (!r) return {};
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(r);
|
|
88
|
+
} catch {
|
|
89
|
+
return { __parseError: !0, raw: r };
|
|
90
|
+
}
|
|
50
91
|
}
|
|
51
92
|
export {
|
|
52
|
-
|
|
93
|
+
A as CustomProvider
|
|
53
94
|
};
|