@ztimson/ai-utils 0.2.7 → 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/dist/index.mjs CHANGED
@@ -1,126 +1,127 @@
1
- import * as j from "node:os";
2
- import { deepCopy as T, objectMap as y, JSONAttemptParse as _, findByProp as k, JSONSanitize as b, Http as M, consoleInterceptor as A, fn as q, ASet as P } from "@ztimson/utils";
3
- import { Anthropic as O } from "@anthropic-ai/sdk";
4
- import { Ollama as $ } from "ollama";
5
- import { OpenAI as E } from "openai";
6
- import { Worker as v } from "worker_threads";
7
- import { fileURLToPath as R } from "url";
8
- import { join as U, dirname as L } from "path";
9
- import { spawn as N } from "node:child_process";
10
- import S from "node:fs/promises";
11
- import W from "node:path";
12
- import { createWorker as D } from "tesseract.js";
13
- import { $ as J, $Sync as H } from "@ztimson/node-utils";
14
- class x {
1
+ import * as M from "node:os";
2
+ import { platform as E, arch as T } from "node:os";
3
+ import { deepCopy as A, objectMap as x, JSONAttemptParse as _, findByProp as j, JSONSanitize as k, Http as q, consoleInterceptor as O, fn as $, ASet as v } from "@ztimson/utils";
4
+ import { Anthropic as R } from "@anthropic-ai/sdk";
5
+ import { Ollama as L } from "ollama";
6
+ import { OpenAI as U } from "openai";
7
+ import { Worker as B } from "worker_threads";
8
+ import { fileURLToPath as W } from "url";
9
+ import { join as I, dirname as D } from "path";
10
+ import { spawn as P } from "node:child_process";
11
+ import b from "node:fs/promises";
12
+ import y from "node:path";
13
+ import { createWorker as N } from "tesseract.js";
14
+ import { $ as H, $Sync as J } from "@ztimson/node-utils";
15
+ class S {
15
16
  }
16
- class I extends x {
17
- constructor(t, e, s) {
18
- super(), this.ai = t, this.apiToken = e, this.model = s, this.client = new O({ apiKey: e });
17
+ class F extends S {
18
+ constructor(t, e, n) {
19
+ super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new R({ apiKey: e });
19
20
  }
20
21
  client;
21
22
  toStandard(t) {
22
23
  for (let e = 0; e < t.length; e++) {
23
- const s = e;
24
- typeof t[s].content != "string" && (t[s].role == "assistant" ? t[s].content.filter((n) => n.type == "tool_use").forEach((n) => {
25
- e++, t.splice(e, 0, { role: "tool", id: n.id, name: n.name, args: n.input, timestamp: Date.now() });
26
- }) : t[s].role == "user" && t[s].content.filter((n) => n.type == "tool_result").forEach((n) => {
27
- const i = t.find((d) => d.id == n.tool_use_id);
28
- i[n.is_error ? "error" : "content"] = n.content;
29
- }), t[s].content = t[s].content.filter((n) => n.type == "text").map((n) => n.text).join(`
24
+ const n = e;
25
+ typeof t[n].content != "string" && (t[n].role == "assistant" ? t[n].content.filter((s) => s.type == "tool_use").forEach((s) => {
26
+ e++, t.splice(e, 0, { role: "tool", id: s.id, name: s.name, args: s.input, timestamp: Date.now() });
27
+ }) : t[n].role == "user" && t[n].content.filter((s) => s.type == "tool_result").forEach((s) => {
28
+ const r = t.find((l) => l.id == s.tool_use_id);
29
+ r[s.is_error ? "error" : "content"] = s.content;
30
+ }), t[n].content = t[n].content.filter((s) => s.type == "text").map((s) => s.text).join(`
30
31
 
31
- `)), t[s].timestamp || (t[s].timestamp = Date.now());
32
+ `)), t[n].timestamp || (t[n].timestamp = Date.now());
32
33
  }
33
34
  return t.filter((e) => !!e.content);
34
35
  }
35
36
  fromStandard(t) {
36
37
  for (let e = 0; e < t.length; e++)
37
38
  if (t[e].role == "tool") {
38
- const s = t[e];
39
+ const n = t[e];
39
40
  t.splice(
40
41
  e,
41
42
  1,
42
- { role: "assistant", content: [{ type: "tool_use", id: s.id, name: s.name, input: s.args }] },
43
- { role: "user", content: [{ type: "tool_result", tool_use_id: s.id, is_error: !!s.error, content: s.error || s.content }] }
43
+ { role: "assistant", content: [{ type: "tool_use", id: n.id, name: n.name, input: n.args }] },
44
+ { role: "user", content: [{ type: "tool_result", tool_use_id: n.id, is_error: !!n.error, content: n.error || n.content }] }
44
45
  ), e++;
45
46
  }
46
- return t.map(({ timestamp: e, ...s }) => s);
47
+ return t.map(({ timestamp: e, ...n }) => n);
47
48
  }
48
49
  ask(t, e = {}) {
49
- const s = new AbortController(), n = new Promise(async (i, d) => {
50
- let r = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
51
- const l = T(r);
52
- e.compress && (r = await this.ai.language.compressHistory(r, e.compress.max, e.compress.min, e));
53
- const u = e.tools || this.ai.options.tools || [], c = {
50
+ const n = new AbortController(), s = new Promise(async (r, l) => {
51
+ let o = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
52
+ const d = A(o);
53
+ e.compress && (o = await this.ai.language.compressHistory(o, e.compress.max, e.compress.min, e));
54
+ const p = e.tools || this.ai.options.tools || [], a = {
54
55
  model: e.model || this.model,
55
56
  max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
56
57
  system: e.system || this.ai.options.system || "",
57
58
  temperature: e.temperature || this.ai.options.temperature || 0.7,
58
- tools: u.map((o) => ({
59
- name: o.name,
60
- description: o.description,
59
+ tools: p.map((i) => ({
60
+ name: i.name,
61
+ description: i.description,
61
62
  input_schema: {
62
63
  type: "object",
63
- properties: o.args ? y(o.args, (a, f) => ({ ...f, required: void 0 })) : {},
64
- required: o.args ? Object.entries(o.args).filter((a) => a[1].required).map((a) => a[0]) : []
64
+ properties: i.args ? x(i.args, (c, f) => ({ ...f, required: void 0 })) : {},
65
+ required: i.args ? Object.entries(i.args).filter((c) => c[1].required).map((c) => c[0]) : []
65
66
  },
66
67
  fn: void 0
67
68
  })),
68
- messages: r,
69
+ messages: o,
69
70
  stream: !!e.stream
70
71
  };
71
72
  let m, h = !0;
72
73
  do {
73
- if (m = await this.client.messages.create(c).catch((a) => {
74
- throw a.message += `
74
+ if (m = await this.client.messages.create(a).catch((c) => {
75
+ throw c.message += `
75
76
 
76
77
  Messages:
77
- ${JSON.stringify(r, null, 2)}`, a;
78
+ ${JSON.stringify(o, null, 2)}`, c;
78
79
  }), e.stream) {
79
80
  h ? h = !1 : e.stream({ text: `
80
81
 
81
82
  ` }), m.content = [];
82
- for await (const a of m) {
83
- if (s.signal.aborted) break;
84
- if (a.type === "content_block_start")
85
- a.content_block.type === "text" ? m.content.push({ type: "text", text: "" }) : a.content_block.type === "tool_use" && m.content.push({ type: "tool_use", id: a.content_block.id, name: a.content_block.name, input: "" });
86
- else if (a.type === "content_block_delta")
87
- if (a.delta.type === "text_delta") {
88
- const f = a.delta.text;
83
+ for await (const c of m) {
84
+ if (n.signal.aborted) break;
85
+ if (c.type === "content_block_start")
86
+ c.content_block.type === "text" ? m.content.push({ type: "text", text: "" }) : c.content_block.type === "tool_use" && m.content.push({ type: "tool_use", id: c.content_block.id, name: c.content_block.name, input: "" });
87
+ else if (c.type === "content_block_delta")
88
+ if (c.delta.type === "text_delta") {
89
+ const f = c.delta.text;
89
90
  m.content.at(-1).text += f, e.stream({ text: f });
90
- } else a.delta.type === "input_json_delta" && (m.content.at(-1).input += a.delta.partial_json);
91
- else if (a.type === "content_block_stop") {
91
+ } else c.delta.type === "input_json_delta" && (m.content.at(-1).input += c.delta.partial_json);
92
+ else if (c.type === "content_block_stop") {
92
93
  const f = m.content.at(-1);
93
94
  f.input != null && (f.input = f.input ? _(f.input, {}) : {});
94
- } else if (a.type === "message_stop")
95
+ } else if (c.type === "message_stop")
95
96
  break;
96
97
  }
97
98
  }
98
- const o = m.content.filter((a) => a.type === "tool_use");
99
- if (o.length && !s.signal.aborted) {
100
- r.push({ role: "assistant", content: m.content }), l.push({ role: "assistant", content: m.content });
101
- const a = await Promise.all(o.map(async (f) => {
102
- const g = u.find(k("name", f.name));
103
- if (!g) return { tool_use_id: f.id, is_error: !0, content: "Tool not found" };
99
+ const i = m.content.filter((c) => c.type === "tool_use");
100
+ if (i.length && !n.signal.aborted) {
101
+ o.push({ role: "assistant", content: m.content }), d.push({ role: "assistant", content: m.content });
102
+ const c = await Promise.all(i.map(async (f) => {
103
+ const g = p.find(j("name", f.name));
104
+ if (e.stream && e.stream({ tool: f.name }), !g) return { tool_use_id: f.id, is_error: !0, content: "Tool not found" };
104
105
  try {
105
106
  const w = await g.fn(f.input, this.ai);
106
- return { type: "tool_result", tool_use_id: f.id, content: b(w) };
107
+ return { type: "tool_result", tool_use_id: f.id, content: k(w) };
107
108
  } catch (w) {
108
109
  return { type: "tool_result", tool_use_id: f.id, is_error: !0, content: w?.message || w?.toString() || "Unknown" };
109
110
  }
110
111
  }));
111
- r.push({ role: "user", content: a }), c.messages = r;
112
+ o.push({ role: "user", content: c }), a.messages = o;
112
113
  }
113
- } while (!s.signal.aborted && m.content.some((o) => o.type === "tool_use"));
114
- e.stream && e.stream({ done: !0 }), i(this.toStandard([...r, { role: "assistant", content: m.content.filter((o) => o.type == "text").map((o) => o.text).join(`
114
+ } while (!n.signal.aborted && m.content.some((i) => i.type === "tool_use"));
115
+ e.stream && e.stream({ done: !0 }), r(this.toStandard([...o, { role: "assistant", content: m.content.filter((i) => i.type == "text").map((i) => i.text).join(`
115
116
 
116
117
  `) }]));
117
118
  });
118
- return Object.assign(n, { abort: () => s.abort() });
119
+ return Object.assign(s, { abort: () => n.abort() });
119
120
  }
120
121
  }
121
- class z extends x {
122
- constructor(t, e, s) {
123
- super(), this.ai = t, this.host = e, this.model = s, this.client = new $({ host: e });
122
+ class z extends S {
123
+ constructor(t, e, n) {
124
+ super(), this.ai = t, this.host = e, this.model = n, this.client = new L({ host: e });
124
125
  }
125
126
  client;
126
127
  toStandard(t) {
@@ -128,8 +129,8 @@ class z extends x {
128
129
  if (t[e].role == "assistant" && t[e].tool_calls)
129
130
  t[e].content ? delete t[e].tool_calls : (t.splice(e, 1), e--);
130
131
  else if (t[e].role == "tool") {
131
- const s = t[e].content.startsWith('{"error":');
132
- t[e] = { role: "tool", name: t[e].tool_name, args: t[e].args, [s ? "error" : "content"]: t[e].content, timestamp: t[e].timestamp };
132
+ const n = t[e].content.startsWith('{"error":');
133
+ t[e] = { role: "tool", name: t[e].tool_name, args: t[e].args, [n ? "error" : "content"]: t[e].content, timestamp: t[e].timestamp };
133
134
  }
134
135
  t[e]?.timestamp || (t[e].timestamp = Date.now());
135
136
  }
@@ -137,183 +138,183 @@ class z extends x {
137
138
  }
138
139
  fromStandard(t) {
139
140
  return t.map((e) => {
140
- const { timestamp: s, ...n } = e;
141
- return e.role != "tool" ? n : { role: "tool", tool_name: e.name, content: e.error || e.content };
141
+ const { timestamp: n, ...s } = e;
142
+ return e.role != "tool" ? s : { role: "tool", tool_name: e.name, content: e.error || e.content };
142
143
  });
143
144
  }
144
145
  ask(t, e = {}) {
145
- const s = new AbortController(), n = new Promise(async (i, d) => {
146
- let r = e.system || this.ai.options.system, l = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
147
- l[0].roll == "system" && (r ? l.shift() : r = l.shift()), e.compress && (l = await this.ai.language.compressHistory(l, e.compress.max, e.compress.min)), e.system && l.unshift({ role: "system", content: r });
148
- const u = e.tools || this.ai.options.tools || [], c = {
146
+ const n = new AbortController(), s = new Promise(async (r, l) => {
147
+ let o = e.system || this.ai.options.system, d = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
148
+ d[0].roll == "system" && (o ? d.shift() : o = d.shift()), e.compress && (d = await this.ai.language.compressHistory(d, e.compress.max, e.compress.min)), e.system && d.unshift({ role: "system", content: o });
149
+ const p = e.tools || this.ai.options.tools || [], a = {
149
150
  model: e.model || this.model,
150
- messages: l,
151
+ messages: d,
151
152
  stream: !!e.stream,
152
- signal: s.signal,
153
+ signal: n.signal,
153
154
  options: {
154
155
  temperature: e.temperature || this.ai.options.temperature || 0.7,
155
156
  num_predict: e.max_tokens || this.ai.options.max_tokens || 4096
156
157
  },
157
- tools: u.map((o) => ({
158
+ tools: p.map((i) => ({
158
159
  type: "function",
159
160
  function: {
160
- name: o.name,
161
- description: o.description,
161
+ name: i.name,
162
+ description: i.description,
162
163
  parameters: {
163
164
  type: "object",
164
- properties: o.args ? y(o.args, (a, f) => ({ ...f, required: void 0 })) : {},
165
- required: o.args ? Object.entries(o.args).filter((a) => a[1].required).map((a) => a[0]) : []
165
+ properties: i.args ? x(i.args, (c, f) => ({ ...f, required: void 0 })) : {},
166
+ required: i.args ? Object.entries(i.args).filter((c) => c[1].required).map((c) => c[0]) : []
166
167
  }
167
168
  }
168
169
  }))
169
170
  };
170
171
  let m, h = !0;
171
172
  do {
172
- if (m = await this.client.chat(c).catch((o) => {
173
- throw o.message += `
173
+ if (m = await this.client.chat(a).catch((i) => {
174
+ throw i.message += `
174
175
 
175
176
  Messages:
176
- ${JSON.stringify(l, null, 2)}`, o;
177
+ ${JSON.stringify(d, null, 2)}`, i;
177
178
  }), e.stream) {
178
179
  h ? h = !1 : e.stream({ text: `
179
180
 
180
181
  ` }), m.message = { role: "assistant", content: "", tool_calls: [] };
181
- for await (const o of m)
182
- if (s.signal.aborted || (o.message?.content && (m.message.content += o.message.content, e.stream({ text: o.message.content })), o.message?.tool_calls && (m.message.tool_calls = o.message.tool_calls), o.done)) break;
182
+ for await (const i of m)
183
+ if (n.signal.aborted || (i.message?.content && (m.message.content += i.message.content, e.stream({ text: i.message.content })), i.message?.tool_calls && (m.message.tool_calls = i.message.tool_calls), i.done)) break;
183
184
  }
184
- if (m.message?.tool_calls?.length && !s.signal.aborted) {
185
- l.push(m.message);
186
- const o = await Promise.all(m.message.tool_calls.map(async (a) => {
187
- const f = u.find(k("name", a.function.name));
188
- if (!f) return { role: "tool", tool_name: a.function.name, content: '{"error": "Tool not found"}' };
189
- const g = typeof a.function.arguments == "string" ? _(a.function.arguments, {}) : a.function.arguments;
185
+ if (m.message?.tool_calls?.length && !n.signal.aborted) {
186
+ d.push(m.message);
187
+ const i = await Promise.all(m.message.tool_calls.map(async (c) => {
188
+ const f = p.find(j("name", c.function.name));
189
+ if (e.stream && e.stream({ tool: c.function.name }), !f) return { role: "tool", tool_name: c.function.name, content: '{"error": "Tool not found"}' };
190
+ const g = typeof c.function.arguments == "string" ? _(c.function.arguments, {}) : c.function.arguments;
190
191
  try {
191
192
  const w = await f.fn(g, this.ai);
192
- return { role: "tool", tool_name: a.function.name, args: g, content: b(w) };
193
+ return { role: "tool", tool_name: c.function.name, args: g, content: k(w) };
193
194
  } catch (w) {
194
- return { role: "tool", tool_name: a.function.name, args: g, content: b({ error: w?.message || w?.toString() || "Unknown" }) };
195
+ return { role: "tool", tool_name: c.function.name, args: g, content: k({ error: w?.message || w?.toString() || "Unknown" }) };
195
196
  }
196
197
  }));
197
- l.push(...o), c.messages = l;
198
+ d.push(...i), a.messages = d;
198
199
  }
199
- } while (!s.signal.aborted && m.message?.tool_calls?.length);
200
- e.stream && e.stream({ done: !0 }), i(this.toStandard([...l, { role: "assistant", content: m.message?.content }]));
200
+ } while (!n.signal.aborted && m.message?.tool_calls?.length);
201
+ e.stream && e.stream({ done: !0 }), r(this.toStandard([...d, { role: "assistant", content: m.message?.content }]));
201
202
  });
202
- return Object.assign(n, { abort: () => s.abort() });
203
+ return Object.assign(s, { abort: () => n.abort() });
203
204
  }
204
205
  }
205
- class F extends x {
206
- constructor(t, e, s) {
207
- super(), this.ai = t, this.apiToken = e, this.model = s, this.client = new E({ apiKey: e });
206
+ class G extends S {
207
+ constructor(t, e, n) {
208
+ super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new U({ apiKey: e });
208
209
  }
209
210
  client;
210
211
  toStandard(t) {
211
212
  for (let e = 0; e < t.length; e++) {
212
- const s = t[e];
213
- if (s.role === "assistant" && s.tool_calls) {
214
- const n = s.tool_calls.map((i) => ({
213
+ const n = t[e];
214
+ if (n.role === "assistant" && n.tool_calls) {
215
+ const s = n.tool_calls.map((r) => ({
215
216
  role: "tool",
216
- id: i.id,
217
- name: i.function.name,
218
- args: _(i.function.arguments, {}),
219
- timestamp: s.timestamp
217
+ id: r.id,
218
+ name: r.function.name,
219
+ args: _(r.function.arguments, {}),
220
+ timestamp: n.timestamp
220
221
  }));
221
- t.splice(e, 1, ...n), e += n.length - 1;
222
- } else if (s.role === "tool" && s.content) {
223
- const n = t.find((i) => s.tool_call_id == i.id);
224
- n && (s.content.includes('"error":') ? n.error = s.content : n.content = s.content), t.splice(e, 1), e--;
222
+ t.splice(e, 1, ...s), e += s.length - 1;
223
+ } else if (n.role === "tool" && n.content) {
224
+ const s = t.find((r) => n.tool_call_id == r.id);
225
+ s && (n.content.includes('"error":') ? s.error = n.content : s.content = n.content), t.splice(e, 1), e--;
225
226
  }
226
227
  t[e]?.timestamp || (t[e].timestamp = Date.now());
227
228
  }
228
229
  return t;
229
230
  }
230
231
  fromStandard(t) {
231
- return t.reduce((e, s) => {
232
- if (s.role === "tool")
232
+ return t.reduce((e, n) => {
233
+ if (n.role === "tool")
233
234
  e.push({
234
235
  role: "assistant",
235
236
  content: null,
236
- tool_calls: [{ id: s.id, type: "function", function: { name: s.name, arguments: JSON.stringify(s.args) } }],
237
+ tool_calls: [{ id: n.id, type: "function", function: { name: n.name, arguments: JSON.stringify(n.args) } }],
237
238
  refusal: null,
238
239
  annotations: []
239
240
  }, {
240
241
  role: "tool",
241
- tool_call_id: s.id,
242
- content: s.error || s.content
242
+ tool_call_id: n.id,
243
+ content: n.error || n.content
243
244
  });
244
245
  else {
245
- const { timestamp: n, ...i } = s;
246
- e.push(i);
246
+ const { timestamp: s, ...r } = n;
247
+ e.push(r);
247
248
  }
248
249
  return e;
249
250
  }, []);
250
251
  }
251
252
  ask(t, e = {}) {
252
- const s = new AbortController(), n = new Promise(async (i, d) => {
253
- let r = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
254
- e.compress && (r = await this.ai.language.compressHistory(r, e.compress.max, e.compress.min, e));
255
- const l = e.tools || this.ai.options.tools || [], u = {
253
+ const n = new AbortController(), s = new Promise(async (r, l) => {
254
+ let o = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
255
+ e.compress && (o = await this.ai.language.compressHistory(o, e.compress.max, e.compress.min, e));
256
+ const d = e.tools || this.ai.options.tools || [], p = {
256
257
  model: e.model || this.model,
257
- messages: r,
258
+ messages: o,
258
259
  stream: !!e.stream,
259
260
  max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
260
261
  temperature: e.temperature || this.ai.options.temperature || 0.7,
261
- tools: l.map((h) => ({
262
+ tools: d.map((h) => ({
262
263
  type: "function",
263
264
  function: {
264
265
  name: h.name,
265
266
  description: h.description,
266
267
  parameters: {
267
268
  type: "object",
268
- properties: h.args ? y(h.args, (o, a) => ({ ...a, required: void 0 })) : {},
269
- required: h.args ? Object.entries(h.args).filter((o) => o[1].required).map((o) => o[0]) : []
269
+ properties: h.args ? x(h.args, (i, c) => ({ ...c, required: void 0 })) : {},
270
+ required: h.args ? Object.entries(h.args).filter((i) => i[1].required).map((i) => i[0]) : []
270
271
  }
271
272
  }
272
273
  }))
273
274
  };
274
- let c, m = !0;
275
+ let a, m = !0;
275
276
  do {
276
- if (c = await this.client.chat.completions.create(u).catch((o) => {
277
- throw o.message += `
277
+ if (a = await this.client.chat.completions.create(p).catch((i) => {
278
+ throw i.message += `
278
279
 
279
280
  Messages:
280
- ${JSON.stringify(r, null, 2)}`, o;
281
+ ${JSON.stringify(o, null, 2)}`, i;
281
282
  }), e.stream) {
282
283
  m ? m = !1 : e.stream({ text: `
283
284
 
284
- ` }), c.choices = [{ message: { content: "", tool_calls: [] } }];
285
- for await (const o of c) {
286
- if (s.signal.aborted) break;
287
- o.choices[0].delta.content && (c.choices[0].message.content += o.choices[0].delta.content, e.stream({ text: o.choices[0].delta.content })), o.choices[0].delta.tool_calls && (c.choices[0].message.tool_calls = o.choices[0].delta.tool_calls);
285
+ ` }), a.choices = [{ message: { content: "", tool_calls: [] } }];
286
+ for await (const i of a) {
287
+ if (n.signal.aborted) break;
288
+ i.choices[0].delta.content && (a.choices[0].message.content += i.choices[0].delta.content, e.stream({ text: i.choices[0].delta.content })), i.choices[0].delta.tool_calls && (a.choices[0].message.tool_calls = i.choices[0].delta.tool_calls);
288
289
  }
289
290
  }
290
- const h = c.choices[0].message.tool_calls || [];
291
- if (h.length && !s.signal.aborted) {
292
- r.push(c.choices[0].message);
293
- const o = await Promise.all(h.map(async (a) => {
294
- const f = l?.find(k("name", a.function.name));
295
- if (!f) return { role: "tool", tool_call_id: a.id, content: '{"error": "Tool not found"}' };
291
+ const h = a.choices[0].message.tool_calls || [];
292
+ if (h.length && !n.signal.aborted) {
293
+ o.push(a.choices[0].message);
294
+ const i = await Promise.all(h.map(async (c) => {
295
+ const f = d?.find(j("name", c.function.name));
296
+ if (e.stream && e.stream({ tool: c.function.name }), !f) return { role: "tool", tool_call_id: c.id, content: '{"error": "Tool not found"}' };
296
297
  try {
297
- const g = _(a.function.arguments, {}), w = await f.fn(g, this.ai);
298
- return { role: "tool", tool_call_id: a.id, content: b(w) };
298
+ const g = _(c.function.arguments, {}), w = await f.fn(g, this.ai);
299
+ return { role: "tool", tool_call_id: c.id, content: k(w) };
299
300
  } catch (g) {
300
- return { role: "tool", tool_call_id: a.id, content: b({ error: g?.message || g?.toString() || "Unknown" }) };
301
+ return { role: "tool", tool_call_id: c.id, content: k({ error: g?.message || g?.toString() || "Unknown" }) };
301
302
  }
302
303
  }));
303
- r.push(...o), u.messages = r;
304
+ o.push(...i), p.messages = o;
304
305
  }
305
- } while (!s.signal.aborted && c.choices?.[0]?.message?.tool_calls?.length);
306
- e.stream && e.stream({ done: !0 }), i(this.toStandard([...r, { role: "assistant", content: c.choices[0].message.content || "" }]));
306
+ } while (!n.signal.aborted && a.choices?.[0]?.message?.tool_calls?.length);
307
+ e.stream && e.stream({ done: !0 }), r(this.toStandard([...o, { role: "assistant", content: a.choices[0].message.content || "" }]));
307
308
  });
308
- return Object.assign(n, { abort: () => s.abort() });
309
+ return Object.assign(s, { abort: () => n.abort() });
309
310
  }
310
311
  }
311
- class G {
312
+ class Q {
312
313
  constructor(t) {
313
- this.ai = t, this.embedWorker = new v(U(L(R(import.meta.url)), "embedder.js")), this.embedWorker.on("message", ({ id: e, embedding: s }) => {
314
- const n = this.embedQueue.get(e);
315
- n && (n.resolve(s), this.embedQueue.delete(e));
316
- }), t.options.anthropic?.token && (this.providers.anthropic = new I(this.ai, t.options.anthropic.token, t.options.anthropic.model)), t.options.ollama?.host && (this.providers.ollama = new z(this.ai, t.options.ollama.host, t.options.ollama.model)), t.options.openAi?.token && (this.providers.openAi = new F(this.ai, t.options.openAi.token, t.options.openAi.model));
314
+ this.ai = t, this.embedWorker = new B(I(D(W(import.meta.url)), "embedder.js")), this.embedWorker.on("message", ({ id: e, embedding: n }) => {
315
+ const s = this.embedQueue.get(e);
316
+ s && (s.resolve(n), this.embedQueue.delete(e));
317
+ }), t.options.anthropic?.token && (this.providers.anthropic = new F(this.ai, t.options.anthropic.token, t.options.anthropic.model)), t.options.ollama?.host && (this.providers.ollama = new z(this.ai, t.options.ollama.host, t.options.ollama.model)), t.options.openAi?.token && (this.providers.openAi = new G(this.ai, t.options.openAi.token, t.options.openAi.model));
317
318
  }
318
319
  embedWorker = null;
319
320
  embedQueue = /* @__PURE__ */ new Map();
@@ -326,9 +327,9 @@ class G {
326
327
  * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history
327
328
  */
328
329
  ask(t, e = {}) {
329
- let s = [null, null];
330
- if (e.model && (typeof e.model == "object" ? s = e.model : s = [e.model, this.ai.options[e.model]?.model]), (!e.model || s[1] == null) && (typeof this.ai.options.model == "object" ? s = this.ai.options.model : s = [this.ai.options.model, this.ai.options[this.ai.options.model]?.model]), !s[0] || !s[1]) throw new Error(`Unknown LLM provider or model: ${s[0]} / ${s[1]}`);
331
- return this.providers[s[0]].ask(t, { ...e, model: s[1] });
330
+ let n = [null, null];
331
+ if (e.model && (typeof e.model == "object" ? n = e.model : n = [e.model, this.ai.options[e.model]?.model]), (!e.model || n[1] == null) && (typeof this.ai.options.model == "object" ? n = this.ai.options.model : n = [this.ai.options.model, this.ai.options[this.ai.options.model]?.model]), !n[0] || !n[1]) throw new Error(`Unknown LLM provider or model: ${n[0]} / ${n[1]}`);
332
+ return this.providers[n[0]].ask(t, { ...e, model: n[1] });
332
333
  }
333
334
  /**
334
335
  * Compress chat history to reduce context size
@@ -338,57 +339,57 @@ class G {
338
339
  * @param {LLMRequest} options LLM options
339
340
  * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0
340
341
  */
341
- async compressHistory(t, e, s, n) {
342
+ async compressHistory(t, e, n, s) {
342
343
  if (this.estimateTokens(t) < e) return t;
343
- let i = 0, d = 0;
344
- for (let c of t.toReversed())
345
- if (d += this.estimateTokens(c.content), d < s) i++;
344
+ let r = 0, l = 0;
345
+ for (let a of t.toReversed())
346
+ if (l += this.estimateTokens(a.content), l < n) r++;
346
347
  else break;
347
- if (t.length <= i) return t;
348
- const r = i == 0 ? [] : t.slice(-i), l = (i == 0 ? t : t.slice(0, -i)).filter((c) => c.role === "assistant" || c.role === "user");
349
- return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(l.map((c) => `${c.role}: ${c.content}`).join(`
348
+ if (t.length <= r) return t;
349
+ const o = r == 0 ? [] : t.slice(-r), d = (r == 0 ? t : t.slice(0, -r)).filter((a) => a.role === "assistant" || a.role === "user");
350
+ return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(d.map((a) => `${a.role}: ${a.content}`).join(`
350
351
 
351
- `), 250, n)}`, timestamp: Date.now() }, ...r];
352
+ `), 250, s)}`, timestamp: Date.now() }, ...o];
352
353
  }
353
354
  cosineSimilarity(t, e) {
354
355
  if (t.length !== e.length) throw new Error("Vectors must be same length");
355
- let s = 0, n = 0, i = 0;
356
- for (let r = 0; r < t.length; r++)
357
- s += t[r] * e[r], n += t[r] * t[r], i += e[r] * e[r];
358
- const d = Math.sqrt(n) * Math.sqrt(i);
359
- return d === 0 ? 0 : s / d;
360
- }
361
- chunk(t, e = 500, s = 50) {
362
- const n = (l, u = "") => l ? Object.entries(l).flatMap(([c, m]) => {
363
- const h = u ? `${u}${isNaN(+c) ? `.${c}` : `[${c}]`}` : c;
364
- return typeof m == "object" && !Array.isArray(m) ? n(m, h) : `${h}: ${Array.isArray(m) ? m.join(", ") : m}`;
365
- }) : [], d = (typeof t == "object" ? n(t) : t.split(`
366
- `)).flatMap((l) => [...l.split(/\s+/).filter(Boolean), `
367
- `]), r = [];
368
- for (let l = 0; l < d.length; ) {
369
- let u = "", c = l;
370
- for (; c < d.length; ) {
371
- const h = u + (u ? " " : "") + d[c];
356
+ let n = 0, s = 0, r = 0;
357
+ for (let o = 0; o < t.length; o++)
358
+ n += t[o] * e[o], s += t[o] * t[o], r += e[o] * e[o];
359
+ const l = Math.sqrt(s) * Math.sqrt(r);
360
+ return l === 0 ? 0 : n / l;
361
+ }
362
+ chunk(t, e = 500, n = 50) {
363
+ const s = (d, p = "") => d ? Object.entries(d).flatMap(([a, m]) => {
364
+ const h = p ? `${p}${isNaN(+a) ? `.${a}` : `[${a}]`}` : a;
365
+ return typeof m == "object" && !Array.isArray(m) ? s(m, h) : `${h}: ${Array.isArray(m) ? m.join(", ") : m}`;
366
+ }) : [], l = (typeof t == "object" ? s(t) : t.split(`
367
+ `)).flatMap((d) => [...d.split(/\s+/).filter(Boolean), `
368
+ `]), o = [];
369
+ for (let d = 0; d < l.length; ) {
370
+ let p = "", a = d;
371
+ for (; a < l.length; ) {
372
+ const h = p + (p ? " " : "") + l[a];
372
373
  if (this.estimateTokens(h.replace(/\s*\n\s*/g, `
373
- `)) > e && u) break;
374
- u = h, c++;
374
+ `)) > e && p) break;
375
+ p = h, a++;
375
376
  }
376
- const m = u.replace(/\s*\n\s*/g, `
377
+ const m = p.replace(/\s*\n\s*/g, `
377
378
  `).trim();
378
- m && r.push(m), l = Math.max(c - s, c === l ? l + 1 : c);
379
+ m && o.push(m), d = Math.max(a - n, a === d ? d + 1 : a);
379
380
  }
380
- return r;
381
- }
382
- embedding(t, e = 500, s = 50) {
383
- const n = (d) => new Promise((r, l) => {
384
- const u = this.embedId++;
385
- this.embedQueue.set(u, { resolve: r, reject: l }), this.embedWorker?.postMessage({ id: u, text: d });
386
- }), i = this.chunk(t, e, s);
387
- return Promise.all(i.map(async (d, r) => ({
388
- index: r,
389
- embedding: await n(d),
390
- text: d,
391
- tokens: this.estimateTokens(d)
381
+ return o;
382
+ }
383
+ embedding(t, e = 500, n = 50) {
384
+ const s = (l) => new Promise((o, d) => {
385
+ const p = this.embedId++;
386
+ this.embedQueue.set(p, { resolve: o, reject: d }), this.embedWorker?.postMessage({ id: p, text: l });
387
+ }), r = this.chunk(t, e, n);
388
+ return Promise.all(r.map(async (l, o) => ({
389
+ index: o,
390
+ embedding: await s(l),
391
+ text: l,
392
+ tokens: this.estimateTokens(l)
392
393
  })));
393
394
  }
394
395
  /**
@@ -408,8 +409,8 @@ class G {
408
409
  */
409
410
  fuzzyMatch(t, ...e) {
410
411
  if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
411
- const s = (d, r = 10) => d.toLowerCase().split("").map((l, u) => l.charCodeAt(0) * (u + 1) % r / r).slice(0, r), n = s(t), i = e.map((d) => s(d)).map((d) => this.cosineSimilarity(n, d));
412
- return { avg: i.reduce((d, r) => d + r, 0) / i.length, max: Math.max(...i), similarities: i };
412
+ const n = (l, o = 10) => l.toLowerCase().split("").map((d, p) => d.charCodeAt(0) * (p + 1) % o / o).slice(0, o), s = n(t), r = e.map((l) => n(l)).map((l) => this.cosineSimilarity(s, l));
413
+ return { avg: r.reduce((l, o) => l + o, 0) / r.length, max: Math.max(...r), similarities: r };
413
414
  }
414
415
  /**
415
416
  * Ask a question with JSON response
@@ -418,11 +419,11 @@ class G {
418
419
  * @returns {Promise<{} | {} | RegExpExecArray | null>}
419
420
  */
420
421
  async json(t, e) {
421
- let s = await this.ask(t, {
422
+ let n = await this.ask(t, {
422
423
  system: "Respond using a JSON blob",
423
424
  ...e
424
425
  });
425
- return s?.[0]?.content ? _(new RegExp("{[sS]*}").exec(s[0].content), {}) : {};
426
+ return n?.[0]?.content ? _(new RegExp("{[sS]*}").exec(n[0].content), {}) : {};
426
427
  }
427
428
  /**
428
429
  * Create a summary of some text
@@ -431,75 +432,102 @@ class G {
431
432
  * @param options LLM request options
432
433
  * @returns {Promise<string>} Summary
433
434
  */
434
- summarize(t, e, s) {
435
- return this.ask(t, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...s }).then((n) => n.pop()?.content || null);
435
+ summarize(t, e, n) {
436
+ return this.ask(t, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...n }).then((s) => s.pop()?.content || null);
436
437
  }
437
438
  }
438
- class B {
439
+ class C {
439
440
  constructor(t) {
440
- this.ai = t, t.options.whisper?.binary && (this.whisperModel = t.options.whisper?.model.endsWith(".bin") ? t.options.whisper?.model : t.options.whisper?.model + ".bin", this.downloadAsrModel());
441
+ if (this.ai = t, t.options.whisper?.binary && (this.whisperModel = t.options.whisper?.model.endsWith(".bin") ? t.options.whisper?.model : t.options.whisper?.model + ".bin", this.downloadAsrModel()), t.options.piper?.model) {
442
+ if (!t.options.piper.model.startsWith("http") || !t.options.piper.model.endsWith(".onnx"))
443
+ throw new Error("Piper model should be a URL to an onnx file to download");
444
+ if (E() != "linux" || T() != "x64" && T() != "arm64")
445
+ throw new Error("Piper TTS only supported on Linux x64/arm64");
446
+ this.piperBinary = y.join(import.meta.dirname, "../bin/piper"), this.downloadTtsModel();
447
+ }
441
448
  }
442
449
  downloads = {};
443
450
  whisperModel;
444
- /**
445
- * Convert audio to text using Auditory Speech Recognition
446
- * @param {string} path Path to audio
447
- * @param model Whisper model
448
- * @returns {Promise<any>} Extracted text
449
- */
451
+ piperBinary;
450
452
  asr(t, e = this.whisperModel) {
451
453
  if (!this.ai.options.whisper?.binary) throw new Error("Whisper not configured");
454
+ let n = () => {
455
+ };
456
+ const s = new Promise(async (r, l) => {
457
+ const o = await this.downloadAsrModel(e);
458
+ let d = "";
459
+ const p = P(this.ai.options.whisper?.binary, ["-nt", "-np", "-m", o, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
460
+ n = () => p.kill("SIGTERM"), p.on("error", (a) => l(a)), p.stdout.on("data", (a) => d += a.toString()), p.on("close", (a) => {
461
+ a === 0 ? r(d.trim() || null) : l(new Error(`Exit code ${a}`));
462
+ });
463
+ });
464
+ return Object.assign(s, { abort: n });
465
+ }
466
+ tts(t, e, n = this.ai.options.piper?.model) {
467
+ if (!this.piperBinary) throw new Error("Piper not configured");
468
+ if (!n) throw new Error("Invalid Piper model");
452
469
  let s = () => {
453
470
  };
454
- return { response: new Promise((i, d) => {
455
- this.downloadAsrModel(e).then((r) => {
456
- let l = "";
457
- const u = N(this.ai.options.whisper?.binary, ["-nt", "-np", "-m", r, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
458
- s = () => u.kill("SIGTERM"), u.on("error", (c) => d(c)), u.stdout.on("data", (c) => l += c.toString()), u.on("close", (c) => {
459
- c === 0 ? i(l.trim() || null) : d(new Error(`Exit code ${c}`));
460
- });
471
+ const r = new Promise(async (l, o) => {
472
+ const d = await this.downloadTtsModel(n), p = e || y.join(M.tmpdir(), `piper_${Date.now()}.wav`), a = P(this.piperBinary, ["--model", d, "--output_file", p], {
473
+ stdio: ["pipe", "ignore", "ignore"],
474
+ env: { ...process.env, LD_LIBRARY_PATH: y.dirname(this.piperBinary) }
461
475
  });
462
- }), abort: s };
476
+ s = () => a.kill("SIGTERM"), a.stdin.write(t), a.stdin.end(), a.on("error", (m) => o(m)), a.on("close", async (m) => {
477
+ if (m === 0)
478
+ if (e)
479
+ l(e);
480
+ else {
481
+ const h = await b.readFile(p);
482
+ await b.unlink(p).catch(() => {
483
+ }), l(h);
484
+ }
485
+ else
486
+ o(new Error(`Exit code ${m}`));
487
+ });
488
+ });
489
+ return Object.assign(r, { abort: s });
463
490
  }
464
- /**
465
- * Downloads the specified Whisper model if it is not already present locally.
466
- *
467
- * @param {string} model Whisper model that will be downloaded
468
- * @return {Promise<string>} Absolute path to model file, resolves once downloaded
469
- */
470
491
  async downloadAsrModel(t = this.whisperModel) {
471
492
  if (!this.ai.options.whisper?.binary) throw new Error("Whisper not configured");
472
493
  t.endsWith(".bin") || (t += ".bin");
473
- const e = W.join(this.ai.options.path, t);
474
- return await S.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[t] ? this.downloads[t] : (this.downloads[t] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then((s) => s.arrayBuffer()).then((s) => Buffer.from(s)).then(async (s) => (await S.writeFile(e, s), delete this.downloads[t], e)), this.downloads[t]);
494
+ const e = y.join(this.ai.options.path, t);
495
+ return await b.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[t] ? this.downloads[t] : (this.downloads[t] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then((n) => n.arrayBuffer()).then((n) => Buffer.from(n)).then(async (n) => (await b.writeFile(e, n), delete this.downloads[t], e)), this.downloads[t]);
496
+ }
497
+ async downloadTtsModel(t = this.ai.options.piper?.model) {
498
+ if (!t) throw new Error("Invalid Piper model");
499
+ const e = t.split("/").pop(), n = y.join(this.ai.options.path, e), [s, r] = await Promise.all([
500
+ b.stat(n).then(() => !0).catch(() => !1),
501
+ b.stat(n + ".json").then(() => !0).catch(() => !1)
502
+ ]);
503
+ return s && r ? n : this.downloads[e] ? this.downloads[e] : (this.downloads[e] = Promise.all([
504
+ s ? Promise.resolve() : fetch(t).then((l) => l.arrayBuffer()).then((l) => b.writeFile(n, Buffer.from(l))),
505
+ r ? Promise.resolve() : fetch(t + ".json").then((l) => l.arrayBuffer()).then((l) => b.writeFile(n + ".json", Buffer.from(l)))
506
+ ]).then(() => (delete this.downloads[e], n)), this.downloads[e]);
475
507
  }
476
508
  }
477
- class C {
509
+ class K {
478
510
  constructor(t) {
479
511
  this.ai = t;
480
512
  }
481
513
  /**
482
514
  * Convert image to text using Optical Character Recognition
483
515
  * @param {string} path Path to image
484
- * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text
516
+ * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method
485
517
  */
486
518
  ocr(t) {
487
519
  let e;
488
- return {
489
- abort: () => {
490
- e?.terminate();
491
- },
492
- response: new Promise(async (s) => {
493
- e = await D(this.ai.options.tesseract?.model || "eng", 2, { cachePath: this.ai.options.path });
494
- const { data: n } = await e.recognize(t);
495
- await e.terminate(), s(n.text.trim() || null);
496
- })
497
- };
520
+ const n = new Promise(async (s) => {
521
+ e = await N(this.ai.options.tesseract?.model || "eng", 2, { cachePath: this.ai.options.path });
522
+ const { data: r } = await e.recognize(t);
523
+ await e.terminate(), s(r.text.trim() || null);
524
+ });
525
+ return Object.assign(n, { abort: () => e?.terminate() });
498
526
  }
499
527
  }
500
- class le {
528
+ class pe {
501
529
  constructor(t) {
502
- this.options = t, t.path || (t.path = j.tmpdir()), process.env.TRANSFORMERS_CACHE = t.path, this.audio = new B(this), this.language = new G(this), this.vision = new C(this);
530
+ this.options = t, t.path || (t.path = M.tmpdir()), process.env.TRANSFORMERS_CACHE = t.path, this.audio = new C(this), this.language = new Q(this), this.vision = new K(this);
503
531
  }
504
532
  /** Audio processing AI */
505
533
  audio;
@@ -508,38 +536,38 @@ class le {
508
536
  /** Vision processing AI */
509
537
  vision;
510
538
  }
511
- const Q = {
539
+ const V = {
512
540
  name: "cli",
513
541
  description: "Use the command line interface, returns any output",
514
542
  args: { command: { type: "string", description: "Command to run", required: !0 } },
515
- fn: (p) => J`${p.command}`
516
- }, me = {
543
+ fn: (u) => H`${u.command}`
544
+ }, ue = {
517
545
  name: "get_datetime",
518
546
  description: "Get current date and time",
519
547
  args: {},
520
548
  fn: async () => (/* @__PURE__ */ new Date()).toISOString()
521
- }, de = {
549
+ }, fe = {
522
550
  name: "exec",
523
551
  description: "Run code/scripts",
524
552
  args: {
525
553
  language: { type: "string", description: "Execution language", enum: ["cli", "node", "python"], required: !0 },
526
554
  code: { type: "string", description: "Code to execute", required: !0 }
527
555
  },
528
- fn: async (p, t) => {
556
+ fn: async (u, t) => {
529
557
  try {
530
- switch (p.type) {
558
+ switch (u.type) {
531
559
  case "bash":
532
- return await Q.fn({ command: p.code }, t);
560
+ return await V.fn({ command: u.code }, t);
533
561
  case "node":
534
- return await K.fn({ code: p.code }, t);
562
+ return await Y.fn({ code: u.code }, t);
535
563
  case "python":
536
- return await V.fn({ code: p.code }, t);
564
+ return await X.fn({ code: u.code }, t);
537
565
  }
538
566
  } catch (e) {
539
567
  return { error: e?.message || e.toString() };
540
568
  }
541
569
  }
542
- }, ue = {
570
+ }, he = {
543
571
  name: "fetch",
544
572
  description: "Make HTTP request to URL",
545
573
  args: {
@@ -548,54 +576,54 @@ const Q = {
548
576
  headers: { type: "object", description: "HTTP headers to send", default: {} },
549
577
  body: { type: "object", description: "HTTP body to send" }
550
578
  },
551
- fn: (p) => new M({ url: p.url, headers: p.headers }).request({ method: p.method || "GET", body: p.body })
552
- }, K = {
579
+ fn: (u) => new q({ url: u.url, headers: u.headers }).request({ method: u.method || "GET", body: u.body })
580
+ }, Y = {
553
581
  name: "exec_javascript",
554
582
  description: "Execute commonjs javascript",
555
583
  args: {
556
584
  code: { type: "string", description: "CommonJS javascript", required: !0 }
557
585
  },
558
- fn: async (p) => {
559
- const t = A(null), e = await q({ console: t }, p.code, !0).catch((s) => t.output.error.push(s));
586
+ fn: async (u) => {
587
+ const t = O(null), e = await $({ console: t }, u.code, !0).catch((n) => t.output.error.push(n));
560
588
  return { ...t.output, return: e, stdout: void 0, stderr: void 0 };
561
589
  }
562
- }, V = {
590
+ }, X = {
563
591
  name: "exec_javascript",
564
592
  description: "Execute commonjs javascript",
565
593
  args: {
566
594
  code: { type: "string", description: "CommonJS javascript", required: !0 }
567
595
  },
568
- fn: async (p) => ({ result: H`python -c "${p.code}"` })
569
- }, pe = {
596
+ fn: async (u) => ({ result: J`python -c "${u.code}"` })
597
+ }, ge = {
570
598
  name: "search",
571
599
  description: "Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",
572
600
  args: {
573
601
  query: { type: "string", description: "Search string", required: !0 },
574
602
  length: { type: "string", description: "Number of results to return", default: 5 }
575
603
  },
576
- fn: async (p) => {
577
- const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(p.query)}`, {
604
+ fn: async (u) => {
605
+ const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(u.query)}`, {
578
606
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
579
- }).then((i) => i.text());
580
- let e, s = /<a .*?href="(.+?)".+?<\/a>/g;
581
- const n = new P();
582
- for (; (e = s.exec(t)) !== null; ) {
583
- let i = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
584
- if (i && (i = decodeURIComponent(i)), i && n.add(i), n.size >= (p.length || 5)) break;
607
+ }).then((r) => r.text());
608
+ let e, n = /<a .*?href="(.+?)".+?<\/a>/g;
609
+ const s = new v();
610
+ for (; (e = n.exec(t)) !== null; ) {
611
+ let r = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
612
+ if (r && (r = decodeURIComponent(r)), r && s.add(r), s.size >= (u.length || 5)) break;
585
613
  }
586
- return n;
614
+ return s;
587
615
  }
588
616
  };
589
617
  export {
590
- le as Ai,
591
- I as Anthropic,
592
- Q as CliTool,
593
- me as DateTimeTool,
594
- de as ExecTool,
595
- ue as FetchTool,
596
- K as JSTool,
597
- G as LLM,
598
- V as PythonTool,
599
- pe as SearchTool
618
+ pe as Ai,
619
+ F as Anthropic,
620
+ V as CliTool,
621
+ ue as DateTimeTool,
622
+ fe as ExecTool,
623
+ he as FetchTool,
624
+ Y as JSTool,
625
+ Q as LLM,
626
+ X as PythonTool,
627
+ ge as SearchTool
600
628
  };
601
629
  //# sourceMappingURL=index.mjs.map