@ztimson/ai-utils 0.7.11 → 0.8.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,39 +1,40 @@
1
- import * as $ from "node:os";
2
- import { tmpdir as P } from "node:os";
3
- import { objectMap as j, JSONAttemptParse as w, findByProp as T, JSONSanitize as b, clean as M, Http as O, consoleInterceptor as A, fn as q, ASet as v } from "@ztimson/utils";
4
- import { Anthropic as R } from "@anthropic-ai/sdk";
5
- import { OpenAI as U } from "openai";
6
- import { fileURLToPath as z } from "url";
7
- import { join as N, dirname as L } from "path";
8
- import { spawn as g, execSync as C } from "node:child_process";
9
- import { mkdtempSync as J } from "node:fs";
10
- import k, { rm as D } from "node:fs/promises";
11
- import _, { join as x } from "node:path";
12
- import { createWorker as W } from "tesseract.js";
13
- import * as I from "cheerio";
14
- import { $ as F, $Sync as H } from "@ztimson/node-utils";
15
- class E {
1
+ import * as O from "node:os";
2
+ import { tmpdir as q } from "node:os";
3
+ import { objectMap as $, JSONAttemptParse as _, findByProp as P, JSONSanitize as x, clean as R, Http as U, consoleInterceptor as z, fn as N, ASet as L } from "@ztimson/utils";
4
+ import { Anthropic as C } from "@anthropic-ai/sdk";
5
+ import { OpenAI as W } from "openai";
6
+ import { fileURLToPath as I } from "url";
7
+ import { join as J, dirname as D } from "path";
8
+ import { spawn as k, execSync as F } from "node:child_process";
9
+ import { mkdtempSync as H } from "node:fs";
10
+ import b from "node:fs/promises";
11
+ import * as j from "node:path";
12
+ import E, { join as T } from "node:path";
13
+ import { createWorker as G } from "tesseract.js";
14
+ import * as B from "cheerio";
15
+ import { $ as K, $Sync as V } from "@ztimson/node-utils";
16
+ class v {
16
17
  }
17
- class G extends E {
18
+ class Y extends v {
18
19
  constructor(r, e, t) {
19
- super(), this.ai = r, this.apiToken = e, this.model = t, this.client = new R({ apiKey: e });
20
+ super(), this.ai = r, this.apiToken = e, this.model = t, this.client = new C({ apiKey: e });
20
21
  }
21
22
  client;
22
23
  toStandard(r) {
23
24
  const e = Date.now(), t = [];
24
- for (let m of r)
25
- if (typeof m.content == "string")
26
- t.push({ timestamp: e, ...m });
25
+ for (let c of r)
26
+ if (typeof c.content == "string")
27
+ t.push({ timestamp: e, ...c });
27
28
  else {
28
- const n = m.content?.filter((s) => s.type == "text").map((s) => s.text).join(`
29
+ const o = c.content?.filter((s) => s.type == "text").map((s) => s.text).join(`
29
30
 
30
31
  `);
31
- n && t.push({ timestamp: e, role: m.role, content: n }), m.content.forEach((s) => {
32
+ o && t.push({ timestamp: e, role: c.role, content: o }), c.content.forEach((s) => {
32
33
  if (s.type == "tool_use")
33
34
  t.push({ timestamp: e, role: "tool", id: s.id, name: s.name, args: s.input, content: void 0 });
34
35
  else if (s.type == "tool_result") {
35
- const i = t.findLast((l) => l.id == s.tool_use_id);
36
- i && (i[s.is_error ? "error" : "content"] = s.content);
36
+ const l = t.findLast((n) => n.id == s.tool_use_id);
37
+ l && (l[s.is_error ? "error" : "content"] = s.content);
37
38
  }
38
39
  });
39
40
  }
@@ -54,78 +55,78 @@ class G extends E {
54
55
  }
55
56
  ask(r, e = {}) {
56
57
  const t = new AbortController();
57
- return Object.assign(new Promise(async (m) => {
58
- let n = this.fromStandard([...e.history || [], { role: "user", content: r, timestamp: Date.now() }]);
59
- const s = e.tools || this.ai.options.llm?.tools || [], i = {
58
+ return Object.assign(new Promise(async (c) => {
59
+ let o = this.fromStandard([...e.history || [], { role: "user", content: r, timestamp: Date.now() }]);
60
+ const s = e.tools || this.ai.options.llm?.tools || [], l = {
60
61
  model: e.model || this.model,
61
62
  max_tokens: e.max_tokens || this.ai.options.llm?.max_tokens || 4096,
62
63
  system: e.system || this.ai.options.llm?.system || "",
63
64
  temperature: e.temperature || this.ai.options.llm?.temperature || 0.7,
64
- tools: s.map((a) => ({
65
- name: a.name,
66
- description: a.description,
65
+ tools: s.map((d) => ({
66
+ name: d.name,
67
+ description: d.description,
67
68
  input_schema: {
68
69
  type: "object",
69
- properties: a.args ? j(a.args, (o, c) => ({ ...c, required: void 0 })) : {},
70
- required: a.args ? Object.entries(a.args).filter((o) => o[1].required).map((o) => o[0]) : []
70
+ properties: d.args ? $(d.args, (i, m) => ({ ...m, required: void 0 })) : {},
71
+ required: d.args ? Object.entries(d.args).filter((i) => i[1].required).map((i) => i[0]) : []
71
72
  },
72
73
  fn: void 0
73
74
  })),
74
- messages: n,
75
+ messages: o,
75
76
  stream: !!e.stream
76
77
  };
77
- let l, d = !0;
78
+ let n, a = !0;
78
79
  do {
79
- if (l = await this.client.messages.create(i).catch((o) => {
80
- throw o.message += `
80
+ if (n = await this.client.messages.create(l).catch((i) => {
81
+ throw i.message += `
81
82
 
82
83
  Messages:
83
- ${JSON.stringify(n, null, 2)}`, o;
84
+ ${JSON.stringify(o, null, 2)}`, i;
84
85
  }), e.stream) {
85
- d ? d = !1 : e.stream({ text: `
86
+ a ? a = !1 : e.stream({ text: `
86
87
 
87
- ` }), l.content = [];
88
- for await (const o of l) {
88
+ ` }), n.content = [];
89
+ for await (const i of n) {
89
90
  if (t.signal.aborted) break;
90
- if (o.type === "content_block_start")
91
- o.content_block.type === "text" ? l.content.push({ type: "text", text: "" }) : o.content_block.type === "tool_use" && l.content.push({ type: "tool_use", id: o.content_block.id, name: o.content_block.name, input: "" });
92
- else if (o.type === "content_block_delta")
93
- if (o.delta.type === "text_delta") {
94
- const c = o.delta.text;
95
- l.content.at(-1).text += c, e.stream({ text: c });
96
- } else o.delta.type === "input_json_delta" && (l.content.at(-1).input += o.delta.partial_json);
97
- else if (o.type === "content_block_stop") {
98
- const c = l.content.at(-1);
99
- c.input != null && (c.input = c.input ? w(c.input, {}) : {});
100
- } else if (o.type === "message_stop")
91
+ if (i.type === "content_block_start")
92
+ i.content_block.type === "text" ? n.content.push({ type: "text", text: "" }) : i.content_block.type === "tool_use" && n.content.push({ type: "tool_use", id: i.content_block.id, name: i.content_block.name, input: "" });
93
+ else if (i.type === "content_block_delta")
94
+ if (i.delta.type === "text_delta") {
95
+ const m = i.delta.text;
96
+ n.content.at(-1).text += m, e.stream({ text: m });
97
+ } else i.delta.type === "input_json_delta" && (n.content.at(-1).input += i.delta.partial_json);
98
+ else if (i.type === "content_block_stop") {
99
+ const m = n.content.at(-1);
100
+ m.input != null && (m.input = m.input ? _(m.input, {}) : {});
101
+ } else if (i.type === "message_stop")
101
102
  break;
102
103
  }
103
104
  }
104
- const a = l.content.filter((o) => o.type === "tool_use");
105
- if (a.length && !t.signal.aborted) {
106
- n.push({ role: "assistant", content: l.content });
107
- const o = await Promise.all(a.map(async (c) => {
108
- const p = s.find(T("name", c.name));
109
- if (e.stream && e.stream({ tool: c.name }), !p) return { tool_use_id: c.id, is_error: !0, content: "Tool not found" };
105
+ const d = n.content.filter((i) => i.type === "tool_use");
106
+ if (d.length && !t.signal.aborted) {
107
+ o.push({ role: "assistant", content: n.content });
108
+ const i = await Promise.all(d.map(async (m) => {
109
+ const p = s.find(P("name", m.name));
110
+ if (e.stream && e.stream({ tool: m.name }), !p) return { tool_use_id: m.id, is_error: !0, content: "Tool not found" };
110
111
  try {
111
- const u = await p.fn(c.input, e?.stream, this.ai);
112
- return { type: "tool_result", tool_use_id: c.id, content: b(u) };
112
+ const u = await p.fn(m.input, e?.stream, this.ai);
113
+ return { type: "tool_result", tool_use_id: m.id, content: x(u) };
113
114
  } catch (u) {
114
- return { type: "tool_result", tool_use_id: c.id, is_error: !0, content: u?.message || u?.toString() || "Unknown" };
115
+ return { type: "tool_result", tool_use_id: m.id, is_error: !0, content: u?.message || u?.toString() || "Unknown" };
115
116
  }
116
117
  }));
117
- n.push({ role: "user", content: o }), i.messages = n;
118
+ o.push({ role: "user", content: i }), l.messages = o;
118
119
  }
119
- } while (!t.signal.aborted && l.content.some((a) => a.type === "tool_use"));
120
- n.push({ role: "assistant", content: l.content.filter((a) => a.type == "text").map((a) => a.text).join(`
120
+ } while (!t.signal.aborted && n.content.some((d) => d.type === "tool_use"));
121
+ o.push({ role: "assistant", content: n.content.filter((d) => d.type == "text").map((d) => d.text).join(`
121
122
 
122
- `) }), n = this.toStandard(n), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...n), m(n.at(-1)?.content);
123
+ `) }), o = this.toStandard(o), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...o), c(o.at(-1)?.content);
123
124
  }), { abort: () => t.abort() });
124
125
  }
125
126
  }
126
- class S extends E {
127
- constructor(r, e, t, m) {
128
- super(), this.ai = r, this.host = e, this.token = t, this.model = m, this.client = new U(M({
127
+ class M extends v {
128
+ constructor(r, e, t, c) {
129
+ super(), this.ai = r, this.host = e, this.token = t, this.model = c, this.client = new W(R({
129
130
  baseURL: e,
130
131
  apiKey: t
131
132
  }));
@@ -135,17 +136,17 @@ class S extends E {
135
136
  for (let e = 0; e < r.length; e++) {
136
137
  const t = r[e];
137
138
  if (t.role === "assistant" && t.tool_calls) {
138
- const m = t.tool_calls.map((n) => ({
139
+ const c = t.tool_calls.map((o) => ({
139
140
  role: "tool",
140
- id: n.id,
141
- name: n.function.name,
142
- args: w(n.function.arguments, {}),
141
+ id: o.id,
142
+ name: o.function.name,
143
+ args: _(o.function.arguments, {}),
143
144
  timestamp: t.timestamp
144
145
  }));
145
- r.splice(e, 1, ...m), e += m.length - 1;
146
+ r.splice(e, 1, ...c), e += c.length - 1;
146
147
  } else if (t.role === "tool" && t.content) {
147
- const m = r.find((n) => t.tool_call_id == n.id);
148
- m && (t.content.includes('"error":') ? m.error = t.content : m.content = t.content), r.splice(e, 1), e--;
148
+ const c = r.find((o) => t.tool_call_id == o.id);
149
+ c && (t.content.includes('"error":') ? c.error = t.content : c.content = t.content), r.splice(e, 1), e--;
149
150
  }
150
151
  r[e]?.timestamp || (r[e].timestamp = Date.now());
151
152
  }
@@ -166,76 +167,76 @@ class S extends E {
166
167
  content: t.error || t.content
167
168
  });
168
169
  else {
169
- const { timestamp: m, ...n } = t;
170
- e.push(n);
170
+ const { timestamp: c, ...o } = t;
171
+ e.push(o);
171
172
  }
172
173
  return e;
173
174
  }, []);
174
175
  }
175
176
  ask(r, e = {}) {
176
177
  const t = new AbortController();
177
- return Object.assign(new Promise(async (m, n) => {
178
+ return Object.assign(new Promise(async (c, o) => {
178
179
  e.system && e.history?.[0]?.role != "system" && e.history?.splice(0, 0, { role: "system", content: e.system, timestamp: Date.now() });
179
180
  let s = this.fromStandard([...e.history || [], { role: "user", content: r, timestamp: Date.now() }]);
180
- const i = e.tools || this.ai.options.llm?.tools || [], l = {
181
+ const l = e.tools || this.ai.options.llm?.tools || [], n = {
181
182
  model: e.model || this.model,
182
183
  messages: s,
183
184
  stream: !!e.stream,
184
185
  max_tokens: e.max_tokens || this.ai.options.llm?.max_tokens || 4096,
185
186
  temperature: e.temperature || this.ai.options.llm?.temperature || 0.7,
186
- tools: i.map((o) => ({
187
+ tools: l.map((i) => ({
187
188
  type: "function",
188
189
  function: {
189
- name: o.name,
190
- description: o.description,
190
+ name: i.name,
191
+ description: i.description,
191
192
  parameters: {
192
193
  type: "object",
193
- properties: o.args ? j(o.args, (c, p) => ({ ...p, required: void 0 })) : {},
194
- required: o.args ? Object.entries(o.args).filter((c) => c[1].required).map((c) => c[0]) : []
194
+ properties: i.args ? $(i.args, (m, p) => ({ ...p, required: void 0 })) : {},
195
+ required: i.args ? Object.entries(i.args).filter((m) => m[1].required).map((m) => m[0]) : []
195
196
  }
196
197
  }
197
198
  }))
198
199
  };
199
- let d, a = !0;
200
+ let a, d = !0;
200
201
  do {
201
- if (d = await this.client.chat.completions.create(l).catch((c) => {
202
- throw c.message += `
202
+ if (a = await this.client.chat.completions.create(n).catch((m) => {
203
+ throw m.message += `
203
204
 
204
205
  Messages:
205
- ${JSON.stringify(s, null, 2)}`, c;
206
+ ${JSON.stringify(s, null, 2)}`, m;
206
207
  }), e.stream) {
207
- a ? a = !1 : e.stream({ text: `
208
+ d ? d = !1 : e.stream({ text: `
208
209
 
209
- ` }), d.choices = [{ message: { content: "", tool_calls: [] } }];
210
- for await (const c of d) {
210
+ ` }), a.choices = [{ message: { content: "", tool_calls: [] } }];
211
+ for await (const m of a) {
211
212
  if (t.signal.aborted) break;
212
- c.choices[0].delta.content && (d.choices[0].message.content += c.choices[0].delta.content, e.stream({ text: c.choices[0].delta.content })), c.choices[0].delta.tool_calls && (d.choices[0].message.tool_calls = c.choices[0].delta.tool_calls);
213
+ m.choices[0].delta.content && (a.choices[0].message.content += m.choices[0].delta.content, e.stream({ text: m.choices[0].delta.content })), m.choices[0].delta.tool_calls && (a.choices[0].message.tool_calls = m.choices[0].delta.tool_calls);
213
214
  }
214
215
  }
215
- const o = d.choices[0].message.tool_calls || [];
216
- if (o.length && !t.signal.aborted) {
217
- s.push(d.choices[0].message);
218
- const c = await Promise.all(o.map(async (p) => {
219
- const u = i?.find(T("name", p.function.name));
216
+ const i = a.choices[0].message.tool_calls || [];
217
+ if (i.length && !t.signal.aborted) {
218
+ s.push(a.choices[0].message);
219
+ const m = await Promise.all(i.map(async (p) => {
220
+ const u = l?.find(P("name", p.function.name));
220
221
  if (e.stream && e.stream({ tool: p.function.name }), !u) return { role: "tool", tool_call_id: p.id, content: '{"error": "Tool not found"}' };
221
222
  try {
222
- const f = w(p.function.arguments, {}), y = await u.fn(f, e.stream, this.ai);
223
- return { role: "tool", tool_call_id: p.id, content: b(y) };
224
- } catch (f) {
225
- return { role: "tool", tool_call_id: p.id, content: b({ error: f?.message || f?.toString() || "Unknown" }) };
223
+ const h = _(p.function.arguments, {}), y = await u.fn(h, e.stream, this.ai);
224
+ return { role: "tool", tool_call_id: p.id, content: x(y) };
225
+ } catch (h) {
226
+ return { role: "tool", tool_call_id: p.id, content: x({ error: h?.message || h?.toString() || "Unknown" }) };
226
227
  }
227
228
  }));
228
- s.push(...c), l.messages = s;
229
+ s.push(...m), n.messages = s;
229
230
  }
230
- } while (!t.signal.aborted && d.choices?.[0]?.message?.tool_calls?.length);
231
- s.push({ role: "assistant", content: d.choices[0].message.content || "" }), s = this.toStandard(s), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...s), m(s.at(-1)?.content);
231
+ } while (!t.signal.aborted && a.choices?.[0]?.message?.tool_calls?.length);
232
+ s.push({ role: "assistant", content: a.choices[0].message.content || "" }), s = this.toStandard(s), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...s), c(s.at(-1)?.content);
232
233
  }), { abort: () => t.abort() });
233
234
  }
234
235
  }
235
- class B {
236
+ class Q {
236
237
  constructor(r) {
237
238
  this.ai = r, r.options.llm?.models && Object.entries(r.options.llm.models).forEach(([e, t]) => {
238
- this.defaultModel || (this.defaultModel = e), t.proto == "anthropic" ? this.models[e] = new G(this.ai, t.token, e) : t.proto == "ollama" ? this.models[e] = new S(this.ai, t.host, "not-needed", e) : t.proto == "openai" && (this.models[e] = new S(this.ai, t.host || null, t.token, e));
239
+ this.defaultModel || (this.defaultModel = e), t.proto == "anthropic" ? this.models[e] = new Y(this.ai, t.token, e) : t.proto == "ollama" ? this.models[e] = new M(this.ai, t.host, "not-needed", e) : t.proto == "openai" && (this.models[e] = new M(this.ai, t.host || null, t.token, e));
239
240
  });
240
241
  }
241
242
  defaultModel;
@@ -249,22 +250,22 @@ class B {
249
250
  ask(r, e = {}) {
250
251
  const t = e.model || this.defaultModel;
251
252
  if (!this.models[t]) throw new Error(`Model does not exist: ${t}`);
252
- let m = () => {
253
+ let c = () => {
253
254
  };
254
- return Object.assign(new Promise(async (n) => {
255
+ return Object.assign(new Promise(async (o) => {
255
256
  if (e.history || (e.history = []), e.memory) {
256
257
  e.system = (e.system || "") + `
257
258
  You have passive persistent memory never make any mention of your memory capabilities and what you can/cannot remember
258
259
  `;
259
- const i = async (d, a, o = 50) => {
260
- const [c, p] = await Promise.all([
261
- a ? this.embedding(a) : Promise.resolve(null),
262
- d ? this.embedding(d) : Promise.resolve(null)
260
+ const l = async (a, d, i = 50) => {
261
+ const [m, p] = await Promise.all([
262
+ d ? this.embedding(d) : Promise.resolve(null),
263
+ a ? this.embedding(a) : Promise.resolve(null)
263
264
  ]);
264
- return (e.memory || []).map((u) => ({ ...u, score: c ? this.cosineSimilarity(u.embeddings[0], c[0].embedding) : 1 })).filter((u) => u.score >= 0.8).map((u) => ({ ...u, score: p ? this.cosineSimilarity(u.embeddings[1], p[0].embedding) : u.score })).filter((u) => u.score >= 0.2).toSorted((u, f) => u.score - f.score).slice(0, o);
265
- }, l = await i(r);
266
- l.length && e.history.push({ role: "assistant", content: `Things I remembered:
267
- ` + l.map((d) => `${d.owner}: ${d.fact}`).join(`
265
+ return (e.memory || []).map((u) => ({ ...u, score: m ? this.cosineSimilarity(u.embeddings[0], m[0].embedding) : 1 })).filter((u) => u.score >= 0.8).map((u) => ({ ...u, score: p ? this.cosineSimilarity(u.embeddings[1], p[0].embedding) : u.score })).filter((u) => u.score >= 0.2).toSorted((u, h) => u.score - h.score).slice(0, i);
266
+ }, n = await l(r);
267
+ n.length && e.history.push({ role: "assistant", content: `Things I remembered:
268
+ ` + n.map((a) => `${a.owner}: ${a.fact}`).join(`
268
269
  `) }), e.tools = [...e.tools || [], {
269
270
  name: "read_memory",
270
271
  description: "Check your long-term memory for more information",
@@ -273,32 +274,32 @@ You have passive persistent memory never make any mention of your memory capabil
273
274
  query: { type: "string", description: "Search memory based on a query, can be used with or without subject argument" },
274
275
  limit: { type: "number", description: "Result limit, default 5" }
275
276
  },
276
- fn: (d) => {
277
- if (!d.subject && !d.query) throw new Error("Either a subject or query argument is required");
278
- return i(d.query, d.subject, d.limit || 5);
277
+ fn: (a) => {
278
+ if (!a.subject && !a.query) throw new Error("Either a subject or query argument is required");
279
+ return l(a.query, a.subject, a.limit || 5);
279
280
  }
280
281
  }];
281
282
  }
282
283
  const s = await this.models[t].ask(r, e);
283
284
  if (e.memory) {
284
- const i = e.history?.findIndex((l) => l.role == "assistant" && l.content.startsWith("Things I remembered:"));
285
- i != null && i >= 0 && e.history?.splice(i, 1);
285
+ const l = e.history?.findIndex((n) => n.role == "assistant" && n.content.startsWith("Things I remembered:"));
286
+ l != null && l >= 0 && e.history?.splice(l, 1);
286
287
  }
287
288
  if (e.compress || e.memory) {
288
- let i = null;
289
+ let l = null;
289
290
  if (e.compress)
290
- i = await this.ai.language.compressHistory(e.history, e.compress.max, e.compress.min, e), e.history.splice(0, e.history.length, ...i.history);
291
+ l = await this.ai.language.compressHistory(e.history, e.compress.max, e.compress.min, e), e.history.splice(0, e.history.length, ...l.history);
291
292
  else {
292
- const l = e.history?.findLastIndex((d) => d.role == "user") ?? -1;
293
- i = await this.ai.language.compressHistory(l != -1 ? e.history.slice(l) : e.history, 0, 0, e);
293
+ const n = e.history?.findLastIndex((a) => a.role == "user") ?? -1;
294
+ l = await this.ai.language.compressHistory(n != -1 ? e.history.slice(n) : e.history, 0, 0, e);
294
295
  }
295
296
  if (e.memory) {
296
- const l = e.memory.filter((d) => !i.memory.some((a) => this.cosineSimilarity(d.embeddings[1], a.embeddings[1]) > 0.8)).concat(i.memory);
297
- e.memory.splice(0, e.memory.length, ...l);
297
+ const n = e.memory.filter((a) => !l.memory.some((d) => this.cosineSimilarity(a.embeddings[1], d.embeddings[1]) > 0.8)).concat(l.memory);
298
+ e.memory.splice(0, e.memory.length, ...n);
298
299
  }
299
300
  }
300
- return n(s);
301
- }), { abort: m });
301
+ return o(s);
302
+ }), { abort: c });
302
303
  }
303
304
  /**
304
305
  * Compress chat history to reduce context size
@@ -308,24 +309,24 @@ You have passive persistent memory never make any mention of your memory capabil
308
309
  * @param {LLMRequest} options LLM options
309
310
  * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0
310
311
  */
311
- async compressHistory(r, e, t, m) {
312
+ async compressHistory(r, e, t, c) {
312
313
  if (this.estimateTokens(r) < e) return { history: r, memory: [] };
313
- let n = 0, s = 0;
314
+ let o = 0, s = 0;
314
315
  for (let u of r.toReversed())
315
- if (s += this.estimateTokens(u.content), s < t) n++;
316
+ if (s += this.estimateTokens(u.content), s < t) o++;
316
317
  else break;
317
- if (r.length <= n) return { history: r, memory: [] };
318
- const i = r[0].role == "system" ? r[0] : null, l = n == 0 ? [] : r.slice(-n), d = (n == 0 ? r : r.slice(0, -n)).filter((u) => u.role === "assistant" || u.role === "user"), a = await this.json(d.map((u) => `${u.role}: ${u.content}`).join(`
318
+ if (r.length <= o) return { history: r, memory: [] };
319
+ const l = r[0].role == "system" ? r[0] : null, n = o == 0 ? [] : r.slice(-o), a = (o == 0 ? r : r.slice(0, -o)).filter((u) => u.role === "assistant" || u.role === "user"), d = await this.json(a.map((u) => `${u.role}: ${u.content}`).join(`
319
320
 
320
321
  `), "{summary: string, facts: [[subject, fact]]}", {
321
322
  system: "Create the smallest summary possible, no more than 500 tokens. Create a list of NEW facts (split by subject [pro]noun and fact) about what you learned from this conversation that you didn't already know or get from a tool call or system prompt. Focus only on new information about people, topics, or facts. Avoid generating facts about the AI.",
322
- model: m?.model,
323
- temperature: m?.temperature || 0.3
324
- }), o = /* @__PURE__ */ new Date(), c = await Promise.all((a?.facts || [])?.map(async ([u, f]) => {
325
- const y = await Promise.all([this.embedding(u), this.embedding(`${u}: ${f}`)]);
326
- return { owner: u, fact: f, embeddings: [y[0][0].embedding, y[1][0].embedding], timestamp: o };
327
- })), p = [{ role: "assistant", content: `Conversation Summary: ${a?.summary}`, timestamp: Date.now() }, ...l];
328
- return i && p.splice(0, 0, i), { history: p, memory: c };
323
+ model: c?.model,
324
+ temperature: c?.temperature || 0.3
325
+ }), i = /* @__PURE__ */ new Date(), m = await Promise.all((d?.facts || [])?.map(async ([u, h]) => {
326
+ const y = await Promise.all([this.embedding(u), this.embedding(`${u}: ${h}`)]);
327
+ return { owner: u, fact: h, embeddings: [y[0][0].embedding, y[1][0].embedding], timestamp: i };
328
+ })), p = [{ role: "assistant", content: `Conversation Summary: ${d?.summary}`, timestamp: Date.now() }, ...n];
329
+ return l && p.splice(0, 0, l), { history: p, memory: m };
329
330
  }
330
331
  /**
331
332
  * Compare the difference between embeddings (calculates the angle between two vectors)
@@ -335,10 +336,10 @@ You have passive persistent memory never make any mention of your memory capabil
335
336
  */
336
337
  cosineSimilarity(r, e) {
337
338
  if (r.length !== e.length) throw new Error("Vectors must be same length");
338
- let t = 0, m = 0, n = 0;
339
- for (let i = 0; i < r.length; i++)
340
- t += r[i] * e[i], m += r[i] * r[i], n += e[i] * e[i];
341
- const s = Math.sqrt(m) * Math.sqrt(n);
339
+ let t = 0, c = 0, o = 0;
340
+ for (let l = 0; l < r.length; l++)
341
+ t += r[l] * e[l], c += r[l] * r[l], o += e[l] * e[l];
342
+ const s = Math.sqrt(c) * Math.sqrt(o);
342
343
  return s === 0 ? 0 : t / s;
343
344
  }
344
345
  /**
@@ -349,25 +350,25 @@ You have passive persistent memory never make any mention of your memory capabil
349
350
  * @returns {string[]} Chunked strings
350
351
  */
351
352
  chunk(r, e = 500, t = 50) {
352
- const m = (l, d = "") => l ? Object.entries(l).flatMap(([a, o]) => {
353
- const c = d ? `${d}${isNaN(+a) ? `.${a}` : `[${a}]`}` : a;
354
- return typeof o == "object" && !Array.isArray(o) ? m(o, c) : `${c}: ${Array.isArray(o) ? o.join(", ") : o}`;
355
- }) : [], s = (typeof r == "object" ? m(r) : r.split(`
356
- `)).flatMap((l) => [...l.split(/\s+/).filter(Boolean), `
357
- `]), i = [];
358
- for (let l = 0; l < s.length; ) {
359
- let d = "", a = l;
360
- for (; a < s.length; ) {
361
- const c = d + (d ? " " : "") + s[a];
362
- if (this.estimateTokens(c.replace(/\s*\n\s*/g, `
363
- `)) > e && d) break;
364
- d = c, a++;
353
+ const c = (n, a = "") => n ? Object.entries(n).flatMap(([d, i]) => {
354
+ const m = a ? `${a}${isNaN(+d) ? `.${d}` : `[${d}]`}` : d;
355
+ return typeof i == "object" && !Array.isArray(i) ? c(i, m) : `${m}: ${Array.isArray(i) ? i.join(", ") : i}`;
356
+ }) : [], s = (typeof r == "object" ? c(r) : r.split(`
357
+ `)).flatMap((n) => [...n.split(/\s+/).filter(Boolean), `
358
+ `]), l = [];
359
+ for (let n = 0; n < s.length; ) {
360
+ let a = "", d = n;
361
+ for (; d < s.length; ) {
362
+ const m = a + (a ? " " : "") + s[d];
363
+ if (this.estimateTokens(m.replace(/\s*\n\s*/g, `
364
+ `)) > e && a) break;
365
+ a = m, d++;
365
366
  }
366
- const o = d.replace(/\s*\n\s*/g, `
367
+ const i = a.replace(/\s*\n\s*/g, `
367
368
  `).trim();
368
- o && i.push(o), l = Math.max(a - t, a === l ? l + 1 : a);
369
+ i && l.push(i), n = Math.max(d - t, d === n ? n + 1 : d);
369
370
  }
370
- return i;
371
+ return l;
371
372
  }
372
373
  /**
373
374
  * Create a vector representation of a string
@@ -376,39 +377,39 @@ You have passive persistent memory never make any mention of your memory capabil
376
377
  * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings
377
378
  */
378
379
  embedding(r, e = {}) {
379
- let { maxTokens: t = 500, overlapTokens: m = 50 } = e, n = !1;
380
+ let { maxTokens: t = 500, overlapTokens: c = 50 } = e, o = !1;
380
381
  const s = () => {
381
- n = !0;
382
- }, i = (d) => new Promise((a, o) => {
383
- if (n) return o(new Error("Aborted"));
384
- const c = [
385
- N(L(z(import.meta.url)), "embedder.js"),
382
+ o = !0;
383
+ }, l = (a) => new Promise((d, i) => {
384
+ if (o) return i(new Error("Aborted"));
385
+ const m = [
386
+ J(D(I(import.meta.url)), "embedder.js"),
386
387
  this.ai.options.path,
387
388
  this.ai.options?.embedder || "bge-small-en-v1.5"
388
- ], p = g("node", c, { stdio: ["pipe", "pipe", "ignore"] });
389
- p.stdin.write(d), p.stdin.end();
389
+ ], p = k("node", m, { stdio: ["pipe", "pipe", "ignore"] });
390
+ p.stdin.write(a), p.stdin.end();
390
391
  let u = "";
391
- p.stdout.on("data", (f) => u += f.toString()), p.on("close", (f) => {
392
- if (n) return o(new Error("Aborted"));
393
- if (f === 0)
392
+ p.stdout.on("data", (h) => u += h.toString()), p.on("close", (h) => {
393
+ if (o) return i(new Error("Aborted"));
394
+ if (h === 0)
394
395
  try {
395
396
  const y = JSON.parse(u);
396
- a(y.embedding);
397
+ d(y.embedding);
397
398
  } catch {
398
- o(new Error("Failed to parse embedding output"));
399
+ i(new Error("Failed to parse embedding output"));
399
400
  }
400
401
  else
401
- o(new Error(`Embedder process exited with code ${f}`));
402
- }), p.on("error", o);
403
- }), l = (async () => {
404
- const d = this.chunk(r, t, m), a = [];
405
- for (let o = 0; o < d.length && !n; o++) {
406
- const c = d[o], p = await i(c);
407
- a.push({ index: o, embedding: p, text: c, tokens: this.estimateTokens(c) });
402
+ i(new Error(`Embedder process exited with code ${h}`));
403
+ }), p.on("error", i);
404
+ }), n = (async () => {
405
+ const a = this.chunk(r, t, c), d = [];
406
+ for (let i = 0; i < a.length && !o; i++) {
407
+ const m = a[i], p = await l(m);
408
+ d.push({ index: i, embedding: p, text: m, tokens: this.estimateTokens(m) });
408
409
  }
409
- return a;
410
+ return d;
410
411
  })();
411
- return Object.assign(l, { abort: s });
412
+ return Object.assign(n, { abort: s });
412
413
  }
413
414
  /**
414
415
  * Estimate variable as tokens
@@ -427,8 +428,8 @@ You have passive persistent memory never make any mention of your memory capabil
427
428
  */
428
429
  fuzzyMatch(r, ...e) {
429
430
  if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
430
- const t = (s, i = 10) => s.toLowerCase().split("").map((l, d) => l.charCodeAt(0) * (d + 1) % i / i).slice(0, i), m = t(r), n = e.map((s) => t(s)).map((s) => this.cosineSimilarity(m, s));
431
- return { avg: n.reduce((s, i) => s + i, 0) / n.length, max: Math.max(...n), similarities: n };
431
+ const t = (s, l = 10) => s.toLowerCase().split("").map((n, a) => n.charCodeAt(0) * (a + 1) % l / l).slice(0, l), c = t(r), o = e.map((s) => t(s)).map((s) => this.cosineSimilarity(c, s));
432
+ return { avg: o.reduce((s, l) => s + l, 0) / o.length, max: Math.max(...o), similarities: o };
432
433
  }
433
434
  /**
434
435
  * Ask a question with JSON response
@@ -438,14 +439,14 @@ You have passive persistent memory never make any mention of your memory capabil
438
439
  * @returns {Promise<{} | {} | RegExpExecArray | null>}
439
440
  */
440
441
  async json(r, e, t) {
441
- let m = await this.ask(r, { ...t, system: (t?.system ? `${t.system}
442
+ let c = await this.ask(r, { ...t, system: (t?.system ? `${t.system}
442
443
  ` : "") + `Only respond using a JSON code block matching this schema:
443
444
  \`\`\`json
444
445
  ${e}
445
446
  \`\`\`` });
446
- if (!m) return {};
447
- const n = /```(?:.+)?\s*([\s\S]*?)```/.exec(m), s = n ? n[1].trim() : m;
448
- return w(s, {});
447
+ if (!c) return {};
448
+ const o = /```(?:.+)?\s*([\s\S]*?)```/.exec(c), s = o ? o[1].trim() : c;
449
+ return _(s, {});
449
450
  }
450
451
  /**
451
452
  * Create a summary of some text
@@ -458,7 +459,7 @@ ${e}
458
459
  return this.ask(r, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...t });
459
460
  }
460
461
  }
461
- class K {
462
+ class X {
462
463
  constructor(r) {
463
464
  this.ai = r, r.options.whisper && (this.whisperModel = r.options.asr || "ggml-base.en.bin", this.downloadAsrModel()), this.pyannote = `
464
465
  import sys
@@ -482,107 +483,145 @@ print(json.dumps(segments))
482
483
  whisperModel;
483
484
  runAsr(r, e = {}) {
484
485
  let t;
485
- const m = new Promise((n, s) => {
486
- this.downloadAsrModel(e.model).then((i) => {
487
- let l = "";
488
- const d = [e.diarization ? "-owts" : "-nt", "-m", i, "-f", r];
489
- t = g(this.ai.options.whisper, d, { stdio: ["ignore", "pipe", "ignore"] }), t.on("error", (a) => s(a)), t.stdout.on("data", (a) => l += a.toString()), t.on("close", (a) => {
490
- if (a === 0)
491
- if (e.diarization)
486
+ const c = new Promise((o, s) => {
487
+ this.downloadAsrModel(e.model).then((l) => {
488
+ if (e.diarization) {
489
+ let n = j.join(j.dirname(r), "transcript");
490
+ t = k(
491
+ this.ai.options.whisper,
492
+ ["-m", l, "-f", r, "-np", "-ml", "1", "-oj", "-of", n],
493
+ { stdio: ["ignore", "ignore", "pipe"] }
494
+ ), t.on("error", (a) => s(a)), t.on("close", async (a) => {
495
+ if (a === 0) {
496
+ n = await b.readFile(n + ".json", "utf-8"), b.rm(n + ".json").catch(() => {
497
+ });
492
498
  try {
493
- n(JSON.parse(l));
499
+ o(JSON.parse(n));
494
500
  } catch {
495
501
  s(new Error("Failed to parse whisper JSON"));
496
502
  }
497
- else
498
- n(l.trim() || null);
499
- else
500
- s(new Error(`Exit code ${a}`));
501
- });
503
+ } else
504
+ s(new Error(`Exit code ${a}`));
505
+ });
506
+ } else {
507
+ let n = "";
508
+ t = k(this.ai.options.whisper, ["-m", l, "-f", r, "-np", "-nt"]), t.on("error", (a) => s(a)), t.stdout.on("data", (a) => n += a.toString()), t.on("close", async (a) => {
509
+ a === 0 ? o(n.trim() || null) : s(new Error(`Exit code ${a}`));
510
+ });
511
+ }
502
512
  });
503
513
  });
504
- return Object.assign(m, { abort: () => t?.kill("SIGTERM") });
514
+ return Object.assign(c, { abort: () => t?.kill("SIGTERM") });
505
515
  }
506
516
  runDiarization(r) {
507
517
  let e = !1, t = () => {
508
518
  e = !0;
509
519
  };
510
- const m = (s) => new Promise((i) => {
511
- const l = g(s, ["-c", "import pyannote.audio"]);
512
- l.on("close", (d) => i(d === 0)), l.on("error", () => i(!1));
513
- }), n = Promise.all([
514
- m("python"),
515
- m("python3")
516
- ]).then((async ([s, i]) => {
520
+ const c = (s) => new Promise((l) => {
521
+ const n = k(s, ["-W", "ignore", "-c", "import pyannote.audio"]);
522
+ n.on("close", (a) => l(a === 0)), n.on("error", () => l(!1));
523
+ }), o = Promise.all([
524
+ c("python"),
525
+ c("python3")
526
+ ]).then((async ([s, l]) => {
517
527
  if (e) return;
518
- if (!s && !i) throw new Error("Pyannote is not installed: pip install pyannote.audio");
519
- const l = i ? "python3" : "python";
520
- return new Promise((d, a) => {
528
+ if (!s && !l) throw new Error("Pyannote is not installed: pip install pyannote.audio");
529
+ const n = l ? "python3" : "python";
530
+ return new Promise((a, d) => {
521
531
  if (e) return;
522
- let o = "";
523
- const c = g(l, ["-c", this.pyannote, r]);
524
- c.stdout.on("data", (p) => o += p.toString()), c.stderr.on("data", (p) => console.error(p.toString())), c.on("close", (p) => {
532
+ let i = "";
533
+ const m = k(n, ["-W", "ignore", "-c", this.pyannote, r]);
534
+ m.stdout.on("data", (p) => i += p.toString()), m.stderr.on("data", (p) => console.error(p.toString())), m.on("close", (p) => {
525
535
  if (p === 0)
526
536
  try {
527
- d(JSON.parse(o));
537
+ a(JSON.parse(i));
528
538
  } catch {
529
- a(new Error("Failed to parse diarization output"));
539
+ d(new Error("Failed to parse diarization output"));
530
540
  }
531
541
  else
532
- a(new Error(`Python process exited with code ${p}`));
533
- }), c.on("error", a), t = () => c.kill("SIGTERM");
542
+ d(new Error(`Python process exited with code ${p}`));
543
+ }), m.on("error", d), t = () => m.kill("SIGTERM");
534
544
  });
535
545
  }));
536
- return Object.assign(n, { abort: t });
546
+ return Object.assign(o, { abort: t });
537
547
  }
538
- combineSpeakerTranscript(r, e) {
539
- const t = /* @__PURE__ */ new Map();
540
- let m = 0;
541
- e.forEach((l) => {
542
- t.has(l.speaker) || t.set(l.speaker, ++m);
548
+ async combineSpeakerTranscript(r, e, t) {
549
+ const c = /* @__PURE__ */ new Map();
550
+ let o = 0;
551
+ t.forEach((n) => {
552
+ c.has(n.speaker) || c.set(n.speaker, ++o);
543
553
  });
544
- const n = [];
545
- let s = -1, i = "";
546
- return r.transcription.forEach((l) => {
547
- const d = l.offsets.from / 1e3, a = e.find((c) => d >= c.start && d <= c.end), o = a ? t.get(a.speaker) : 1;
548
- o !== s ? (i && n.push(`[Speaker ${s}]: ${i.trim()}`), s = o, i = l.text) : i += " " + l.text;
549
- }), i && n.push(`[Speaker ${s}]: ${i.trim()}`), n.join(`
550
- `);
554
+ const s = r.match(/[^.!?]+[.!?]+/g) || [r], l = [];
555
+ return s.forEach((n) => {
556
+ if (n = n.trim(), !n) return;
557
+ const a = n.toLowerCase().replace(/[^\w\s]/g, "").split(/\s+/);
558
+ let d = 1 / 0;
559
+ const i = [];
560
+ if (e.transcription.forEach((h) => {
561
+ const y = h.text.trim().toLowerCase();
562
+ if (a.some((g) => y.includes(g))) {
563
+ const g = h.offsets.from / 1e3, w = h.offsets.to / 1e3;
564
+ i.push({ start: g, end: w }), g < d && (d = g);
565
+ }
566
+ }), d === 1 / 0) return;
567
+ const m = /* @__PURE__ */ new Map();
568
+ i.forEach((h) => {
569
+ t.forEach((y) => {
570
+ const g = Math.max(0, Math.min(h.end, y.end) - Math.max(h.start, y.start)), w = h.end - h.start;
571
+ if (w > 0) {
572
+ const A = g / w, S = c.get(y.speaker);
573
+ m.set(S, (m.get(S) || 0) + A);
574
+ }
575
+ });
576
+ });
577
+ let p = 1, u = 0;
578
+ m.forEach((h, y) => {
579
+ h > u && (u = h, p = y);
580
+ }), l.push(`[Speaker ${p}]: ${n}`);
581
+ }), l.join(`
582
+ `).trim();
551
583
  }
552
584
  asr(r, e = {}) {
553
585
  if (!this.ai.options.whisper) throw new Error("Whisper not configured");
554
- const t = x(J(x(P(), "audio-")), "converted.wav");
555
- C(`ffmpeg -i "${r}" -ar 16000 -ac 1 -f wav "${t}"`, { stdio: "ignore" });
556
- const m = () => D(_.dirname(t), { recursive: !0, force: !0 }).catch(() => {
557
- }), n = this.runAsr(t, { model: e.model, diarization: !!e.diarization }), s = e.diarization ? this.runDiarization(t) : Promise.resolve(null);
558
- let i = !1, l = () => {
559
- i = !0, n.abort(), s?.abort?.(), m();
586
+ const t = T(H(T(q(), "audio-")), "converted.wav");
587
+ F(`ffmpeg -i "${r}" -ar 16000 -ac 1 -f wav "${t}"`, { stdio: "ignore" });
588
+ const c = () => b.rm(E.dirname(t), { recursive: !0, force: !0 }).catch(() => {
589
+ }), o = this.runAsr(t, { model: e.model, diarization: !1 }), s = e.diarization ? this.runAsr(t, { model: e.model, diarization: !0 }) : Promise.resolve(null), l = e.diarization ? this.runDiarization(t) : Promise.resolve(null);
590
+ let n = !1, a = () => {
591
+ n = !0, o.abort(), s?.abort?.(), l?.abort?.(), c();
560
592
  };
561
- const d = Promise.all([n, s]).then(async ([a, o]) => {
562
- if (i || !e.diarization) return a;
563
- if (a = this.combineSpeakerTranscript(a, o), !i && e.diarization === "id") {
593
+ const d = Promise.allSettled([o, s, l]).then(async ([i, m, p]) => {
594
+ if (i.status == "rejected") throw new Error(`Whisper.cpp punctuated:
595
+ ` + i.reason);
596
+ if (m.status == "rejected") throw new Error(`Whisper.cpp timestamps:
597
+ ` + m.reason);
598
+ if (p.status == "rejected") throw new Error(`Pyannote:
599
+ ` + p.reason);
600
+ if (n || !e.diarization) return i.value;
601
+ let u = await this.combineSpeakerTranscript(i.value, m.value, p.value);
602
+ if (!n && e.diarization === "id") {
564
603
  if (!this.ai.language.defaultModel) throw new Error("Configure an LLM for advanced ASR speaker detection");
565
- let c = this.ai.language.chunk(a, 500, 0);
566
- c.length > 4 && (c = [...c.slice(0, 3), c.at(-1)]);
567
- const p = await this.ai.language.json(c.join(`
604
+ let h = this.ai.language.chunk(u, 500, 0);
605
+ h.length > 4 && (h = [...h.slice(0, 3), h.at(-1)]);
606
+ const y = await this.ai.language.json(h.join(`
568
607
  `), '{1: "Detected Name", 2: "Second Name"}', {
569
608
  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",
570
609
  temperature: 0.1
571
610
  });
572
- Object.entries(p).forEach(([u, f]) => a = a.replaceAll(`[Speaker ${u}]`, `[${f}]`));
611
+ Object.entries(y).forEach(([g, w]) => u = u.replaceAll(`[Speaker ${g}]`, `[${w}]`));
573
612
  }
574
- return a;
575
- }).finally(() => m());
576
- return Object.assign(d, { abort: l });
613
+ return u;
614
+ }).finally(() => c());
615
+ return Object.assign(d, { abort: a });
577
616
  }
578
617
  async downloadAsrModel(r = this.whisperModel) {
579
618
  if (!this.ai.options.whisper) throw new Error("Whisper not configured");
580
619
  r.endsWith(".bin") || (r += ".bin");
581
- const e = _.join(this.ai.options.path, r);
582
- return await k.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[r] ? this.downloads[r] : (this.downloads[r] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${r}`).then((t) => t.arrayBuffer()).then((t) => Buffer.from(t)).then(async (t) => (await k.writeFile(e, t), delete this.downloads[r], e)), this.downloads[r]);
620
+ const e = E.join(this.ai.options.path, r);
621
+ return await b.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[r] ? this.downloads[r] : (this.downloads[r] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${r}`).then((t) => t.arrayBuffer()).then((t) => Buffer.from(t)).then(async (t) => (await b.writeFile(e, t), delete this.downloads[r], e)), this.downloads[r]);
583
622
  }
584
623
  }
585
- class V {
624
+ class Z {
586
625
  constructor(r) {
587
626
  this.ai = r;
588
627
  }
@@ -593,17 +632,17 @@ class V {
593
632
  */
594
633
  ocr(r) {
595
634
  let e;
596
- const t = new Promise(async (m) => {
597
- e = await W(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
598
- const { data: n } = await e.recognize(r);
599
- await e.terminate(), m(n.text.trim() || null);
635
+ const t = new Promise(async (c) => {
636
+ e = await G(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
637
+ const { data: o } = await e.recognize(r);
638
+ await e.terminate(), c(o.text.trim() || null);
600
639
  });
601
640
  return Object.assign(t, { abort: () => e?.terminate() });
602
641
  }
603
642
  }
604
- class de {
643
+ class fe {
605
644
  constructor(r) {
606
- this.options = r, r.path || (r.path = $.tmpdir()), process.env.TRANSFORMERS_CACHE = r.path, this.audio = new K(this), this.language = new B(this), this.vision = new V(this);
645
+ this.options = r, r.path || (r.path = O.tmpdir()), process.env.TRANSFORMERS_CACHE = r.path, this.audio = new X(this), this.language = new Q(this), this.vision = new Z(this);
607
646
  }
608
647
  /** Audio processing AI */
609
648
  audio;
@@ -612,38 +651,38 @@ class de {
612
651
  /** Vision processing AI */
613
652
  vision;
614
653
  }
615
- const Y = {
654
+ const ee = {
616
655
  name: "cli",
617
656
  description: "Use the command line interface, returns any output",
618
657
  args: { command: { type: "string", description: "Command to run", required: !0 } },
619
- fn: (h) => F`${h.command}`
620
- }, ue = {
658
+ fn: (f) => K`${f.command}`
659
+ }, ye = {
621
660
  name: "get_datetime",
622
661
  description: "Get current UTC date / time",
623
662
  args: {},
624
663
  fn: async () => (/* @__PURE__ */ new Date()).toUTCString()
625
- }, pe = {
664
+ }, ge = {
626
665
  name: "exec",
627
666
  description: "Run code/scripts",
628
667
  args: {
629
668
  language: { type: "string", description: "Execution language", enum: ["cli", "node", "python"], required: !0 },
630
669
  code: { type: "string", description: "Code to execute", required: !0 }
631
670
  },
632
- fn: async (h, r, e) => {
671
+ fn: async (f, r, e) => {
633
672
  try {
634
- switch (h.type) {
673
+ switch (f.type) {
635
674
  case "bash":
636
- return await Y.fn({ command: h.code }, r, e);
675
+ return await ee.fn({ command: f.code }, r, e);
637
676
  case "node":
638
- return await Q.fn({ code: h.code }, r, e);
677
+ return await te.fn({ code: f.code }, r, e);
639
678
  case "python":
640
- return await X.fn({ code: h.code }, r, e);
679
+ return await re.fn({ code: f.code }, r, e);
641
680
  }
642
681
  } catch (t) {
643
682
  return { error: t?.message || t.toString() };
644
683
  }
645
684
  }
646
- }, he = {
685
+ }, we = {
647
686
  name: "fetch",
648
687
  description: "Make HTTP request to URL",
649
688
  args: {
@@ -652,85 +691,85 @@ const Y = {
652
691
  headers: { type: "object", description: "HTTP headers to send", default: {} },
653
692
  body: { type: "object", description: "HTTP body to send" }
654
693
  },
655
- fn: (h) => new O({ url: h.url, headers: h.headers }).request({ method: h.method || "GET", body: h.body })
656
- }, Q = {
694
+ fn: (f) => new U({ url: f.url, headers: f.headers }).request({ method: f.method || "GET", body: f.body })
695
+ }, te = {
657
696
  name: "exec_javascript",
658
697
  description: "Execute commonjs javascript",
659
698
  args: {
660
699
  code: { type: "string", description: "CommonJS javascript", required: !0 }
661
700
  },
662
- fn: async (h) => {
663
- const r = A(null), e = await q({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
701
+ fn: async (f) => {
702
+ const r = z(null), e = await N({ console: r }, f.code, !0).catch((t) => r.output.error.push(t));
664
703
  return { ...r.output, return: e, stdout: void 0, stderr: void 0 };
665
704
  }
666
- }, X = {
705
+ }, re = {
667
706
  name: "exec_javascript",
668
707
  description: "Execute commonjs javascript",
669
708
  args: {
670
709
  code: { type: "string", description: "CommonJS javascript", required: !0 }
671
710
  },
672
- fn: async (h) => ({ result: H`python -c "${h.code}"` })
673
- }, fe = {
711
+ fn: async (f) => ({ result: V`python -c "${f.code}"` })
712
+ }, be = {
674
713
  name: "read_webpage",
675
714
  description: "Extract clean, structured content from a webpage. Use after web_search to read specific URLs",
676
715
  args: {
677
716
  url: { type: "string", description: "URL to extract content from", required: !0 },
678
717
  focus: { type: "string", description: 'Optional: What aspect to focus on (e.g., "pricing", "features", "contact info")' }
679
718
  },
680
- fn: async (h) => {
681
- const r = await fetch(h.url, { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } }).then((s) => s.text()).catch((s) => {
719
+ fn: async (f) => {
720
+ const r = await fetch(f.url, { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } }).then((s) => s.text()).catch((s) => {
682
721
  throw new Error(`Failed to fetch: ${s.message}`);
683
- }), e = I.load(r);
722
+ }), e = B.load(r);
684
723
  e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();
685
724
  const t = {
686
725
  title: e('meta[property="og:title"]').attr("content") || e("title").text() || "",
687
726
  description: e('meta[name="description"]').attr("content") || e('meta[property="og:description"]').attr("content") || ""
688
727
  };
689
- let m = "";
690
- const n = ["article", "main", '[role="main"]', ".content", ".post", ".entry", "body"];
691
- for (const s of n) {
692
- const i = e(s).first();
693
- if (i.length && i.text().trim().length > 200) {
694
- m = i.text();
728
+ let c = "";
729
+ const o = ["article", "main", '[role="main"]', ".content", ".post", ".entry", "body"];
730
+ for (const s of o) {
731
+ const l = e(s).first();
732
+ if (l.length && l.text().trim().length > 200) {
733
+ c = l.text();
695
734
  break;
696
735
  }
697
736
  }
698
- return m || (m = e("body").text()), m = m.replace(/\s+/g, " ").trim().slice(0, 8e3), { url: h.url, title: t.title.trim(), description: t.description.trim(), content: m, focus: h.focus };
737
+ return c || (c = e("body").text()), c = c.replace(/\s+/g, " ").trim().slice(0, 8e3), { url: f.url, title: t.title.trim(), description: t.description.trim(), content: c, focus: f.focus };
699
738
  }
700
- }, ye = {
739
+ }, ke = {
701
740
  name: "web_search",
702
741
  description: "Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool",
703
742
  args: {
704
743
  query: { type: "string", description: "Search string", required: !0 },
705
744
  length: { type: "string", description: "Number of results to return", default: 5 }
706
745
  },
707
- fn: async (h) => {
708
- const r = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(h.query)}`, {
746
+ fn: async (f) => {
747
+ const r = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(f.query)}`, {
709
748
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
710
- }).then((n) => n.text());
749
+ }).then((o) => o.text());
711
750
  let e, t = /<a .*?href="(.+?)".+?<\/a>/g;
712
- const m = new v();
751
+ const c = new L();
713
752
  for (; (e = t.exec(r)) !== null; ) {
714
- let n = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
715
- if (n && (n = decodeURIComponent(n)), n && m.add(n), m.size >= (h.length || 5)) break;
753
+ let o = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
754
+ if (o && (o = decodeURIComponent(o)), o && c.add(o), c.size >= (f.length || 5)) break;
716
755
  }
717
- return m;
756
+ return c;
718
757
  }
719
758
  };
720
759
  export {
721
- de as Ai,
722
- G as Anthropic,
723
- K as Audio,
724
- Y as CliTool,
725
- ue as DateTimeTool,
726
- pe as ExecTool,
727
- he as FetchTool,
728
- Q as JSTool,
729
- E as LLMProvider,
730
- S as OpenAi,
731
- X as PythonTool,
732
- fe as ReadWebpageTool,
733
- V as Vision,
734
- ye as WebSearchTool
760
+ fe as Ai,
761
+ Y as Anthropic,
762
+ X as Audio,
763
+ ee as CliTool,
764
+ ye as DateTimeTool,
765
+ ge as ExecTool,
766
+ we as FetchTool,
767
+ te as JSTool,
768
+ v as LLMProvider,
769
+ M as OpenAi,
770
+ re as PythonTool,
771
+ be as ReadWebpageTool,
772
+ Z as Vision,
773
+ ke as WebSearchTool
735
774
  };
736
775
  //# sourceMappingURL=index.mjs.map