@anvaka/vue-llm 0.2.0 → 0.3.1

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.
@@ -1,74 +1,86 @@
1
- import { BaseProvider as f } from "./BaseProvider.js";
2
- class m extends f {
1
+ import { BaseProvider as g } from "./BaseProvider.js";
2
+ class C extends g {
3
3
  async detectCapabilities() {
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
- }
7
- prepareRequest(e, t) {
8
- const n = h(e), o = {
9
- model: t.model || this.config.model || "claude-3-sonnet-20240229",
10
- max_tokens: t.maxTokens || 1e3,
11
- temperature: t.temperature ?? 0.7,
12
- messages: n,
13
- stream: t.stream || !1
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
- }
17
- processMessages(e, t) {
18
- return t.images && this.capabilities.has("vision") ? this.addImagesToMessages(e, t.images) : e;
19
- }
20
- addImagesToMessages(e, t) {
21
- const n = e[e.length - 1];
22
- if (n && n.role === "user") {
23
- const o = [{ type: "text", text: n.content }];
24
- t.forEach((s) => {
25
- o.push({
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 = _(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
+ };
14
+ s.includes("claude-opus-4-7") || (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 = m(e.tools), e.tool_choice && (r.tool_choice = e.tool_choice)), this.promptCachingEnabled(e) && y(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({
26
36
  type: "image",
27
- source: { type: "base64", media_type: "image/jpeg", data: typeof s == "string" ? s : s.data }
37
+ source: { type: "base64", media_type: "image/jpeg", data: typeof r == "string" ? r : r.data }
28
38
  });
29
- }), n.content = o;
39
+ }), o.content = s;
30
40
  }
31
- return e;
41
+ return t;
32
42
  }
33
- processResponse(e) {
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 || {} }));
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 || {} }));
35
45
  return {
36
- content: (o == null ? void 0 : o.text) || "",
37
- usage: e.usage || null,
38
- finishReason: t,
39
- toolCalls: l
46
+ content: (s == null ? void 0 : s.text) || "",
47
+ usage: f(t.usage),
48
+ finishReason: e,
49
+ toolCalls: c
40
50
  };
41
51
  }
42
- parseStreamingLine(e) {
43
- if (!e.startsWith("data: ")) return null;
44
- const t = e.slice(6).trim();
45
- if (t === "[DONE]") return { done: !0 };
52
+ parseStreamingLine(t) {
53
+ if (!t.startsWith("data: ")) return null;
54
+ const e = t.slice(6).trim();
55
+ if (e === "[DONE]") return { done: !0 };
46
56
  try {
47
- return JSON.parse(t);
57
+ return JSON.parse(e);
48
58
  } catch {
49
59
  return null;
50
60
  }
51
61
  }
52
- extractStreamingContent(e) {
53
- var t, n, o, s, l, r, d;
54
- if (e.done) return { done: !0 };
55
- if (e.type === "error") {
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;
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;
58
68
  }
59
- if (e.type === "content_block_start") {
60
- const a = e.content_block;
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;
61
73
  return (a == null ? void 0 : a.type) === "tool_use" ? {
62
74
  content: "",
63
75
  done: !1,
64
- toolCallDelta: { index: e.index, id: a.id, name: a.name, argsTextDelta: "" }
76
+ toolCallDelta: { index: t.index, id: a.id, name: a.name, argsTextDelta: "" }
65
77
  } : null;
66
78
  }
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" ? {
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" ? {
68
80
  content: "",
69
81
  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;
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;
72
84
  }
73
85
  getApiPath() {
74
86
  return "/v1/messages";
@@ -83,61 +95,103 @@ class m extends f {
83
95
  return this.config.apiKey;
84
96
  }
85
97
  buildHeaders() {
86
- const e = super.buildHeaders();
87
- return this.requiresAuth() && (e["anthropic-version"] = "2023-06-01", e["anthropic-dangerous-direct-browser-access"] = "true"), e;
98
+ const t = super.buildHeaders();
99
+ return this.requiresAuth() && (t["anthropic-version"] = "2023-06-01", t["anthropic-dangerous-direct-browser-access"] = "true"), t;
88
100
  }
89
101
  getModelsEndpoint() {
90
102
  return `${this.config.baseUrl}/v1/models`;
91
103
  }
92
- parseModelsResponse(e) {
93
- var t;
94
- return ((t = e.data) == null ? void 0 : t.map((n) => n.id)) || [];
104
+ parseModelsResponse(t) {
105
+ var e;
106
+ return ((e = t.data) == null ? void 0 : e.map((o) => o.id)) || [];
95
107
  }
96
108
  }
97
- function u(i) {
98
- if (!i) return null;
99
- const e = String(i).toLowerCase();
100
- return e === "max_tokens" ? "length" : e;
109
+ function h(n) {
110
+ if (!n) return null;
111
+ const t = String(n).toLowerCase();
112
+ return t === "max_tokens" ? "length" : t;
113
+ }
114
+ function f(n) {
115
+ if (!n) return null;
116
+ 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 };
117
+ return n.cache_read_input_tokens != null && (i.cachedInputTokens = e), n.cache_creation_input_tokens != null && (i.cacheCreationInputTokens = o), i;
101
118
  }
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({
119
+ function _(n) {
120
+ const t = [];
121
+ for (const e of n)
122
+ if (e.role !== "system") {
123
+ if (e.role === "assistant" && Array.isArray(e.tool_calls) && e.tool_calls.length) {
124
+ const o = [];
125
+ e.content && o.push({ type: "text", text: e.content });
126
+ for (const s of e.tool_calls)
127
+ o.push({
111
128
  type: "tool_use",
112
- id: o.id,
113
- name: o.name,
114
- input: o.args || {}
129
+ id: s.id,
130
+ name: s.name,
131
+ input: s.args || {}
115
132
  });
116
- e.push({ role: "assistant", content: n });
133
+ t.push({ role: "assistant", content: o });
117
134
  continue;
118
135
  }
119
- if (t.role === "tool") {
120
- e.push({
136
+ if (e.role === "tool") {
137
+ t.push({
121
138
  role: "user",
122
139
  content: [{
123
140
  type: "tool_result",
124
- tool_use_id: t.tool_call_id,
125
- content: String(t.content ?? "")
141
+ tool_use_id: e.tool_call_id,
142
+ content: String(e.content ?? "")
126
143
  }]
127
144
  });
128
145
  continue;
129
146
  }
130
- e.push({ role: t.role, content: t.content });
147
+ t.push({ role: e.role, content: e.content });
131
148
  }
132
- return e;
149
+ return t;
150
+ }
151
+ function m(n) {
152
+ return n.map((t) => t.type === "function" && t.function ? {
153
+ name: t.function.name,
154
+ description: t.function.description,
155
+ input_schema: t.function.parameters || { type: "object", properties: {} }
156
+ } : t);
133
157
  }
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);
158
+ const l = { type: "ephemeral" };
159
+ function y(n, t) {
160
+ if (n.system)
161
+ n.system = k(n.system);
162
+ else if (Array.isArray(n.tools) && n.tools.length) {
163
+ const e = n.tools.length - 1;
164
+ n.tools[e] = { ...n.tools[e], cache_control: l };
165
+ }
166
+ if (t != null && t.cacheTranscript) {
167
+ const e = n.messages;
168
+ if (Array.isArray(e) && e.length) {
169
+ const o = e[e.length - 1];
170
+ o.content = x(o.content);
171
+ }
172
+ }
173
+ return n;
174
+ }
175
+ function k(n) {
176
+ let t;
177
+ if (typeof n == "string")
178
+ t = [{ type: "text", text: n }];
179
+ else if (Array.isArray(n) && n.length)
180
+ t = n.map((e) => typeof e == "string" ? { type: "text", text: e } : { ...e });
181
+ else
182
+ return n;
183
+ return t[t.length - 1] = { ...t[t.length - 1], cache_control: l }, t;
184
+ }
185
+ function x(n) {
186
+ if (typeof n == "string")
187
+ return [{ type: "text", text: n, cache_control: l }];
188
+ if (Array.isArray(n) && n.length) {
189
+ const t = n.slice(), e = t.length - 1, o = t[e];
190
+ return t[e] = typeof o == "string" ? { type: "text", text: o, cache_control: l } : { ...o, cache_control: l }, t;
191
+ }
192
+ return n;
140
193
  }
141
194
  export {
142
- m as AnthropicProvider
195
+ C as AnthropicProvider,
196
+ f as normalizeAnthropicUsage
143
197
  };
@@ -1,4 +1,4 @@
1
- class q {
1
+ class A {
2
2
  constructor(e) {
3
3
  this.config = e, this.capabilities = /* @__PURE__ */ new Set(), this.activeRequests = /* @__PURE__ */ new Map();
4
4
  }
@@ -7,106 +7,108 @@ class q {
7
7
  }
8
8
  async detectCapabilities() {
9
9
  }
10
- prepareRequest(e, r) {
10
+ prepareRequest(e, t) {
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, r, n) {
17
- const a = this.prepareRequest(e, r), s = new AbortController(), l = r.requestId || this.generateRequestId();
18
- this.activeRequests.set(l, s);
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 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)
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
25
  try {
26
- t = JSON.parse(o.argsText);
26
+ s = JSON.parse(a.argsText);
27
27
  } catch {
28
- t = { __parseError: !0, raw: o.argsText };
28
+ s = { __parseError: !0, raw: a.argsText };
29
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);
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);
41
42
  }
42
- const m = t.done || !1, E = m ? f() : null;
43
+ const T = s.done || !1, C = T ? b() : null;
43
44
  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;
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;
54
56
  };
55
57
  for (; ; ) {
56
- const { done: h, value: o } = await y.read();
57
- if (h) {
58
- c.length > 0 && b(c);
58
+ const { done: p, value: a } = await k.read();
59
+ if (p) {
60
+ u.length > 0 && R(u);
59
61
  break;
60
62
  }
61
- c += R.decode(o, { stream: !0 });
62
- let t;
63
- for (; (t = c.indexOf(`
63
+ u += E.decode(a, { stream: !0 });
64
+ let s;
65
+ for (; (s = u.indexOf(`
64
66
  `)) !== -1; ) {
65
- const m = c.slice(0, t);
66
- if (c = c.slice(t + 1), b(m) === "done")
67
- return { content: p, toolCalls: f() };
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 };
68
70
  }
69
71
  }
70
- return { content: p, toolCalls: f() };
71
- } catch (d) {
72
- throw d.name === "AbortError" ? new Error("Request cancelled") : d;
72
+ return { content: m, thinking: f, toolCalls: b(), usage: g };
73
+ } catch (h) {
74
+ throw h.name === "AbortError" ? new Error("Request cancelled") : h;
73
75
  } finally {
74
76
  this.activeRequests.delete(l);
75
77
  }
76
78
  }
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));
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));
80
82
  try {
81
- const s = this.buildHeaders(), l = await fetch(this.getEndpoint(), {
83
+ const o = this.buildHeaders(), l = await fetch(this.getEndpoint(), {
82
84
  method: "POST",
83
- headers: s,
85
+ headers: o,
84
86
  body: JSON.stringify(e),
85
- signal: a.signal || r
87
+ signal: r.signal || t
86
88
  });
87
89
  if (!l.ok) {
88
- const d = await l.text();
89
- throw new Error(`LLM API Error (${l.status}): ${d}`);
90
+ const h = await l.text();
91
+ throw new Error(`LLM API Error (${l.status}): ${h}`);
90
92
  }
91
93
  return l.json();
92
- } catch (s) {
93
- throw s.name === "AbortError" ? new Error("Request cancelled") : s;
94
+ } catch (o) {
95
+ throw o.name === "AbortError" ? new Error("Request cancelled") : o;
94
96
  } finally {
95
- !r && n && this.activeRequests.delete(n);
97
+ !t && n && this.activeRequests.delete(n);
96
98
  }
97
99
  }
98
- async makeStreamingRequest(e, r) {
99
- const n = this.buildHeaders(), a = await fetch(this.getStreamingEndpoint(), {
100
+ async makeStreamingRequest(e, t) {
101
+ const n = this.buildHeaders(), r = await fetch(this.getStreamingEndpoint(), {
100
102
  method: "POST",
101
103
  headers: n,
102
104
  body: JSON.stringify(e),
103
- signal: r
105
+ signal: t
104
106
  });
105
- if (!a.ok) {
106
- const s = await a.text();
107
- throw new Error(`LLM API Error (${a.status}): ${s}`);
107
+ if (!r.ok) {
108
+ const o = await r.text();
109
+ throw new Error(`LLM API Error (${r.status}): ${o}`);
108
110
  }
109
- return a;
111
+ return r;
110
112
  }
111
113
  buildHeaders() {
112
114
  const e = { "Content-Type": "application/json" };
@@ -147,8 +149,8 @@ class q {
147
149
  }
148
150
  // Cancel specific request
149
151
  cancelRequest(e) {
150
- const r = this.activeRequests.get(e);
151
- r && (r.abort(), this.activeRequests.delete(e));
152
+ const t = this.activeRequests.get(e);
153
+ t && (t.abort(), this.activeRequests.delete(e));
152
154
  }
153
155
  // Check if provider has capability
154
156
  hasCapability(e) {
@@ -157,17 +159,17 @@ class q {
157
159
  // Discover available models (override in subclass if needed)
158
160
  async discoverModels(e = 1e4) {
159
161
  try {
160
- const r = this.buildHeaders(), n = new AbortController(), a = setTimeout(() => n.abort(), e), s = await fetch(this.getModelsEndpoint(), {
162
+ const t = this.buildHeaders(), n = new AbortController(), r = setTimeout(() => n.abort(), e), o = await fetch(this.getModelsEndpoint(), {
161
163
  method: "GET",
162
- headers: r,
164
+ headers: t,
163
165
  signal: n.signal
164
166
  });
165
- if (clearTimeout(a), !s.ok)
166
- throw new Error(`Failed to fetch models: ${s.status} ${s.statusText}`);
167
- const l = await s.json();
167
+ if (clearTimeout(r), !o.ok)
168
+ throw new Error(`Failed to fetch models: ${o.status} ${o.statusText}`);
169
+ const l = await o.json();
168
170
  return this.parseModelsResponse(l);
169
- } catch (r) {
170
- throw r.name === "AbortError" ? new Error("Model discovery timeout - please check your connection") : r;
171
+ } catch (t) {
172
+ throw t.name === "AbortError" ? new Error("Model discovery timeout - please check your connection") : t;
171
173
  }
172
174
  }
173
175
  getModelsEndpoint() {
@@ -177,6 +179,14 @@ class q {
177
179
  throw new Error("parseModelsResponse must be implemented by subclass");
178
180
  }
179
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
+ }
180
190
  export {
181
- q as BaseProvider
191
+ A as BaseProvider
182
192
  };
@@ -1,33 +1,66 @@
1
- import { BaseProvider as u } from "./BaseProvider.js";
2
- class l extends u {
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(e, t) {
6
- return {
7
- model: t.model || this.config.model || "gpt-3.5-turbo",
8
- messages: e,
9
- temperature: t.temperature ?? 0.7,
10
- max_tokens: t.maxTokens || 1e3,
11
- stream: t.stream || !1
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(e) {
15
- var t, n, r, s, a;
16
- return { content: ((r = (n = (t = e.choices) == null ? void 0 : t[0]) == null ? void 0 : n.message) == null ? void 0 : r.content) || "", usage: e.usage || null, finishReason: o((a = (s = e.choices) == null ? void 0 : s[0]) == null ? void 0 : a.finish_reason) };
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(e) {
19
- if (!e.startsWith("data: ")) return null;
20
- const t = e.slice(6).trim();
21
- if (t === "[DONE]") return { done: !0 };
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(t);
38
+ return JSON.parse(e);
24
39
  } catch {
25
40
  return null;
26
41
  }
27
42
  }
28
- extractStreamingContent(e) {
29
- var t, n, r, s, a;
30
- return e.done ? { done: !0 } : { content: ((r = (n = (t = e.choices) == null ? void 0 : t[0]) == null ? void 0 : n.delta) == null ? void 0 : r.content) || "", thinking: "", done: !1, usage: e.usage || null, finishReason: o((a = (s = e.choices) == null ? void 0 : s[0]) == null ? void 0 : a.finish_reason) };
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(e) {
42
- var t, n;
43
- return ((n = (t = e.data) == null ? void 0 : t.map((r) => r.id)) == null ? void 0 : n.sort()) || [];
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 o(i) {
47
- if (!i) return null;
48
- const e = String(i).toLowerCase();
49
- return e === "max_tokens" ? "length" : e;
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
- l as CustomProvider
93
+ A as CustomProvider
53
94
  };