@ztimson/ai-utils 0.8.11 → 0.8.12

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,23 +1,23 @@
1
1
  import * as O from "node:os";
2
2
  import { tmpdir as U } from "node:os";
3
- import { objectMap as z, JSONAttemptParse as _, findByProp as R, JSONSanitize as S, clean as W, Http as C, consoleInterceptor as N, fn as J, ASet as F } from "@ztimson/utils";
4
- import { Anthropic as B } from "@anthropic-ai/sdk";
5
- import { OpenAI as D } from "openai";
6
- import { fileURLToPath as H } from "url";
7
- import { join as I, dirname as G } from "path";
3
+ import { Anthropic as W } from "@anthropic-ai/sdk";
4
+ import { objectMap as z, JSONAttemptParse as S, findByProp as R, JSONSanitize as _, clean as N, Http as C, consoleInterceptor as J, fn as I, ASet as D } from "@ztimson/utils";
5
+ import { OpenAI as F } from "openai";
6
+ import { fileURLToPath as B } from "url";
7
+ import { join as H, dirname as G } from "path";
8
8
  import { spawn as w, execSync as K } from "node:child_process";
9
- import { mkdtempSync as V } from "node:fs";
9
+ import { mkdtempSync as Y } from "node:fs";
10
10
  import b from "node:fs/promises";
11
11
  import * as M from "node:path";
12
12
  import q, { join as A } from "node:path";
13
- import { createWorker as Y } from "tesseract.js";
13
+ import { createWorker as V } from "tesseract.js";
14
14
  import * as Z from "cheerio";
15
15
  import { $Sync as j } from "@ztimson/node-utils";
16
16
  class L {
17
17
  }
18
18
  class Q extends L {
19
19
  constructor(r, e, t) {
20
- super(), this.ai = r, this.apiToken = e, this.model = t, this.client = new B({ apiKey: e });
20
+ super(), this.ai = r, this.apiToken = e, this.model = t, this.client = new W({ apiKey: e });
21
21
  }
22
22
  client;
23
23
  toStandard(r) {
@@ -33,8 +33,8 @@ class Q extends L {
33
33
  if (n.type == "tool_use")
34
34
  t.push({ timestamp: e, role: "tool", id: n.id, name: n.name, args: n.input, content: void 0 });
35
35
  else if (n.type == "tool_result") {
36
- const u = t.findLast((l) => l.id == n.tool_use_id);
37
- u && (u[n.is_error ? "error" : "content"] = n.content);
36
+ const m = t.findLast((l) => l.id == n.tool_use_id);
37
+ m && (m[n.is_error ? "error" : "content"] = n.content);
38
38
  }
39
39
  });
40
40
  }
@@ -57,33 +57,33 @@ class Q extends L {
57
57
  const t = new AbortController();
58
58
  return Object.assign(new Promise(async (i) => {
59
59
  let o = this.fromStandard([...e.history || [], { role: "user", content: r, timestamp: Date.now() }]);
60
- const n = e.tools || this.ai.options.llm?.tools || [], u = {
60
+ const n = e.tools || this.ai.options.llm?.tools || [], m = {
61
61
  model: e.model || this.model,
62
62
  max_tokens: e.max_tokens || this.ai.options.llm?.max_tokens || 4096,
63
63
  system: e.system || this.ai.options.llm?.system || "",
64
64
  temperature: e.temperature || this.ai.options.llm?.temperature || 0.7,
65
- tools: n.map((m) => ({
66
- name: m.name,
67
- description: m.description,
65
+ tools: n.map((u) => ({
66
+ name: u.name,
67
+ description: u.description,
68
68
  input_schema: {
69
69
  type: "object",
70
- properties: m.args ? z(m.args, (s, a) => ({ ...a, required: void 0 })) : {},
71
- required: m.args ? Object.entries(m.args).filter((s) => s[1].required).map((s) => s[0]) : []
70
+ properties: u.args ? z(u.args, (s, c) => ({ ...c, required: void 0 })) : {},
71
+ required: u.args ? Object.entries(u.args).filter((s) => s[1].required).map((s) => s[0]) : []
72
72
  },
73
73
  fn: void 0
74
74
  })),
75
75
  messages: o,
76
76
  stream: !!e.stream
77
77
  };
78
- let l, c = !0;
78
+ let l, a = !0;
79
79
  do {
80
- if (l = await this.client.messages.create(u).catch((s) => {
80
+ if (l = await this.client.messages.create(m).catch((s) => {
81
81
  throw s.message += `
82
82
 
83
83
  Messages:
84
84
  ${JSON.stringify(o, null, 2)}`, s;
85
85
  }), e.stream) {
86
- c ? c = !1 : e.stream({ text: `
86
+ a ? a = !1 : e.stream({ text: `
87
87
 
88
88
  ` }), l.content = [];
89
89
  for await (const s of l) {
@@ -92,33 +92,33 @@ ${JSON.stringify(o, null, 2)}`, s;
92
92
  s.content_block.type === "text" ? l.content.push({ type: "text", text: "" }) : s.content_block.type === "tool_use" && l.content.push({ type: "tool_use", id: s.content_block.id, name: s.content_block.name, input: "" });
93
93
  else if (s.type === "content_block_delta")
94
94
  if (s.delta.type === "text_delta") {
95
- const a = s.delta.text;
96
- l.content.at(-1).text += a, e.stream({ text: a });
95
+ const c = s.delta.text;
96
+ l.content.at(-1).text += c, e.stream({ text: c });
97
97
  } else s.delta.type === "input_json_delta" && (l.content.at(-1).input += s.delta.partial_json);
98
98
  else if (s.type === "content_block_stop") {
99
- const a = l.content.at(-1);
100
- a.input != null && (a.input = a.input ? _(a.input, {}) : {});
99
+ const c = l.content.at(-1);
100
+ c.input != null && (c.input = c.input ? S(c.input, {}) : {});
101
101
  } else if (s.type === "message_stop")
102
102
  break;
103
103
  }
104
104
  }
105
- const m = l.content.filter((s) => s.type === "tool_use");
106
- if (m.length && !t.signal.aborted) {
105
+ const u = l.content.filter((s) => s.type === "tool_use");
106
+ if (u.length && !t.signal.aborted) {
107
107
  o.push({ role: "assistant", content: l.content });
108
- const s = await Promise.all(m.map(async (a) => {
109
- const d = n.find(R("name", a.name));
110
- if (e.stream && e.stream({ tool: a.name }), !d) return { tool_use_id: a.id, is_error: !0, content: "Tool not found" };
108
+ const s = await Promise.all(u.map(async (c) => {
109
+ const d = n.find(R("name", c.name));
110
+ if (e.stream && e.stream({ tool: c.name }), !d) return { tool_use_id: c.id, is_error: !0, content: "Tool not found" };
111
111
  try {
112
- const p = await d.fn(a.input, e?.stream, this.ai);
113
- return { type: "tool_result", tool_use_id: a.id, content: S(p) };
112
+ const p = await d.fn(c.input, e?.stream, this.ai);
113
+ return { type: "tool_result", tool_use_id: c.id, content: _(p) };
114
114
  } catch (p) {
115
- return { type: "tool_result", tool_use_id: a.id, is_error: !0, content: p?.message || p?.toString() || "Unknown" };
115
+ return { type: "tool_result", tool_use_id: c.id, is_error: !0, content: p?.message || p?.toString() || "Unknown" };
116
116
  }
117
117
  }));
118
- o.push({ role: "user", content: s }), u.messages = o;
118
+ o.push({ role: "user", content: s }), m.messages = o;
119
119
  }
120
- } while (!t.signal.aborted && l.content.some((m) => m.type === "tool_use"));
121
- o.push({ role: "assistant", content: l.content.filter((m) => m.type == "text").map((m) => m.text).join(`
120
+ } while (!t.signal.aborted && l.content.some((u) => u.type === "tool_use"));
121
+ o.push({ role: "assistant", content: l.content.filter((u) => u.type == "text").map((u) => u.text).join(`
122
122
 
123
123
  `) }), o = this.toStandard(o), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...o), i(o.at(-1)?.content);
124
124
  }), { abort: () => t.abort() });
@@ -126,7 +126,7 @@ ${JSON.stringify(o, null, 2)}`, s;
126
126
  }
127
127
  class P extends L {
128
128
  constructor(r, e, t, i) {
129
- super(), this.ai = r, this.host = e, this.token = t, this.model = i, this.client = new D(W({
129
+ super(), this.ai = r, this.host = e, this.token = t, this.model = i, this.client = new F(N({
130
130
  baseURL: e,
131
131
  apiKey: t || e ? "ignored" : void 0
132
132
  }));
@@ -140,7 +140,7 @@ class P extends L {
140
140
  role: "tool",
141
141
  id: o.id,
142
142
  name: o.function.name,
143
- args: _(o.function.arguments, {}),
143
+ args: S(o.function.arguments, {}),
144
144
  timestamp: t.timestamp
145
145
  }));
146
146
  r.splice(e, 1, ...i), e += i.length - 1;
@@ -178,42 +178,42 @@ class P extends L {
178
178
  return Object.assign(new Promise(async (i, o) => {
179
179
  e.system && (e.history?.[0]?.role != "system" ? e.history?.splice(0, 0, { role: "system", content: e.system, timestamp: Date.now() }) : e.history[0].content = e.system);
180
180
  let n = this.fromStandard([...e.history || [], { role: "user", content: r, timestamp: Date.now() }]);
181
- const u = e.tools || this.ai.options.llm?.tools || [], l = {
181
+ const m = e.tools || this.ai.options.llm?.tools || [], l = {
182
182
  model: e.model || this.model,
183
183
  messages: n,
184
184
  stream: !!e.stream,
185
185
  max_tokens: e.max_tokens || this.ai.options.llm?.max_tokens || 4096,
186
186
  temperature: e.temperature || this.ai.options.llm?.temperature || 0.7,
187
- tools: u.map((s) => ({
187
+ tools: m.map((s) => ({
188
188
  type: "function",
189
189
  function: {
190
190
  name: s.name,
191
191
  description: s.description,
192
192
  parameters: {
193
193
  type: "object",
194
- properties: s.args ? z(s.args, (a, d) => ({ ...d, required: void 0 })) : {},
195
- required: s.args ? Object.entries(s.args).filter((a) => a[1].required).map((a) => a[0]) : []
194
+ properties: s.args ? z(s.args, (c, d) => ({ ...d, required: void 0 })) : {},
195
+ required: s.args ? Object.entries(s.args).filter((c) => c[1].required).map((c) => c[0]) : []
196
196
  }
197
197
  }
198
198
  }))
199
199
  };
200
- let c, m = !0;
200
+ let a, u = !0;
201
201
  do {
202
- if (c = await this.client.chat.completions.create(l).catch((a) => {
203
- throw a.message += `
202
+ if (a = await this.client.chat.completions.create(l).catch((c) => {
203
+ throw c.message += `
204
204
 
205
205
  Messages:
206
- ${JSON.stringify(n, null, 2)}`, a;
206
+ ${JSON.stringify(n, null, 2)}`, c;
207
207
  }), e.stream) {
208
- m ? m = !1 : e.stream({ text: `
208
+ u ? u = !1 : e.stream({ text: `
209
209
 
210
- ` }), c.choices = [{ message: { role: "assistant", content: "", tool_calls: [] } }];
211
- for await (const a of c) {
210
+ ` }), a.choices = [{ message: { role: "assistant", content: "", tool_calls: [] } }];
211
+ for await (const c of a) {
212
212
  if (t.signal.aborted) break;
213
- if (a.choices[0].delta.content && (c.choices[0].message.content += a.choices[0].delta.content, e.stream({ text: a.choices[0].delta.content })), a.choices[0].delta.tool_calls)
214
- for (const d of a.choices[0].delta.tool_calls) {
215
- const p = c.choices[0].message.tool_calls.find((f) => f.index === d.index);
216
- p ? (d.id && (p.id = d.id), d.type && (p.type = d.type), d.function && (p.function || (p.function = {}), d.function.name && (p.function.name = d.function.name), d.function.arguments && (p.function.arguments = (p.function.arguments || "") + d.function.arguments))) : c.choices[0].message.tool_calls.push({
213
+ if (c.choices[0].delta.content && (a.choices[0].message.content += c.choices[0].delta.content, e.stream({ text: c.choices[0].delta.content })), c.choices[0].delta.tool_calls)
214
+ for (const d of c.choices[0].delta.tool_calls) {
215
+ const p = a.choices[0].message.tool_calls.find((f) => f.index === d.index);
216
+ p ? (d.id && (p.id = d.id), d.type && (p.type = d.type), d.function && (p.function || (p.function = {}), d.function.name && (p.function.name = d.function.name), d.function.arguments && (p.function.arguments = (p.function.arguments || "") + d.function.arguments))) : a.choices[0].message.tool_calls.push({
217
217
  index: d.index,
218
218
  id: d.id || "",
219
219
  type: d.type || "function",
@@ -225,23 +225,23 @@ ${JSON.stringify(n, null, 2)}`, a;
225
225
  }
226
226
  }
227
227
  }
228
- const s = c.choices[0].message.tool_calls || [];
228
+ const s = a.choices[0].message.tool_calls || [];
229
229
  if (s.length && !t.signal.aborted) {
230
- n.push(c.choices[0].message);
231
- const a = await Promise.all(s.map(async (d) => {
232
- const p = u?.find(R("name", d.function.name));
230
+ n.push(a.choices[0].message);
231
+ const c = await Promise.all(s.map(async (d) => {
232
+ const p = m?.find(R("name", d.function.name));
233
233
  if (e.stream && e.stream({ tool: d.function.name }), !p) return { role: "tool", tool_call_id: d.id, content: '{"error": "Tool not found"}' };
234
234
  try {
235
- const f = _(d.function.arguments, {}), g = await p.fn(f, e.stream, this.ai);
236
- return { role: "tool", tool_call_id: d.id, content: S(g) };
235
+ const f = S(d.function.arguments, {}), g = await p.fn(f, e.stream, this.ai);
236
+ return { role: "tool", tool_call_id: d.id, content: _(g) };
237
237
  } catch (f) {
238
- return { role: "tool", tool_call_id: d.id, content: S({ error: f?.message || f?.toString() || "Unknown" }) };
238
+ return { role: "tool", tool_call_id: d.id, content: _({ error: f?.message || f?.toString() || "Unknown" }) };
239
239
  }
240
240
  }));
241
- n.push(...a), l.messages = n;
241
+ n.push(...c), l.messages = n;
242
242
  }
243
- } while (!t.signal.aborted && c.choices?.[0]?.message?.tool_calls?.length);
244
- n.push({ role: "assistant", content: c.choices[0].message.content || "" }), n = this.toStandard(n), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...n), i(n.at(-1)?.content);
243
+ } while (!t.signal.aborted && a.choices?.[0]?.message?.tool_calls?.length);
244
+ n.push({ role: "assistant", content: a.choices[0].message.content || "" }), n = this.toStandard(n), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...n), i(n.at(-1)?.content);
245
245
  }), { abort: () => t.abort() });
246
246
  }
247
247
  }
@@ -274,13 +274,13 @@ class X {
274
274
  };
275
275
  return Object.assign(new Promise(async (o) => {
276
276
  if (e.history || (e.history = []), e.memory) {
277
- const u = async (c, m, s = 10) => {
278
- const [a, d] = await Promise.all([
279
- m ? this.embedding(m) : Promise.resolve(null),
280
- c ? this.embedding(c) : Promise.resolve(null)
277
+ const m = async (a, u, s = 10) => {
278
+ const [c, d] = await Promise.all([
279
+ u ? this.embedding(u) : Promise.resolve(null),
280
+ a ? this.embedding(a) : Promise.resolve(null)
281
281
  ]);
282
282
  return (e.memory || []).map((p) => {
283
- const f = (a ? this.cosineSimilarity(p.embeddings[0], a[0].embedding) : 0) + (d ? this.cosineSimilarity(p.embeddings[1], d[0].embedding) : 0);
283
+ const f = (c ? this.cosineSimilarity(p.embeddings[0], c[0].embedding) : 0) + (d ? this.cosineSimilarity(p.embeddings[1], d[0].embedding) : 0);
284
284
  return { ...p, score: f };
285
285
  }).toSorted((p, f) => p.score - f.score).slice(0, s).map((p) => `- ${p.owner}: ${p.fact}`).join(`
286
286
  `);
@@ -288,7 +288,7 @@ class X {
288
288
  e.system += `
289
289
  You have RAG memory and will be given the top_k closest memories regarding the users query. Save anything new you have learned worth remembering from the user message using the remember tool and feel free to recall memories manually.
290
290
  `;
291
- const l = await u(r);
291
+ const l = await m(r);
292
292
  l.length && e.history.push({ role: "tool", name: "recall", id: "auto_recall_" + Math.random().toString(), args: {}, content: `Things I remembered:
293
293
  ${l}` }), e.tools = [{
294
294
  name: "recall",
@@ -298,9 +298,9 @@ ${l}` }), e.tools = [{
298
298
  query: { type: "string", description: "Search memory based on a query, can be used with or without subject argument" },
299
299
  topK: { type: "number", description: "Result limit, default 5" }
300
300
  },
301
- fn: (c) => {
302
- if (!c.subject && !c.query) throw new Error("Either a subject or query argument is required");
303
- return u(c.query, c.subject, c.topK);
301
+ fn: (a) => {
302
+ if (!a.subject && !a.query) throw new Error("Either a subject or query argument is required");
303
+ return m(a.query, a.subject, a.topK);
304
304
  }
305
305
  }, {
306
306
  name: "remember",
@@ -309,20 +309,20 @@ ${l}` }), e.tools = [{
309
309
  owner: { type: "string", description: "Subject/person this fact is about" },
310
310
  fact: { type: "string", description: "The information to remember" }
311
311
  },
312
- fn: async (c) => {
312
+ fn: async (a) => {
313
313
  if (!e.memory) return;
314
- const m = await Promise.all([
315
- this.embedding(c.owner),
316
- this.embedding(`${c.owner}: ${c.fact}`)
317
- ]), s = { owner: c.owner, fact: c.fact, embeddings: [m[0][0].embedding, m[1][0].embedding] };
318
- return e.memory.splice(0, e.memory.length, ...e.memory.filter((a) => !(this.cosineSimilarity(s.embeddings[0], a.embeddings[0]) >= 0.9 && this.cosineSimilarity(s.embeddings[1], a.embeddings[1]) >= 0.8)), s), "Remembered!";
314
+ const u = await Promise.all([
315
+ this.embedding(a.owner),
316
+ this.embedding(`${a.owner}: ${a.fact}`)
317
+ ]), s = { owner: a.owner, fact: a.fact, embeddings: [u[0][0].embedding, u[1][0].embedding] };
318
+ return e.memory.splice(0, e.memory.length, ...e.memory.filter((c) => !(this.cosineSimilarity(s.embeddings[0], c.embeddings[0]) >= 0.9 && this.cosineSimilarity(s.embeddings[1], c.embeddings[1]) >= 0.8)), s), "Remembered!";
319
319
  }
320
320
  }, ...e.tools || []];
321
321
  }
322
322
  const n = await this.models[t].ask(r, e);
323
- if (e.memory && e.history.splice(0, e.history.length, ...e.history.filter((u) => u.role != "tool" || u.name != "recall" && u.name != "remember")), e.compress) {
324
- const u = await this.ai.language.compressHistory(e.history, e.compress.max, e.compress.min, e);
325
- e.history.splice(0, e.history.length, ...u);
323
+ if (e.memory && e.history.splice(0, e.history.length, ...e.history.filter((m) => m.role != "tool" || m.name != "recall" && m.name != "remember")), e.compress) {
324
+ const m = await this.ai.language.compressHistory(e.history, e.compress.max, e.compress.min, e);
325
+ e.history.splice(0, e.history.length, ...m);
326
326
  }
327
327
  return o(n);
328
328
  }), { abort: i });
@@ -350,10 +350,10 @@ ${l}` }), e.tools = [{
350
350
  if (n += this.estimateTokens(d.content), n < t) o++;
351
351
  else break;
352
352
  if (r.length <= o) return r;
353
- const u = r[0].role == "system" ? r[0] : null, l = o == 0 ? [] : r.slice(-o), c = (o == 0 ? r : r.slice(0, -o)).filter((d) => d.role === "assistant" || d.role === "user"), m = await this.summarize(c.map((d) => `[${d.role}]: ${d.content}`).join(`
353
+ const m = r[0].role == "system" ? r[0] : null, l = o == 0 ? [] : r.slice(-o), a = (o == 0 ? r : r.slice(0, -o)).filter((d) => d.role === "assistant" || d.role === "user"), u = await this.summarize(a.map((d) => `[${d.role}]: ${d.content}`).join(`
354
354
 
355
- `), 500, i), s = Date.now(), a = [{ role: "tool", name: "summary", id: "summary_" + s, args: {}, content: `Conversation Summary: ${m?.summary}`, timestamp: s }, ...l];
356
- return u && a.splice(0, 0, u), a;
355
+ `), 500, i), s = Date.now(), c = [{ role: "tool", name: "summary", id: "summary_" + s, args: {}, content: `Conversation Summary: ${u?.summary}`, timestamp: s }, ...l];
356
+ return m && c.splice(0, 0, m), c;
357
357
  }
358
358
  /**
359
359
  * Compare the difference between embeddings (calculates the angle between two vectors)
@@ -364,8 +364,8 @@ ${l}` }), e.tools = [{
364
364
  cosineSimilarity(r, e) {
365
365
  if (r.length !== e.length) throw new Error("Vectors must be same length");
366
366
  let t = 0, i = 0, o = 0;
367
- for (let u = 0; u < r.length; u++)
368
- t += r[u] * e[u], i += r[u] * r[u], o += e[u] * e[u];
367
+ for (let m = 0; m < r.length; m++)
368
+ t += r[m] * e[m], i += r[m] * r[m], o += e[m] * e[m];
369
369
  const n = Math.sqrt(i) * Math.sqrt(o);
370
370
  return n === 0 ? 0 : t / n;
371
371
  }
@@ -377,25 +377,25 @@ ${l}` }), e.tools = [{
377
377
  * @returns {string[]} Chunked strings
378
378
  */
379
379
  chunk(r, e = 500, t = 50) {
380
- const i = (l, c = "") => l ? Object.entries(l).flatMap(([m, s]) => {
381
- const a = c ? `${c}${isNaN(+m) ? `.${m}` : `[${m}]`}` : m;
382
- return typeof s == "object" && !Array.isArray(s) ? i(s, a) : `${a}: ${Array.isArray(s) ? s.join(", ") : s}`;
380
+ const i = (l, a = "") => l ? Object.entries(l).flatMap(([u, s]) => {
381
+ const c = a ? `${a}${isNaN(+u) ? `.${u}` : `[${u}]`}` : u;
382
+ return typeof s == "object" && !Array.isArray(s) ? i(s, c) : `${c}: ${Array.isArray(s) ? s.join(", ") : s}`;
383
383
  }) : [], n = (typeof r == "object" ? i(r) : r.toString().split(`
384
384
  `)).flatMap((l) => [...l.split(/\s+/).filter(Boolean), `
385
- `]), u = [];
385
+ `]), m = [];
386
386
  for (let l = 0; l < n.length; ) {
387
- let c = "", m = l;
388
- for (; m < n.length; ) {
389
- const a = c + (c ? " " : "") + n[m];
390
- if (this.estimateTokens(a.replace(/\s*\n\s*/g, `
391
- `)) > e && c) break;
392
- c = a, m++;
387
+ let a = "", u = l;
388
+ for (; u < n.length; ) {
389
+ const c = a + (a ? " " : "") + n[u];
390
+ if (this.estimateTokens(c.replace(/\s*\n\s*/g, `
391
+ `)) > e && a) break;
392
+ a = c, u++;
393
393
  }
394
- const s = c.replace(/\s*\n\s*/g, `
394
+ const s = a.replace(/\s*\n\s*/g, `
395
395
  `).trim();
396
- s && u.push(s), l = Math.max(m - t, m === l ? l + 1 : m);
396
+ s && m.push(s), l = Math.max(u - t, u === l ? l + 1 : u);
397
397
  }
398
- return u;
398
+ return m;
399
399
  }
400
400
  /**
401
401
  * Create a vector representation of a string
@@ -407,21 +407,21 @@ ${l}` }), e.tools = [{
407
407
  let { maxTokens: t = 500, overlapTokens: i = 50 } = e, o = !1;
408
408
  const n = () => {
409
409
  o = !0;
410
- }, u = (c) => new Promise((m, s) => {
410
+ }, m = (a) => new Promise((u, s) => {
411
411
  if (o) return s(new Error("Aborted"));
412
- const a = [
413
- I(G(H(import.meta.url)), "embedder.js"),
412
+ const c = [
413
+ H(G(B(import.meta.url)), "embedder.js"),
414
414
  this.ai.options.path,
415
415
  this.ai.options?.embedder || "bge-small-en-v1.5"
416
- ], d = w("node", a, { stdio: ["pipe", "pipe", "ignore"] });
417
- d.stdin.write(c), d.stdin.end();
416
+ ], d = w("node", c, { stdio: ["pipe", "pipe", "ignore"] });
417
+ d.stdin.write(a), d.stdin.end();
418
418
  let p = "";
419
419
  d.stdout.on("data", (f) => p += f.toString()), d.on("close", (f) => {
420
420
  if (o) return s(new Error("Aborted"));
421
421
  if (f === 0)
422
422
  try {
423
423
  const g = JSON.parse(p);
424
- m(g.embedding);
424
+ u(g.embedding);
425
425
  } catch {
426
426
  s(new Error("Failed to parse embedding output"));
427
427
  }
@@ -429,12 +429,12 @@ ${l}` }), e.tools = [{
429
429
  s(new Error(`Embedder process exited with code ${f}`));
430
430
  }), d.on("error", s);
431
431
  }), l = (async () => {
432
- const c = this.chunk(r, t, i), m = [];
433
- for (let s = 0; s < c.length && !o; s++) {
434
- const a = c[s], d = await u(a);
435
- m.push({ index: s, embedding: d, text: a, tokens: this.estimateTokens(a) });
432
+ const a = this.chunk(r, t, i), u = [];
433
+ for (let s = 0; s < a.length && !o; s++) {
434
+ const c = a[s], d = await m(c);
435
+ u.push({ index: s, embedding: d, text: c, tokens: this.estimateTokens(c) });
436
436
  }
437
- return m;
437
+ return u;
438
438
  })();
439
439
  return Object.assign(l, { abort: n });
440
440
  }
@@ -455,8 +455,8 @@ ${l}` }), e.tools = [{
455
455
  */
456
456
  fuzzyMatch(r, ...e) {
457
457
  if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
458
- const t = (n, u = 10) => n.toLowerCase().split("").map((l, c) => l.charCodeAt(0) * (c + 1) % u / u).slice(0, u), i = t(r), o = e.map((n) => t(n)).map((n) => this.cosineSimilarity(i, n));
459
- return { avg: o.reduce((n, u) => n + u, 0) / o.length, max: Math.max(...o), similarities: o };
458
+ const t = (n, m = 10) => n.toLowerCase().split("").map((l, a) => l.charCodeAt(0) * (a + 1) % m / m).slice(0, m), i = t(r), o = e.map((n) => t(n)).map((n) => this.cosineSimilarity(i, n));
459
+ return { avg: o.reduce((n, m) => n + m, 0) / o.length, max: Math.max(...o), similarities: o };
460
460
  }
461
461
  /**
462
462
  * Ask a question with JSON response
@@ -466,15 +466,35 @@ ${l}` }), e.tools = [{
466
466
  * @returns {Promise<{} | {} | RegExpExecArray | null>}
467
467
  */
468
468
  async json(r, e, t) {
469
- const i = await this.code(r, { ...t, system: [
470
- t?.system,
471
- `Only respond using JSON matching this schema:
469
+ let i = `Your job is to convert input to JSON. Call \`submit\` exactly once with JSON matching this schema:
472
470
  \`\`\`json
473
471
  ${e}
474
- \`\`\``
475
- ].filter((o) => !!o).join(`
476
- `) });
477
- return i ? _(i, {}) : null;
472
+ \`\`\``;
473
+ return t?.system && (i += `
474
+
475
+ ` + t.system), new Promise(async (o, n) => {
476
+ let m = !1;
477
+ const l = await this.ask(r, {
478
+ temperature: 0.3,
479
+ ...t,
480
+ system: i,
481
+ tools: [{
482
+ name: "submit",
483
+ description: "Submit JSON",
484
+ args: { json: { type: "string", description: "Javascript parsable JSON string", required: !0 } },
485
+ fn: (a) => {
486
+ try {
487
+ const u = JSON.parse(a.json);
488
+ o(u), m = !0;
489
+ } catch {
490
+ return "Invalid JSON";
491
+ }
492
+ return "Done";
493
+ }
494
+ }, ...t?.tools || []]
495
+ });
496
+ m || n(`AI failed to create summary: ${l}`);
497
+ });
478
498
  }
479
499
  /**
480
500
  * Create a summary of some text
@@ -483,8 +503,25 @@ ${e}
483
503
  * @param options LLM request options
484
504
  * @returns {Promise<string>} Summary
485
505
  */
486
- summarize(r, e = 500, t) {
487
- return this.ask(r, { system: `Generate the shortest summary possible <= ${e} tokens. Output nothing else`, temperature: 0.3, ...t });
506
+ async summarize(r, e = 500, t) {
507
+ let i = `Your job is to summarize the users message. Call \`submit\` exactly once with the shortest summary possible that's <= ${e} tokens. Output nothing else`;
508
+ return t?.system && (i += `
509
+
510
+ ` + t.system), new Promise(async (o, n) => {
511
+ let m = !1;
512
+ const l = await this.ask(r, {
513
+ temperature: 0.3,
514
+ ...t,
515
+ system: i,
516
+ tools: [{
517
+ name: "submit",
518
+ description: "Submit summary",
519
+ args: { summary: { type: "string", description: "Summarization", required: !0 } },
520
+ fn: (a) => (m = !0, o(a.summary || null), "Done")
521
+ }, ...t?.tools || []]
522
+ });
523
+ m || n(`AI failed to create summary: ${l}`);
524
+ });
488
525
  }
489
526
  }
490
527
  class ee {
@@ -512,18 +549,18 @@ print(json.dumps(segments))
512
549
  async addPunctuation(r, e, t = 150) {
513
550
  const i = (n) => {
514
551
  if (n = n.toLowerCase().replace(/[^a-z]/g, ""), n.length <= 3) return 1;
515
- const u = n.match(/[aeiouy]+/g);
516
- let l = u ? u.length : 1;
552
+ const m = n.match(/[aeiouy]+/g);
553
+ let l = m ? m.length : 1;
517
554
  return n.endsWith("e") && l--, Math.max(1, l);
518
555
  };
519
556
  let o = "";
520
- return r.transcription.filter((n, u) => {
557
+ return r.transcription.filter((n, m) => {
521
558
  let l = !1;
522
- const c = r.transcription[u - 1], m = r.transcription[u + 1];
523
- return !n.text && m ? (m.offsets.from = n.offsets.from, m.timestamps.from = n.offsets.from) : n.text && n.text[0] != " " && c && (c.offsets.to = n.offsets.to, c.timestamps.to = n.timestamps.to, c.text += n.text, l = !0), !!n.text && !l;
559
+ const a = r.transcription[m - 1], u = r.transcription[m + 1];
560
+ return !n.text && u ? (u.offsets.from = n.offsets.from, u.timestamps.from = n.offsets.from) : n.text && n.text[0] != " " && a && (a.offsets.to = n.offsets.to, a.timestamps.to = n.timestamps.to, a.text += n.text, l = !0), !!n.text && !l;
524
561
  }).forEach((n) => {
525
- const u = /^[A-Z]/.test(n.text.trim()), l = n.offsets.to - n.offsets.from, m = i(n.text.trim()) * t;
526
- u && l > m * 2 && n.text[0] == " " && (o += "."), o += n.text;
562
+ const m = /^[A-Z]/.test(n.text.trim()), l = n.offsets.to - n.offsets.from, u = i(n.text.trim()) * t;
563
+ m && l > u * 2 && n.text[0] == " " && (o += "."), o += n.text;
527
564
  }), e ? this.ai.language.ask(o, {
528
565
  system: "Remove any misplaced punctuation from the following ASR transcript using the replace tool. Avoid modifying words unless there is an obvious typo",
529
566
  temperature: 0.1,
@@ -544,15 +581,15 @@ print(json.dumps(segments))
544
581
  e.forEach((p) => {
545
582
  i.has(p.speaker) || i.set(p.speaker, ++o);
546
583
  });
547
- const n = await this.addPunctuation(r, t), u = n.match(/[^.!?]+[.!?]+/g) || [n], l = r.transcription.filter((p) => p.text.trim()), c = u.map((p) => {
584
+ const n = await this.addPunctuation(r, t), m = n.match(/[^.!?]+[.!?]+/g) || [n], l = r.transcription.filter((p) => p.text.trim()), a = m.map((p) => {
548
585
  if (p = p.trim(), !p) return null;
549
586
  const f = p.toLowerCase().replace(/[^\w\s]/g, "").split(/\s+/), g = /* @__PURE__ */ new Map();
550
587
  f.forEach((x) => {
551
588
  const k = l.find((y) => x === y.text.trim().toLowerCase().replace(/[^\w]/g, ""));
552
589
  if (!k) return;
553
- const $ = k.offsets.from / 1e3, v = e.find((y) => $ >= y.start && $ <= y.end);
554
- if (v) {
555
- const y = i.get(v.speaker);
590
+ const v = k.offsets.from / 1e3, $ = e.find((y) => v >= y.start && v <= y.end);
591
+ if ($) {
592
+ const y = i.get($.speaker);
556
593
  g.set(y, (g.get(y) || 0) + 1);
557
594
  }
558
595
  });
@@ -560,17 +597,17 @@ print(json.dumps(segments))
560
597
  return g.forEach((x, k) => {
561
598
  x > E && (E = x, T = k);
562
599
  }), { speaker: T, text: p };
563
- }).filter((p) => p !== null), m = [];
564
- c.forEach((p) => {
565
- const f = m[m.length - 1];
566
- f && f.speaker === p.speaker ? f.text += " " + p.text : m.push({ ...p });
600
+ }).filter((p) => p !== null), u = [];
601
+ a.forEach((p) => {
602
+ const f = u[u.length - 1];
603
+ f && f.speaker === p.speaker ? f.text += " " + p.text : u.push({ ...p });
567
604
  });
568
- let s = m.map((p) => `[Speaker ${p.speaker}]: ${p.text}`).join(`
605
+ let s = u.map((p) => `[Speaker ${p.speaker}]: ${p.text}`).join(`
569
606
  `).trim();
570
607
  if (!t) return s;
571
- let a = this.ai.language.chunk(s, 500, 0);
572
- a.length > 4 && (a = [...a.slice(0, 3), a.at(-1)]);
573
- const d = await this.ai.language.json(a.join(`
608
+ let c = this.ai.language.chunk(s, 500, 0);
609
+ c.length > 4 && (c = [...c.slice(0, 3), c.at(-1)]);
610
+ const d = await this.ai.language.json(c.join(`
574
611
  `), '{1: "Detected Name", 2: "Second Name"}', {
575
612
  system: "Use the following transcript to identify speakers. Only identify speakers you are positive about, dont mention speakers you are unsure about in your response",
576
613
  temperature: 0.1
@@ -580,15 +617,15 @@ print(json.dumps(segments))
580
617
  runAsr(r, e = {}) {
581
618
  let t;
582
619
  const i = new Promise((o, n) => {
583
- this.downloadAsrModel(e.model).then((u) => {
620
+ this.downloadAsrModel(e.model).then((m) => {
584
621
  if (e.diarization) {
585
622
  let l = M.join(M.dirname(r), "transcript");
586
623
  t = w(
587
624
  this.ai.options.whisper,
588
- ["-m", u, "-f", r, "-np", "-ml", "1", "-oj", "-of", l],
625
+ ["-m", m, "-f", r, "-np", "-ml", "1", "-oj", "-of", l],
589
626
  { stdio: ["ignore", "ignore", "pipe"] }
590
- ), t.on("error", (c) => n(c)), t.on("close", async (c) => {
591
- if (c === 0) {
627
+ ), t.on("error", (a) => n(a)), t.on("close", async (a) => {
628
+ if (a === 0) {
592
629
  l = await b.readFile(l + ".json", "utf-8"), b.rm(l + ".json").catch(() => {
593
630
  });
594
631
  try {
@@ -597,12 +634,12 @@ print(json.dumps(segments))
597
634
  n(new Error("Failed to parse whisper JSON"));
598
635
  }
599
636
  } else
600
- n(new Error(`Exit code ${c}`));
637
+ n(new Error(`Exit code ${a}`));
601
638
  });
602
639
  } else {
603
640
  let l = "";
604
- t = w(this.ai.options.whisper, ["-m", u, "-f", r, "-np", "-nt"]), t.on("error", (c) => n(c)), t.stdout.on("data", (c) => l += c.toString()), t.on("close", async (c) => {
605
- c === 0 ? o(l.trim() || null) : n(new Error(`Exit code ${c}`));
641
+ t = w(this.ai.options.whisper, ["-m", m, "-f", r, "-np", "-nt"]), t.on("error", (a) => n(a)), t.stdout.on("data", (a) => l += a.toString()), t.on("close", async (a) => {
642
+ a === 0 ? o(l.trim() || null) : n(new Error(`Exit code ${a}`));
606
643
  });
607
644
  }
608
645
  });
@@ -613,53 +650,53 @@ print(json.dumps(segments))
613
650
  let e = !1, t = () => {
614
651
  e = !0;
615
652
  };
616
- const i = (n) => new Promise((u) => {
653
+ const i = (n) => new Promise((m) => {
617
654
  const l = w(n, ["-W", "ignore", "-c", "import pyannote.audio"]);
618
- l.on("close", (c) => u(c === 0)), l.on("error", () => u(!1));
655
+ l.on("close", (a) => m(a === 0)), l.on("error", () => m(!1));
619
656
  }), o = Promise.all([
620
657
  i("python"),
621
658
  i("python3")
622
- ]).then((async ([n, u]) => {
659
+ ]).then((async ([n, m]) => {
623
660
  if (e) return;
624
- if (!n && !u) throw new Error("Pyannote is not installed: pip install pyannote.audio");
625
- const l = u ? "python3" : "python";
626
- return new Promise((c, m) => {
661
+ if (!n && !m) throw new Error("Pyannote is not installed: pip install pyannote.audio");
662
+ const l = m ? "python3" : "python";
663
+ return new Promise((a, u) => {
627
664
  if (e) return;
628
665
  let s = "";
629
- const a = w(l, ["-W", "ignore", "-c", this.pyannote, r]);
630
- a.stdout.on("data", (d) => s += d.toString()), a.stderr.on("data", (d) => console.error(d.toString())), a.on("close", (d) => {
666
+ const c = w(l, ["-W", "ignore", "-c", this.pyannote, r]);
667
+ c.stdout.on("data", (d) => s += d.toString()), c.stderr.on("data", (d) => console.error(d.toString())), c.on("close", (d) => {
631
668
  if (d === 0)
632
669
  try {
633
- c(JSON.parse(s));
670
+ a(JSON.parse(s));
634
671
  } catch {
635
- m(new Error("Failed to parse diarization output"));
672
+ u(new Error("Failed to parse diarization output"));
636
673
  }
637
674
  else
638
- m(new Error(`Python process exited with code ${d}`));
639
- }), a.on("error", m), t = () => a.kill("SIGTERM");
675
+ u(new Error(`Python process exited with code ${d}`));
676
+ }), c.on("error", u), t = () => c.kill("SIGTERM");
640
677
  });
641
678
  }));
642
679
  return Object.assign(o, { abort: t });
643
680
  }
644
681
  asr(r, e = {}) {
645
682
  if (!this.ai.options.whisper) throw new Error("Whisper not configured");
646
- const t = A(V(A(U(), "audio-")), "converted.wav");
683
+ const t = A(Y(A(U(), "audio-")), "converted.wav");
647
684
  K(`ffmpeg -i "${r}" -ar 16000 -ac 1 -f wav "${t}"`, { stdio: "ignore" });
648
685
  const i = () => b.rm(q.dirname(t), { recursive: !0, force: !0 }).catch(() => {
649
686
  });
650
687
  if (!e.diarization) return this.runAsr(t, { model: e.model });
651
688
  const o = this.runAsr(t, { model: e.model, diarization: !0 }), n = this.runDiarization(t);
652
- let u = !1, l = () => {
653
- u = !0, o.abort(), n.abort(), i();
689
+ let m = !1, l = () => {
690
+ m = !0, o.abort(), n.abort(), i();
654
691
  };
655
- const c = Promise.allSettled([o, n]).then(async ([m, s]) => {
656
- if (m.status == "rejected") throw new Error(`Whisper.cpp timestamps:
657
- ` + m.reason);
692
+ const a = Promise.allSettled([o, n]).then(async ([u, s]) => {
693
+ if (u.status == "rejected") throw new Error(`Whisper.cpp timestamps:
694
+ ` + u.reason);
658
695
  if (s.status == "rejected") throw new Error(`Pyannote:
659
696
  ` + s.reason);
660
- return u || !e.diarization ? m.value : this.diarizeTranscript(m.value, s.value, e.diarization == "llm");
697
+ return m || !e.diarization ? u.value : this.diarizeTranscript(u.value, s.value, e.diarization == "llm");
661
698
  }).finally(() => i());
662
- return Object.assign(c, { abort: l });
699
+ return Object.assign(a, { abort: l });
663
700
  }
664
701
  async downloadAsrModel(r = this.whisperModel) {
665
702
  if (!this.ai.options.whisper) throw new Error("Whisper not configured");
@@ -680,7 +717,7 @@ class te {
680
717
  ocr(r) {
681
718
  let e;
682
719
  const t = new Promise(async (i) => {
683
- e = await Y(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
720
+ e = await V(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
684
721
  const { data: o } = await e.recognize(r);
685
722
  await e.terminate(), i(o.text.trim() || null);
686
723
  });
@@ -736,7 +773,7 @@ const re = () => O.platform() == "win32" ? "cmd" : j`echo $SHELL`?.split("/").po
736
773
  return { error: t?.message || t.toString() };
737
774
  }
738
775
  }
739
- }, _e = {
776
+ }, Se = {
740
777
  name: "fetch",
741
778
  description: "Make HTTP request to URL",
742
779
  args: {
@@ -753,7 +790,7 @@ const re = () => O.platform() == "win32" ? "cmd" : j`echo $SHELL`?.split("/").po
753
790
  code: { type: "string", description: "CommonJS javascript", required: !0 }
754
791
  },
755
792
  fn: async (h) => {
756
- const r = N(null), e = await J({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
793
+ const r = J(null), e = await I({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
757
794
  return { ...r.output, return: e, stdout: void 0, stderr: void 0 };
758
795
  }
759
796
  }, oe = {
@@ -763,7 +800,7 @@ const re = () => O.platform() == "win32" ? "cmd" : j`echo $SHELL`?.split("/").po
763
800
  code: { type: "string", description: "CommonJS javascript", required: !0 }
764
801
  },
765
802
  fn: async (h) => ({ result: j`python -c "${h.code}"` })
766
- }, Se = {
803
+ }, _e = {
767
804
  name: "read_webpage",
768
805
  description: "Extract clean, structured content from a webpage or convert media/documents to accessible formats",
769
806
  args: {
@@ -788,8 +825,8 @@ const re = () => O.platform() == "win32" ? "cmd" : j`echo $SHELL`?.split("/").po
788
825
  const s = await e.arrayBuffer();
789
826
  if (s.byteLength > 10485760)
790
827
  return { url: h.url, type: "media", mimeType: i, error: "File too large", size: s.byteLength, maxSize: 10485760 };
791
- const a = Buffer.from(s).toString("base64");
792
- return { url: h.url, type: "media", mimeType: i, dataUrl: `data:${i};base64,${a}`, size: s.byteLength };
828
+ const c = Buffer.from(s).toString("base64");
829
+ return { url: h.url, type: "media", mimeType: i, dataUrl: `data:${i};base64,${c}`, size: s.byteLength };
793
830
  }
794
831
  if (i.match(/^(text\/(plain|csv|xml)|application\/(json|xml|csv|x-yaml))/) || h.url.match(/\.(txt|json|xml|csv|yaml|yml|md)$/i)) {
795
832
  const s = await e.text();
@@ -799,12 +836,12 @@ const re = () => O.platform() == "win32" ? "cmd" : j`echo $SHELL`?.split("/").po
799
836
  const s = await e.arrayBuffer();
800
837
  if (s.byteLength > 10485760)
801
838
  return { url: h.url, type: "binary", mimeType: i, error: "File too large", size: s.byteLength, maxSize: 10485760 };
802
- const a = Buffer.from(s).toString("base64");
803
- return { url: h.url, type: "binary", mimeType: i, dataUrl: `data:${i};base64,${a}`, size: s.byteLength };
839
+ const c = Buffer.from(s).toString("base64");
840
+ return { url: h.url, type: "binary", mimeType: i, dataUrl: `data:${i};base64,${c}`, size: s.byteLength };
804
841
  }
805
842
  const o = await e.text(), n = Z.load(o);
806
843
  n('script, style, nav, footer, header, aside, iframe, noscript, svg, [role="navigation"], [role="banner"], [role="complementary"], .ad, .ads, .advertisement, .cookie, .popup, .modal, .sidebar, .related, .comments, .social-share').remove();
807
- const u = {
844
+ const m = {
808
845
  title: n('meta[property="og:title"]').attr("content") || n("title").text() || "",
809
846
  description: n('meta[name="description"]').attr("content") || n('meta[property="og:description"]').attr("content") || "",
810
847
  author: n('meta[name="author"]').attr("content") || "",
@@ -812,30 +849,30 @@ const re = () => O.platform() == "win32" ? "cmd" : j`echo $SHELL`?.split("/").po
812
849
  image: n('meta[property="og:image"]').attr("content") || ""
813
850
  };
814
851
  let l = "";
815
- const c = ["article", "main", '[role="main"]', ".content", ".post-content", ".entry-content", ".article-content", "body"];
816
- for (const s of c) {
817
- const a = n(s).first();
818
- if (a.length && a.text().trim().length > 200) {
819
- l = a.text();
852
+ const a = ["article", "main", '[role="main"]', ".content", ".post-content", ".entry-content", ".article-content", "body"];
853
+ for (const s of a) {
854
+ const c = n(s).first();
855
+ if (c.length && c.text().trim().length > 200) {
856
+ l = c.text();
820
857
  break;
821
858
  }
822
859
  }
823
860
  l || (l = n("body").text()), l = l.replace(/\n\s*\n\s*\n/g, `
824
861
 
825
862
  `).replace(/[ \t]+/g, " ").trim().slice(0, 5e4);
826
- let m = [];
827
- return l.length < 500 && (n("a[href]").each((s, a) => {
828
- const d = n(a).attr("href"), p = n(a).text().trim();
829
- d && p && !d.startsWith("#") && m.push({ text: p, href: d });
830
- }), m = m.slice(0, 50)), {
863
+ let u = [];
864
+ return l.length < 500 && (n("a[href]").each((s, c) => {
865
+ const d = n(c).attr("href"), p = n(c).text().trim();
866
+ d && p && !d.startsWith("#") && u.push({ text: p, href: d });
867
+ }), u = u.slice(0, 50)), {
831
868
  url: h.url,
832
869
  type: "html",
833
- title: u.title.trim(),
834
- description: u.description.trim(),
835
- author: u.author.trim(),
836
- published: u.published,
870
+ title: m.title.trim(),
871
+ description: m.description.trim(),
872
+ author: m.author.trim(),
873
+ published: m.published,
837
874
  content: l,
838
- links: m.length ? m : void 0
875
+ links: u.length ? u : void 0
839
876
  };
840
877
  }
841
878
  }, je = {
@@ -850,7 +887,7 @@ const re = () => O.platform() == "win32" ? "cmd" : j`echo $SHELL`?.split("/").po
850
887
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
851
888
  }).then((o) => o.text());
852
889
  let e, t = /<a .*?href="(.+?)".+?<\/a>/g;
853
- const i = new F();
890
+ const i = new D();
854
891
  for (; (e = t.exec(r)) !== null; ) {
855
892
  let o = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
856
893
  if (o && (o = decodeURIComponent(o)), o && i.add(o), i.size >= (h.length || 5)) break;
@@ -866,12 +903,12 @@ export {
866
903
  we as DateTimeTool,
867
904
  xe as DateTimeUTCTool,
868
905
  ke as ExecTool,
869
- _e as FetchTool,
906
+ Se as FetchTool,
870
907
  se as JSTool,
871
908
  L as LLMProvider,
872
909
  P as OpenAi,
873
910
  oe as PythonTool,
874
- Se as ReadWebpageTool,
911
+ _e as ReadWebpageTool,
875
912
  te as Vision,
876
913
  je as WebSearchTool
877
914
  };