@anvaka/vue-llm 0.1.1 → 0.2.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/dist/core/LLMClient.js +94 -28
- package/dist/providers/AnthropicProvider.js +76 -21
- package/dist/providers/BaseProvider.js +89 -62
- package/dist/providers/BedrockProvider.js +172 -0
- package/dist/providers/CustomProvider.js +1 -1
- package/dist/providers/GeminiProvider.js +1 -1
- package/dist/providers/GrokProvider.js +1 -1
- package/dist/providers/LlamaServerProvider.js +1 -1
- package/dist/providers/OllamaProvider.js +1 -1
- package/dist/providers/OpenAIProvider.js +82 -35
- package/dist/providers/OpenRouterProvider.js +72 -39
- package/dist/providers/factory.js +23 -18
- package/dist/providers/index.js +11 -6
- package/dist/vue/components/LLMConfigModal.vue.js +114 -110
- package/dist/vue/components/ProviderSelector.vue.js +3 -3
- package/dist/vue/components/StoredKeysManager.vue.js +8 -8
- package/dist/vue-llm.css +1 -1
- package/package.json +1 -1
package/dist/core/LLMClient.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createProviderFlexible as I } from "../providers/factory.js";
|
|
2
|
-
class
|
|
2
|
+
class $ {
|
|
3
3
|
constructor({ configStore: t, logger: s } = {}) {
|
|
4
4
|
this.configStore = t, this.logger = s || console, this.config = null, this.provider = null, this.usageTracker = null;
|
|
5
5
|
}
|
|
@@ -25,11 +25,11 @@ class A {
|
|
|
25
25
|
], n = this.validateCapabilities({
|
|
26
26
|
model: this.config.model,
|
|
27
27
|
enableThinking: !1,
|
|
28
|
-
temperature: 0.1,
|
|
28
|
+
temperature: t.temperature ?? 0.1,
|
|
29
29
|
maxTokens: 10,
|
|
30
30
|
stream: !1
|
|
31
|
-
}), o = this.provider.prepareRequest(e, n),
|
|
32
|
-
return (r = this.provider.processResponse(
|
|
31
|
+
}), o = this.provider.prepareRequest(e, n), l = await this.provider.makeRequest(o);
|
|
32
|
+
return (r = this.provider.processResponse(l).content) == null ? void 0 : r.trim();
|
|
33
33
|
} finally {
|
|
34
34
|
this.config = s, this.provider = i;
|
|
35
35
|
}
|
|
@@ -66,7 +66,7 @@ class A {
|
|
|
66
66
|
{ role: "user", content: "ping" }
|
|
67
67
|
], s = this.validateCapabilities({
|
|
68
68
|
model: this.config.model,
|
|
69
|
-
temperature: 0.1,
|
|
69
|
+
temperature: this.config.temperature ?? 0.1,
|
|
70
70
|
maxTokens: 10,
|
|
71
71
|
stream: !1
|
|
72
72
|
}), i = this.provider.prepareRequest(t, s), r = await this.provider.makeRequest(i);
|
|
@@ -80,6 +80,72 @@ class A {
|
|
|
80
80
|
e = n.fullContent, s && s(n);
|
|
81
81
|
}), e;
|
|
82
82
|
}
|
|
83
|
+
// Multi-turn tool-calling loop. Each iteration:
|
|
84
|
+
// 1) stream a model response (text + accumulated tool_calls)
|
|
85
|
+
// 2) append the assistant message to the conversation
|
|
86
|
+
// 3) if no tool calls → stop (the model is done)
|
|
87
|
+
// 4) otherwise execute each tool via `executors[name](args)` and append
|
|
88
|
+
// a tool message per call, then loop
|
|
89
|
+
//
|
|
90
|
+
// `tools` is OpenAI-style ([{type:'function', function:{name, description, parameters}}]).
|
|
91
|
+
// Providers translate to native format. The caller passes `executors` as a
|
|
92
|
+
// `{ name -> async (args) => result }` map. Results are stringified into the
|
|
93
|
+
// tool message content (or used verbatim if the executor already returns a
|
|
94
|
+
// string).
|
|
95
|
+
//
|
|
96
|
+
// `onEvent` (optional) fires for: iter-start, text-delta, tool-call-delta,
|
|
97
|
+
// assistant-message, tool-call, tool-result, stop. Use it to drive a trace UI.
|
|
98
|
+
async runAgentLoop({
|
|
99
|
+
messages: t,
|
|
100
|
+
tools: s,
|
|
101
|
+
executors: i,
|
|
102
|
+
onEvent: r,
|
|
103
|
+
maxIters: e = 10,
|
|
104
|
+
temperature: n,
|
|
105
|
+
model: o,
|
|
106
|
+
maxTokens: l,
|
|
107
|
+
enableThinking: u
|
|
108
|
+
} = {}) {
|
|
109
|
+
if (await this.ensureInitialized(), !this.provider.hasCapability("tools"))
|
|
110
|
+
throw new Error("Configured provider does not support tools");
|
|
111
|
+
const h = t.slice();
|
|
112
|
+
let c = 0, m = null;
|
|
113
|
+
for (; c < e; ) {
|
|
114
|
+
c++, r && r({ type: "iter-start", iter: c });
|
|
115
|
+
const b = this.validateCapabilities({
|
|
116
|
+
messages: h,
|
|
117
|
+
tools: s,
|
|
118
|
+
stream: !0,
|
|
119
|
+
model: o || this.config.model,
|
|
120
|
+
temperature: n ?? this.config.temperature,
|
|
121
|
+
maxTokens: l ?? this.config.maxTokens ?? 4096,
|
|
122
|
+
enableThinking: u ?? !1,
|
|
123
|
+
requestId: this.generateRequestId()
|
|
124
|
+
}), p = await this.provider.streamRequest(h, b, (a) => {
|
|
125
|
+
a.content && r && r({ type: "text-delta", text: a.content }), a.toolCallDelta && r && r({ type: "tool-call-delta", delta: a.toolCallDelta });
|
|
126
|
+
}), v = (p == null ? void 0 : p.content) || "", d = (p == null ? void 0 : p.toolCalls) || [], w = { role: "assistant", content: v };
|
|
127
|
+
if (d.length && (w.tool_calls = d), h.push(w), r && r({ type: "assistant-message", content: v, toolCalls: d }), !d.length) {
|
|
128
|
+
m = "no-tool-calls";
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
for (const a of d) {
|
|
132
|
+
r && r({ type: "tool-call", id: a.id, name: a.name, args: a.args });
|
|
133
|
+
const _ = i && i[a.name];
|
|
134
|
+
let y;
|
|
135
|
+
if (!_)
|
|
136
|
+
y = `Error: unknown tool '${a.name}'`;
|
|
137
|
+
else
|
|
138
|
+
try {
|
|
139
|
+
const f = await _(a.args || {});
|
|
140
|
+
y = typeof f == "string" ? f : JSON.stringify(f ?? "");
|
|
141
|
+
} catch (f) {
|
|
142
|
+
y = `Error: ${(f == null ? void 0 : f.message) || String(f)}`;
|
|
143
|
+
}
|
|
144
|
+
h.push({ role: "tool", tool_call_id: a.id, content: y }), r && r({ type: "tool-result", id: a.id, name: a.name, content: y });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return m || (m = "max-iters"), r && r({ type: "stop", reason: m, iterations: c }), { messages: h, iterations: c, stopReason: m };
|
|
148
|
+
}
|
|
83
149
|
generateRequestId() {
|
|
84
150
|
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
85
151
|
}
|
|
@@ -163,11 +229,11 @@ class S {
|
|
|
163
229
|
};
|
|
164
230
|
try {
|
|
165
231
|
if (this.targetNode) {
|
|
166
|
-
const
|
|
167
|
-
return await this._streamIntoTarget(e,
|
|
232
|
+
const u = r({ ...n, stream: !0 });
|
|
233
|
+
return await this._streamIntoTarget(e, u, s, i);
|
|
168
234
|
}
|
|
169
|
-
const
|
|
170
|
-
return await this._promiseResponse(e,
|
|
235
|
+
const l = r({ ...n, stream: !1 });
|
|
236
|
+
return await this._promiseResponse(e, l, s, i);
|
|
171
237
|
} finally {
|
|
172
238
|
(o = t.cleanup) == null || o.call(t);
|
|
173
239
|
}
|
|
@@ -182,13 +248,13 @@ class S {
|
|
|
182
248
|
throw new Error("Provider presets require a configured ConfigStore instance");
|
|
183
249
|
const s = (e = (r = this.client).getConfigByName) == null ? void 0 : e.call(r, t);
|
|
184
250
|
if (!s) {
|
|
185
|
-
const
|
|
186
|
-
throw new Error(`Provider preset '${t}' not found.${
|
|
251
|
+
const l = (((o = (n = this.client.configStore).getEnabledConfigs) == null ? void 0 : o.call(n)) || []).map((h) => h.name || `${h.provider} (${h.baseUrl})`).filter(Boolean), u = l.length ? ` Available presets: ${l.join(", ")}` : " No configured providers found.";
|
|
252
|
+
throw new Error(`Provider preset '${t}' not found.${u}`);
|
|
187
253
|
}
|
|
188
254
|
const i = I(s.provider, s);
|
|
189
255
|
return await i.initialize(), { provider: i, config: s, cleanup: () => {
|
|
190
|
-
var
|
|
191
|
-
return (
|
|
256
|
+
var l;
|
|
257
|
+
return (l = i.cancelAllRequests) == null ? void 0 : l.call(i);
|
|
192
258
|
} };
|
|
193
259
|
}
|
|
194
260
|
_resolvePresetName() {
|
|
@@ -205,30 +271,30 @@ class S {
|
|
|
205
271
|
}
|
|
206
272
|
}
|
|
207
273
|
async _streamIntoTarget(t, s, i, r) {
|
|
208
|
-
var c, m,
|
|
274
|
+
var c, m, b, p, v, d, w, a, _, y, f, C, T, k;
|
|
209
275
|
let e, n;
|
|
210
276
|
typeof this.targetNode == "string" ? (n = this.targetNode, e = this.contextNode.createChild(n), (c = e.setSelected) == null || c.call(e)) : (e = this.targetNode, n = ((m = e.getText) == null ? void 0 : m.call(e)) || ""), this._applyAttributes(e);
|
|
211
277
|
const o = r == null ? void 0 : r.name;
|
|
212
|
-
o && e.addTag && e.addTag("provider", o), (
|
|
278
|
+
o && e.addTag && e.addTag("provider", o), (b = e.addLLMLog) == null || b.call(e, this.operationName || "streaming-request", {
|
|
213
279
|
provider: r == null ? void 0 : r.provider,
|
|
214
280
|
model: r == null ? void 0 : r.model,
|
|
215
281
|
messages: t,
|
|
216
282
|
options: s
|
|
217
|
-
}), (
|
|
218
|
-
let
|
|
283
|
+
}), (p = e.setStreamingState) == null || p.call(e, !0), e._activeRequestId = s.requestId;
|
|
284
|
+
let l = "", u = null, h = 0;
|
|
219
285
|
try {
|
|
220
|
-
return await i.streamRequest(t, s, (
|
|
221
|
-
var
|
|
222
|
-
|
|
223
|
-
}), (
|
|
224
|
-
} catch (
|
|
225
|
-
throw (
|
|
286
|
+
return await i.streamRequest(t, s, (g) => {
|
|
287
|
+
var x, q, R;
|
|
288
|
+
g.content && (l = g.fullContent, (x = e.setText) == null || x.call(e, l)), (q = g.usage) != null && q.tokens && (h += g.usage.tokens), g.finishReason && (u = g.finishReason), g.done && ((R = e.setStreamingState) == null || R.call(e, !1), e._activeRequestId = null);
|
|
289
|
+
}), (v = e.addLLMLog) == null || v.call(e, (this.operationName || "streaming-request") + "-response", { requestId: s.requestId }, { content: l, usage: { tokens: h } }), u === "length" ? ((d = e.setAttribute) == null || d.call(e, "_truncated", !0), (w = e.addLog) == null || w.call(e, "Response truncated. Increase Max Tokens.", "warn", { finish_reason: "length" })) : (a = e.setAttribute) == null || a.call(e, "_truncated", !1), await ((_ = e.persistNow) == null ? void 0 : _.call(e)), e;
|
|
290
|
+
} catch (g) {
|
|
291
|
+
throw (y = e.addLLMLog) == null || y.call(e, (this.operationName || "streaming-request") + "-error", { requestId: s.requestId }, null, g), (f = e.setStreamingState) == null || f.call(e, !1), e._activeRequestId = null, (C = e.setText) == null || C.call(e, `Error: ${g.message}`), (T = e.setAttribute) == null || T.call(e, "_truncated", !1), await ((k = e.persistNow) == null ? void 0 : k.call(e)), g;
|
|
226
292
|
}
|
|
227
293
|
}
|
|
228
294
|
async _promiseResponse(t, s, i, r) {
|
|
229
|
-
var
|
|
295
|
+
var u, h, c, m, b, p, v;
|
|
230
296
|
const e = i.prepareRequest(t, s), n = await i.makeRequest(e), o = i.processResponse(n);
|
|
231
|
-
if ((o.finishReason || ((
|
|
297
|
+
if ((o.finishReason || ((h = (u = n == null ? void 0 : n.choices) == null ? void 0 : u[0]) == null ? void 0 : h.finish_reason) || null) === "length")
|
|
232
298
|
try {
|
|
233
299
|
this.contextNode.setAttribute("_truncated", !0);
|
|
234
300
|
} catch (d) {
|
|
@@ -238,11 +304,11 @@ class S {
|
|
|
238
304
|
try {
|
|
239
305
|
this.contextNode.setAttribute("_truncated", !1);
|
|
240
306
|
} catch (d) {
|
|
241
|
-
(
|
|
307
|
+
(p = (b = this.client.logger) == null ? void 0 : b.warn) == null || p.call(b, "Unable to clear truncated marker on node", { error: d });
|
|
242
308
|
}
|
|
243
|
-
return ((
|
|
309
|
+
return ((v = o.content) == null ? void 0 : v.trim()) || "";
|
|
244
310
|
}
|
|
245
311
|
}
|
|
246
312
|
export {
|
|
247
|
-
|
|
313
|
+
$ as LLMClient
|
|
248
314
|
};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { BaseProvider as
|
|
2
|
-
class
|
|
1
|
+
import { BaseProvider as f } from "./BaseProvider.js";
|
|
2
|
+
class m extends f {
|
|
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 = {
|
|
8
|
+
const n = h(e), o = {
|
|
9
9
|
model: t.model || this.config.model || "claude-3-sonnet-20240229",
|
|
10
10
|
max_tokens: t.maxTokens || 1e3,
|
|
11
|
-
temperature: t.temperature
|
|
12
|
-
messages:
|
|
11
|
+
temperature: t.temperature ?? 0.7,
|
|
12
|
+
messages: n,
|
|
13
13
|
stream: t.stream || !1
|
|
14
|
-
},
|
|
15
|
-
return
|
|
14
|
+
}, s = e.find((l) => l.role === "system");
|
|
15
|
+
return s && (o.system = s.content), t.tools && this.capabilities.has("tools") && (o.tools = p(t.tools), t.tool_choice && (o.tool_choice = t.tool_choice)), o;
|
|
16
16
|
}
|
|
17
17
|
processMessages(e, t) {
|
|
18
18
|
return t.images && this.capabilities.has("vision") ? this.addImagesToMessages(e, t.images) : e;
|
|
@@ -20,20 +20,24 @@ class d extends c {
|
|
|
20
20
|
addImagesToMessages(e, t) {
|
|
21
21
|
const n = e[e.length - 1];
|
|
22
22
|
if (n && n.role === "user") {
|
|
23
|
-
const
|
|
23
|
+
const o = [{ type: "text", text: n.content }];
|
|
24
24
|
t.forEach((s) => {
|
|
25
|
-
|
|
25
|
+
o.push({
|
|
26
26
|
type: "image",
|
|
27
27
|
source: { type: "base64", media_type: "image/jpeg", data: typeof s == "string" ? s : s.data }
|
|
28
28
|
});
|
|
29
|
-
}), n.content =
|
|
29
|
+
}), n.content = o;
|
|
30
30
|
}
|
|
31
31
|
return e;
|
|
32
32
|
}
|
|
33
33
|
processResponse(e) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const t = u(e.stop_reason), n = e.content || [], o = n.find((r) => r.type === "text"), l = n.filter((r) => r.type === "tool_use").map((r) => ({ id: r.id, name: r.name, args: r.input || {} }));
|
|
35
|
+
return {
|
|
36
|
+
content: (o == null ? void 0 : o.text) || "",
|
|
37
|
+
usage: e.usage || null,
|
|
38
|
+
finishReason: t,
|
|
39
|
+
toolCalls: l
|
|
40
|
+
};
|
|
37
41
|
}
|
|
38
42
|
parseStreamingLine(e) {
|
|
39
43
|
if (!e.startsWith("data: ")) return null;
|
|
@@ -46,13 +50,25 @@ class d extends c {
|
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
extractStreamingContent(e) {
|
|
49
|
-
var t, n, r,
|
|
53
|
+
var t, n, o, s, l, r, d;
|
|
50
54
|
if (e.done) return { done: !0 };
|
|
51
55
|
if (e.type === "error") {
|
|
52
|
-
const
|
|
53
|
-
throw
|
|
56
|
+
const a = ((t = e.error) == null ? void 0 : t.type) || "anthropic_error", c = new Error(((n = e.error) == null ? void 0 : n.message) || "Anthropic streaming error");
|
|
57
|
+
throw c.code = a, e.request_id && (c.requestId = e.request_id), c;
|
|
54
58
|
}
|
|
55
|
-
|
|
59
|
+
if (e.type === "content_block_start") {
|
|
60
|
+
const a = e.content_block;
|
|
61
|
+
return (a == null ? void 0 : a.type) === "tool_use" ? {
|
|
62
|
+
content: "",
|
|
63
|
+
done: !1,
|
|
64
|
+
toolCallDelta: { index: e.index, id: a.id, name: a.name, argsTextDelta: "" }
|
|
65
|
+
} : null;
|
|
66
|
+
}
|
|
67
|
+
return e.type === "content_block_delta" ? ((o = e.delta) == null ? void 0 : o.type) === "text_delta" ? { content: ((s = e.delta) == null ? void 0 : s.text) || "", thinking: "", done: !1, usage: null, finishReason: null } : ((l = e.delta) == null ? void 0 : l.type) === "input_json_delta" ? {
|
|
68
|
+
content: "",
|
|
69
|
+
done: !1,
|
|
70
|
+
toolCallDelta: { index: e.index, argsTextDelta: ((r = e.delta) == null ? void 0 : r.partial_json) || "" }
|
|
71
|
+
} : null : e.type === "message_delta" ? { content: "", thinking: "", done: !1, usage: e.usage ? { tokens: e.usage.output_tokens || 0 } : null, finishReason: u((d = e.delta) == null ? void 0 : d.stop_reason) } : e.type === "message_stop" ? { content: "", thinking: "", done: !0, usage: null, finishReason: u(e.stop_reason) } : null;
|
|
56
72
|
}
|
|
57
73
|
getApiPath() {
|
|
58
74
|
return "/v1/messages";
|
|
@@ -78,11 +94,50 @@ class d extends c {
|
|
|
78
94
|
return ((t = e.data) == null ? void 0 : t.map((n) => n.id)) || [];
|
|
79
95
|
}
|
|
80
96
|
}
|
|
81
|
-
function
|
|
97
|
+
function u(i) {
|
|
82
98
|
if (!i) return null;
|
|
83
99
|
const e = String(i).toLowerCase();
|
|
84
100
|
return e === "max_tokens" ? "length" : e;
|
|
85
101
|
}
|
|
102
|
+
function h(i) {
|
|
103
|
+
const e = [];
|
|
104
|
+
for (const t of i)
|
|
105
|
+
if (t.role !== "system") {
|
|
106
|
+
if (t.role === "assistant" && Array.isArray(t.tool_calls) && t.tool_calls.length) {
|
|
107
|
+
const n = [];
|
|
108
|
+
t.content && n.push({ type: "text", text: t.content });
|
|
109
|
+
for (const o of t.tool_calls)
|
|
110
|
+
n.push({
|
|
111
|
+
type: "tool_use",
|
|
112
|
+
id: o.id,
|
|
113
|
+
name: o.name,
|
|
114
|
+
input: o.args || {}
|
|
115
|
+
});
|
|
116
|
+
e.push({ role: "assistant", content: n });
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (t.role === "tool") {
|
|
120
|
+
e.push({
|
|
121
|
+
role: "user",
|
|
122
|
+
content: [{
|
|
123
|
+
type: "tool_result",
|
|
124
|
+
tool_use_id: t.tool_call_id,
|
|
125
|
+
content: String(t.content ?? "")
|
|
126
|
+
}]
|
|
127
|
+
});
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
e.push({ role: t.role, content: t.content });
|
|
131
|
+
}
|
|
132
|
+
return e;
|
|
133
|
+
}
|
|
134
|
+
function p(i) {
|
|
135
|
+
return i.map((e) => e.type === "function" && e.function ? {
|
|
136
|
+
name: e.function.name,
|
|
137
|
+
description: e.function.description,
|
|
138
|
+
input_schema: e.function.parameters || { type: "object", properties: {} }
|
|
139
|
+
} : e);
|
|
140
|
+
}
|
|
86
141
|
export {
|
|
87
|
-
|
|
142
|
+
m as AnthropicProvider
|
|
88
143
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class q {
|
|
2
2
|
constructor(e) {
|
|
3
3
|
this.config = e, this.capabilities = /* @__PURE__ */ new Set(), this.activeRequests = /* @__PURE__ */ new Map();
|
|
4
4
|
}
|
|
@@ -7,79 +7,106 @@ class R {
|
|
|
7
7
|
}
|
|
8
8
|
async detectCapabilities() {
|
|
9
9
|
}
|
|
10
|
-
prepareRequest(e,
|
|
10
|
+
prepareRequest(e, r) {
|
|
11
11
|
throw new Error("prepareRequest must be implemented by subclass");
|
|
12
12
|
}
|
|
13
13
|
processResponse(e) {
|
|
14
14
|
throw new Error("processResponse must be implemented by subclass");
|
|
15
15
|
}
|
|
16
|
-
async streamRequest(e,
|
|
17
|
-
const
|
|
18
|
-
this.activeRequests.set(
|
|
16
|
+
async streamRequest(e, r, n) {
|
|
17
|
+
const a = this.prepareRequest(e, r), s = new AbortController(), l = r.requestId || this.generateRequestId();
|
|
18
|
+
this.activeRequests.set(l, s);
|
|
19
19
|
try {
|
|
20
|
-
const
|
|
21
|
-
let
|
|
20
|
+
const y = (await this.makeStreamingRequest(a, s.signal)).body.getReader(), R = new TextDecoder();
|
|
21
|
+
let p = "", w = "", c = "";
|
|
22
|
+
const g = /* @__PURE__ */ new Map(), f = () => Array.from(g.values()).sort((o, t) => o.index - t.index).map((o) => {
|
|
23
|
+
let t = {};
|
|
24
|
+
if (o.argsText)
|
|
25
|
+
try {
|
|
26
|
+
t = JSON.parse(o.argsText);
|
|
27
|
+
} catch {
|
|
28
|
+
t = { __parseError: !0, raw: o.argsText };
|
|
29
|
+
}
|
|
30
|
+
return { id: o.id, name: o.name, args: t };
|
|
31
|
+
}), b = (h) => {
|
|
32
|
+
if (!h.trim()) return null;
|
|
33
|
+
const o = this.parseStreamingLine(h);
|
|
34
|
+
if (!o) return null;
|
|
35
|
+
const t = this.extractStreamingContent(o);
|
|
36
|
+
if (!t) return null;
|
|
37
|
+
if (t.content && (p += t.content), t.thinking && (w += t.thinking), t.toolCallDelta) {
|
|
38
|
+
const i = t.toolCallDelta;
|
|
39
|
+
let u = g.get(i.index);
|
|
40
|
+
u ? (i.id && (u.id = i.id), i.name && (u.name = i.name)) : (u = { index: i.index, id: i.id || null, name: i.name || "", argsText: "" }, g.set(i.index, u)), i.argsTextDelta && (u.argsText += i.argsTextDelta);
|
|
41
|
+
}
|
|
42
|
+
const m = t.done || !1, E = m ? f() : null;
|
|
43
|
+
return n({
|
|
44
|
+
content: t.content || "",
|
|
45
|
+
thinking: t.thinking || "",
|
|
46
|
+
fullContent: p,
|
|
47
|
+
fullThinking: w,
|
|
48
|
+
done: m,
|
|
49
|
+
usage: t.usage || null,
|
|
50
|
+
finishReason: t.finishReason || null,
|
|
51
|
+
toolCallDelta: t.toolCallDelta || null,
|
|
52
|
+
toolCalls: E
|
|
53
|
+
}), m ? "done" : null;
|
|
54
|
+
};
|
|
22
55
|
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;
|
|
56
|
+
const { done: h, value: o } = await y.read();
|
|
57
|
+
if (h) {
|
|
58
|
+
c.length > 0 && b(c);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
c += R.decode(o, { stream: !0 });
|
|
62
|
+
let t;
|
|
63
|
+
for (; (t = c.indexOf(`
|
|
64
|
+
`)) !== -1; ) {
|
|
65
|
+
const m = c.slice(0, t);
|
|
66
|
+
if (c = c.slice(t + 1), b(m) === "done")
|
|
67
|
+
return { content: p, toolCalls: f() };
|
|
41
68
|
}
|
|
42
69
|
}
|
|
43
|
-
return
|
|
44
|
-
} catch (
|
|
45
|
-
throw
|
|
70
|
+
return { content: p, toolCalls: f() };
|
|
71
|
+
} catch (d) {
|
|
72
|
+
throw d.name === "AbortError" ? new Error("Request cancelled") : d;
|
|
46
73
|
} finally {
|
|
47
|
-
this.activeRequests.delete(
|
|
74
|
+
this.activeRequests.delete(l);
|
|
48
75
|
}
|
|
49
76
|
}
|
|
50
|
-
async makeRequest(e,
|
|
51
|
-
const
|
|
52
|
-
|
|
77
|
+
async makeRequest(e, r, n) {
|
|
78
|
+
const a = r ? { signal: r } : new AbortController();
|
|
79
|
+
r || (n = n || this.generateRequestId(), this.activeRequests.set(n, a));
|
|
53
80
|
try {
|
|
54
|
-
const
|
|
81
|
+
const s = this.buildHeaders(), l = await fetch(this.getEndpoint(), {
|
|
55
82
|
method: "POST",
|
|
56
|
-
headers:
|
|
83
|
+
headers: s,
|
|
57
84
|
body: JSON.stringify(e),
|
|
58
|
-
signal:
|
|
85
|
+
signal: a.signal || r
|
|
59
86
|
});
|
|
60
|
-
if (!
|
|
61
|
-
const
|
|
62
|
-
throw new Error(`LLM API Error (${
|
|
87
|
+
if (!l.ok) {
|
|
88
|
+
const d = await l.text();
|
|
89
|
+
throw new Error(`LLM API Error (${l.status}): ${d}`);
|
|
63
90
|
}
|
|
64
|
-
return
|
|
65
|
-
} catch (
|
|
66
|
-
throw
|
|
91
|
+
return l.json();
|
|
92
|
+
} catch (s) {
|
|
93
|
+
throw s.name === "AbortError" ? new Error("Request cancelled") : s;
|
|
67
94
|
} finally {
|
|
68
|
-
!
|
|
95
|
+
!r && n && this.activeRequests.delete(n);
|
|
69
96
|
}
|
|
70
97
|
}
|
|
71
|
-
async makeStreamingRequest(e,
|
|
72
|
-
const
|
|
98
|
+
async makeStreamingRequest(e, r) {
|
|
99
|
+
const n = this.buildHeaders(), a = await fetch(this.getStreamingEndpoint(), {
|
|
73
100
|
method: "POST",
|
|
74
|
-
headers:
|
|
101
|
+
headers: n,
|
|
75
102
|
body: JSON.stringify(e),
|
|
76
|
-
signal:
|
|
103
|
+
signal: r
|
|
77
104
|
});
|
|
78
|
-
if (!
|
|
79
|
-
const
|
|
80
|
-
throw new Error(`LLM API Error (${
|
|
105
|
+
if (!a.ok) {
|
|
106
|
+
const s = await a.text();
|
|
107
|
+
throw new Error(`LLM API Error (${a.status}): ${s}`);
|
|
81
108
|
}
|
|
82
|
-
return
|
|
109
|
+
return a;
|
|
83
110
|
}
|
|
84
111
|
buildHeaders() {
|
|
85
112
|
const e = { "Content-Type": "application/json" };
|
|
@@ -120,8 +147,8 @@ class R {
|
|
|
120
147
|
}
|
|
121
148
|
// Cancel specific request
|
|
122
149
|
cancelRequest(e) {
|
|
123
|
-
const
|
|
124
|
-
|
|
150
|
+
const r = this.activeRequests.get(e);
|
|
151
|
+
r && (r.abort(), this.activeRequests.delete(e));
|
|
125
152
|
}
|
|
126
153
|
// Check if provider has capability
|
|
127
154
|
hasCapability(e) {
|
|
@@ -130,17 +157,17 @@ class R {
|
|
|
130
157
|
// Discover available models (override in subclass if needed)
|
|
131
158
|
async discoverModels(e = 1e4) {
|
|
132
159
|
try {
|
|
133
|
-
const
|
|
160
|
+
const r = this.buildHeaders(), n = new AbortController(), a = setTimeout(() => n.abort(), e), s = await fetch(this.getModelsEndpoint(), {
|
|
134
161
|
method: "GET",
|
|
135
|
-
headers:
|
|
136
|
-
signal:
|
|
162
|
+
headers: r,
|
|
163
|
+
signal: n.signal
|
|
137
164
|
});
|
|
138
|
-
if (clearTimeout(
|
|
139
|
-
throw new Error(`Failed to fetch models: ${
|
|
140
|
-
const
|
|
141
|
-
return this.parseModelsResponse(
|
|
142
|
-
} catch (
|
|
143
|
-
throw
|
|
165
|
+
if (clearTimeout(a), !s.ok)
|
|
166
|
+
throw new Error(`Failed to fetch models: ${s.status} ${s.statusText}`);
|
|
167
|
+
const l = await s.json();
|
|
168
|
+
return this.parseModelsResponse(l);
|
|
169
|
+
} catch (r) {
|
|
170
|
+
throw r.name === "AbortError" ? new Error("Model discovery timeout - please check your connection") : r;
|
|
144
171
|
}
|
|
145
172
|
}
|
|
146
173
|
getModelsEndpoint() {
|
|
@@ -151,5 +178,5 @@ class R {
|
|
|
151
178
|
}
|
|
152
179
|
}
|
|
153
180
|
export {
|
|
154
|
-
|
|
181
|
+
q as BaseProvider
|
|
155
182
|
};
|