@ztimson/ai-utils 0.7.11 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 U from "node:os";
2
+ import { tmpdir as W } from "node:os";
3
+ import { objectMap as q, JSONAttemptParse as _, findByProp as O, JSONSanitize as S, clean as z, Http as N, consoleInterceptor as C, fn as L, ASet as J } from "@ztimson/utils";
4
+ import { Anthropic as F } from "@anthropic-ai/sdk";
5
+ import { OpenAI as I } from "openai";
6
+ import { fileURLToPath as H } from "url";
7
+ import { join as D, dirname as G } from "path";
8
+ import { spawn as b, execSync as B } from "node:child_process";
9
+ import { mkdtempSync as K } from "node:fs";
10
+ import w from "node:fs/promises";
11
+ import * as $ from "node:path";
12
+ import v, { join as M } from "node:path";
13
+ import { createWorker as V } from "tesseract.js";
14
+ import * as Y from "cheerio";
15
+ import { $ as Z, $Sync as Q } from "@ztimson/node-utils";
16
+ class R {
16
17
  }
17
- class G extends E {
18
+ class X extends R {
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 F({ 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 l of r)
26
+ if (typeof l.content == "string")
27
+ t.push({ timestamp: e, ...l });
27
28
  else {
28
- const n = m.content?.filter((s) => s.type == "text").map((s) => s.text).join(`
29
+ const n = l.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
+ n && t.push({ timestamp: e, role: l.role, content: n }), l.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 c = t.findLast((a) => a.id == s.tool_use_id);
37
+ c && (c[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
+ return Object.assign(new Promise(async (l) => {
58
59
  let n = this.fromStandard([...e.history || [], { role: "user", content: r, timestamp: Date.now() }]);
59
- const s = e.tools || this.ai.options.llm?.tools || [], i = {
60
+ const s = e.tools || this.ai.options.llm?.tools || [], c = {
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((m) => ({
66
+ name: m.name,
67
+ description: m.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: m.args ? q(m.args, (i, u) => ({ ...u, required: void 0 })) : {},
71
+ required: m.args ? Object.entries(m.args).filter((i) => i[1].required).map((i) => i[0]) : []
71
72
  },
72
73
  fn: void 0
73
74
  })),
74
75
  messages: n,
75
76
  stream: !!e.stream
76
77
  };
77
- let l, d = !0;
78
+ let a, o = !0;
78
79
  do {
79
- if (l = await this.client.messages.create(i).catch((o) => {
80
- throw o.message += `
80
+ if (a = await this.client.messages.create(c).catch((i) => {
81
+ throw i.message += `
81
82
 
82
83
  Messages:
83
- ${JSON.stringify(n, null, 2)}`, o;
84
+ ${JSON.stringify(n, null, 2)}`, i;
84
85
  }), e.stream) {
85
- d ? d = !1 : e.stream({ text: `
86
+ o ? o = !1 : e.stream({ text: `
86
87
 
87
- ` }), l.content = [];
88
- for await (const o of l) {
88
+ ` }), a.content = [];
89
+ for await (const i of a) {
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" ? a.content.push({ type: "text", text: "" }) : i.content_block.type === "tool_use" && a.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 u = i.delta.text;
96
+ a.content.at(-1).text += u, e.stream({ text: u });
97
+ } else i.delta.type === "input_json_delta" && (a.content.at(-1).input += i.delta.partial_json);
98
+ else if (i.type === "content_block_stop") {
99
+ const u = a.content.at(-1);
100
+ u.input != null && (u.input = u.input ? _(u.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 m = a.content.filter((i) => i.type === "tool_use");
106
+ if (m.length && !t.signal.aborted) {
107
+ n.push({ role: "assistant", content: a.content });
108
+ const i = await Promise.all(m.map(async (u) => {
109
+ const p = s.find(O("name", u.name));
110
+ if (e.stream && e.stream({ tool: u.name }), !p) return { tool_use_id: u.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) };
113
- } catch (u) {
114
- return { type: "tool_result", tool_use_id: c.id, is_error: !0, content: u?.message || u?.toString() || "Unknown" };
112
+ const d = await p.fn(u.input, e?.stream, this.ai);
113
+ return { type: "tool_result", tool_use_id: u.id, content: S(d) };
114
+ } catch (d) {
115
+ return { type: "tool_result", tool_use_id: u.id, is_error: !0, content: d?.message || d?.toString() || "Unknown" };
115
116
  }
116
117
  }));
117
- n.push({ role: "user", content: o }), i.messages = n;
118
+ n.push({ role: "user", content: i }), c.messages = n;
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 && a.content.some((m) => m.type === "tool_use"));
121
+ n.push({ role: "assistant", content: a.content.filter((m) => m.type == "text").map((m) => m.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
+ `) }), n = this.toStandard(n), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...n), l(n.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 A extends R {
128
+ constructor(r, e, t, l) {
129
+ super(), this.ai = r, this.host = e, this.token = t, this.model = l, this.client = new I(z({
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 l = t.tool_calls.map((n) => ({
139
140
  role: "tool",
140
141
  id: n.id,
141
142
  name: n.function.name,
142
- args: w(n.function.arguments, {}),
143
+ args: _(n.function.arguments, {}),
143
144
  timestamp: t.timestamp
144
145
  }));
145
- r.splice(e, 1, ...m), e += m.length - 1;
146
+ r.splice(e, 1, ...l), e += l.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 l = r.find((n) => t.tool_call_id == n.id);
149
+ l && (t.content.includes('"error":') ? l.error = t.content : l.content = t.content), r.splice(e, 1), e--;
149
150
  }
150
151
  r[e]?.timestamp || (r[e].timestamp = Date.now());
151
152
  }
@@ -166,7 +167,7 @@ class S extends E {
166
167
  content: t.error || t.content
167
168
  });
168
169
  else {
169
- const { timestamp: m, ...n } = t;
170
+ const { timestamp: l, ...n } = t;
170
171
  e.push(n);
171
172
  }
172
173
  return e;
@@ -174,68 +175,68 @@ class S extends E {
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 (l, n) => {
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 c = e.tools || this.ai.options.llm?.tools || [], a = {
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: c.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 ? q(i.args, (u, p) => ({ ...p, required: void 0 })) : {},
195
+ required: i.args ? Object.entries(i.args).filter((u) => u[1].required).map((u) => u[0]) : []
195
196
  }
196
197
  }
197
198
  }))
198
199
  };
199
- let d, a = !0;
200
+ let o, m = !0;
200
201
  do {
201
- if (d = await this.client.chat.completions.create(l).catch((c) => {
202
- throw c.message += `
202
+ if (o = await this.client.chat.completions.create(a).catch((u) => {
203
+ throw u.message += `
203
204
 
204
205
  Messages:
205
- ${JSON.stringify(s, null, 2)}`, c;
206
+ ${JSON.stringify(s, null, 2)}`, u;
206
207
  }), e.stream) {
207
- a ? a = !1 : e.stream({ text: `
208
+ m ? m = !1 : e.stream({ text: `
208
209
 
209
- ` }), d.choices = [{ message: { content: "", tool_calls: [] } }];
210
- for await (const c of d) {
210
+ ` }), o.choices = [{ message: { content: "", tool_calls: [] } }];
211
+ for await (const u of o) {
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
+ u.choices[0].delta.content && (o.choices[0].message.content += u.choices[0].delta.content, e.stream({ text: u.choices[0].delta.content })), u.choices[0].delta.tool_calls && (o.choices[0].message.tool_calls = u.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));
220
- if (e.stream && e.stream({ tool: p.function.name }), !u) return { role: "tool", tool_call_id: p.id, content: '{"error": "Tool not found"}' };
216
+ const i = o.choices[0].message.tool_calls || [];
217
+ if (i.length && !t.signal.aborted) {
218
+ s.push(o.choices[0].message);
219
+ const u = await Promise.all(i.map(async (p) => {
220
+ const d = c?.find(O("name", p.function.name));
221
+ if (e.stream && e.stream({ tool: p.function.name }), !d) 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) };
223
+ const f = _(p.function.arguments, {}), y = await d.fn(f, e.stream, this.ai);
224
+ return { role: "tool", tool_call_id: p.id, content: S(y) };
224
225
  } catch (f) {
225
- return { role: "tool", tool_call_id: p.id, content: b({ error: f?.message || f?.toString() || "Unknown" }) };
226
+ return { role: "tool", tool_call_id: p.id, content: S({ error: f?.message || f?.toString() || "Unknown" }) };
226
227
  }
227
228
  }));
228
- s.push(...c), l.messages = s;
229
+ s.push(...u), a.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 && o.choices?.[0]?.message?.tool_calls?.length);
232
+ s.push({ role: "assistant", content: o.choices[0].message.content || "" }), s = this.toStandard(s), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...s), l(s.at(-1)?.content);
232
233
  }), { abort: () => t.abort() });
233
234
  }
234
235
  }
235
- class B {
236
+ class ee {
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 X(this.ai, t.token, e) : t.proto == "ollama" ? this.models[e] = new A(this.ai, t.host, "not-needed", e) : t.proto == "openai" && (this.models[e] = new A(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 l = () => {
253
254
  };
254
255
  return Object.assign(new Promise(async (n) => {
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 c = async (o, m, i = 50) => {
261
+ const [u, p] = await Promise.all([
262
+ m ? this.embedding(m) : Promise.resolve(null),
263
+ o ? this.embedding(o) : 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((d) => ({ ...d, score: u ? this.cosineSimilarity(d.embeddings[0], u[0].embedding) : 1 })).filter((d) => d.score >= 0.8).map((d) => ({ ...d, score: p ? this.cosineSimilarity(d.embeddings[1], p[0].embedding) : d.score })).filter((d) => d.score >= 0.2).toSorted((d, f) => d.score - f.score).slice(0, i);
266
+ }, a = await c(r);
267
+ a.length && e.history.push({ role: "assistant", content: `Things I remembered:
268
+ ` + a.map((o) => `${o.owner}: ${o.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,40 @@ 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: (o) => {
278
+ if (!o.subject && !o.query) throw new Error("Either a subject or query argument is required");
279
+ return c(o.query, o.subject, o.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 c = e.history?.findIndex((a) => a.role == "assistant" && a.content.startsWith("Things I remembered:"));
286
+ c != null && c >= 0 && e.history?.splice(c, 1);
286
287
  }
287
288
  if (e.compress || e.memory) {
288
- let i = null;
289
+ let c = 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
+ c = await this.ai.language.compressHistory(e.history, e.compress.max, e.compress.min, e), e.history.splice(0, e.history.length, ...c.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 a = e.history?.findLastIndex((o) => o.role == "user") ?? -1;
294
+ c = await this.ai.language.compressHistory(a != -1 ? e.history.slice(a) : 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 a = e.memory.filter((o) => !c.memory.some((m) => this.cosineSimilarity(o.embeddings[1], m.embeddings[1]) > 0.8)).concat(c.memory);
298
+ e.memory.splice(0, e.memory.length, ...a);
298
299
  }
299
300
  }
300
301
  return n(s);
301
- }), { abort: m });
302
+ }), { abort: l });
303
+ }
304
+ async code(r, e) {
305
+ const t = await this.ask(r, { ...e, system: [
306
+ e?.system,
307
+ "Return your response in a code block"
308
+ ].filter((n) => !!n).join(`
309
+ `) }), l = /```(?:.+)?\s*([\s\S]*?)```/.exec(t);
310
+ return l ? l[1].trim() : null;
302
311
  }
303
312
  /**
304
313
  * Compress chat history to reduce context size
@@ -308,24 +317,24 @@ You have passive persistent memory never make any mention of your memory capabil
308
317
  * @param {LLMRequest} options LLM options
309
318
  * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0
310
319
  */
311
- async compressHistory(r, e, t, m) {
320
+ async compressHistory(r, e, t, l) {
312
321
  if (this.estimateTokens(r) < e) return { history: r, memory: [] };
313
322
  let n = 0, s = 0;
314
- for (let u of r.toReversed())
315
- if (s += this.estimateTokens(u.content), s < t) n++;
323
+ for (let d of r.toReversed())
324
+ if (s += this.estimateTokens(d.content), s < t) n++;
316
325
  else break;
317
326
  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(`
327
+ const c = r[0].role == "system" ? r[0] : null, a = n == 0 ? [] : r.slice(-n), o = (n == 0 ? r : r.slice(0, -n)).filter((d) => d.role === "assistant" || d.role === "user"), m = await this.json(o.map((d) => `${d.role}: ${d.content}`).join(`
319
328
 
320
329
  `), "{summary: string, facts: [[subject, fact]]}", {
321
330
  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 };
331
+ model: l?.model,
332
+ temperature: l?.temperature || 0.3
333
+ }), i = /* @__PURE__ */ new Date(), u = await Promise.all((m?.facts || [])?.map(async ([d, f]) => {
334
+ const y = await Promise.all([this.embedding(d), this.embedding(`${d}: ${f}`)]);
335
+ return { owner: d, fact: f, embeddings: [y[0][0].embedding, y[1][0].embedding], timestamp: i };
336
+ })), p = [{ role: "assistant", content: `Conversation Summary: ${m?.summary}`, timestamp: Date.now() }, ...a];
337
+ return c && p.splice(0, 0, c), { history: p, memory: u };
329
338
  }
330
339
  /**
331
340
  * Compare the difference between embeddings (calculates the angle between two vectors)
@@ -335,10 +344,10 @@ You have passive persistent memory never make any mention of your memory capabil
335
344
  */
336
345
  cosineSimilarity(r, e) {
337
346
  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);
347
+ let t = 0, l = 0, n = 0;
348
+ for (let c = 0; c < r.length; c++)
349
+ t += r[c] * e[c], l += r[c] * r[c], n += e[c] * e[c];
350
+ const s = Math.sqrt(l) * Math.sqrt(n);
342
351
  return s === 0 ? 0 : t / s;
343
352
  }
344
353
  /**
@@ -349,25 +358,25 @@ You have passive persistent memory never make any mention of your memory capabil
349
358
  * @returns {string[]} Chunked strings
350
359
  */
351
360
  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++;
361
+ const l = (a, o = "") => a ? Object.entries(a).flatMap(([m, i]) => {
362
+ const u = o ? `${o}${isNaN(+m) ? `.${m}` : `[${m}]`}` : m;
363
+ return typeof i == "object" && !Array.isArray(i) ? l(i, u) : `${u}: ${Array.isArray(i) ? i.join(", ") : i}`;
364
+ }) : [], s = (typeof r == "object" ? l(r) : r.split(`
365
+ `)).flatMap((a) => [...a.split(/\s+/).filter(Boolean), `
366
+ `]), c = [];
367
+ for (let a = 0; a < s.length; ) {
368
+ let o = "", m = a;
369
+ for (; m < s.length; ) {
370
+ const u = o + (o ? " " : "") + s[m];
371
+ if (this.estimateTokens(u.replace(/\s*\n\s*/g, `
372
+ `)) > e && o) break;
373
+ o = u, m++;
365
374
  }
366
- const o = d.replace(/\s*\n\s*/g, `
375
+ const i = o.replace(/\s*\n\s*/g, `
367
376
  `).trim();
368
- o && i.push(o), l = Math.max(a - t, a === l ? l + 1 : a);
377
+ i && c.push(i), a = Math.max(m - t, m === a ? a + 1 : m);
369
378
  }
370
- return i;
379
+ return c;
371
380
  }
372
381
  /**
373
382
  * Create a vector representation of a string
@@ -376,39 +385,39 @@ You have passive persistent memory never make any mention of your memory capabil
376
385
  * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings
377
386
  */
378
387
  embedding(r, e = {}) {
379
- let { maxTokens: t = 500, overlapTokens: m = 50 } = e, n = !1;
388
+ let { maxTokens: t = 500, overlapTokens: l = 50 } = e, n = !1;
380
389
  const s = () => {
381
390
  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"),
391
+ }, c = (o) => new Promise((m, i) => {
392
+ if (n) return i(new Error("Aborted"));
393
+ const u = [
394
+ D(G(H(import.meta.url)), "embedder.js"),
386
395
  this.ai.options.path,
387
396
  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();
390
- let u = "";
391
- p.stdout.on("data", (f) => u += f.toString()), p.on("close", (f) => {
392
- if (n) return o(new Error("Aborted"));
397
+ ], p = b("node", u, { stdio: ["pipe", "pipe", "ignore"] });
398
+ p.stdin.write(o), p.stdin.end();
399
+ let d = "";
400
+ p.stdout.on("data", (f) => d += f.toString()), p.on("close", (f) => {
401
+ if (n) return i(new Error("Aborted"));
393
402
  if (f === 0)
394
403
  try {
395
- const y = JSON.parse(u);
396
- a(y.embedding);
404
+ const y = JSON.parse(d);
405
+ m(y.embedding);
397
406
  } catch {
398
- o(new Error("Failed to parse embedding output"));
407
+ i(new Error("Failed to parse embedding output"));
399
408
  }
400
409
  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) });
410
+ i(new Error(`Embedder process exited with code ${f}`));
411
+ }), p.on("error", i);
412
+ }), a = (async () => {
413
+ const o = this.chunk(r, t, l), m = [];
414
+ for (let i = 0; i < o.length && !n; i++) {
415
+ const u = o[i], p = await c(u);
416
+ m.push({ index: i, embedding: p, text: u, tokens: this.estimateTokens(u) });
408
417
  }
409
- return a;
418
+ return m;
410
419
  })();
411
- return Object.assign(l, { abort: s });
420
+ return Object.assign(a, { abort: s });
412
421
  }
413
422
  /**
414
423
  * Estimate variable as tokens
@@ -427,8 +436,8 @@ You have passive persistent memory never make any mention of your memory capabil
427
436
  */
428
437
  fuzzyMatch(r, ...e) {
429
438
  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 };
439
+ const t = (s, c = 10) => s.toLowerCase().split("").map((a, o) => a.charCodeAt(0) * (o + 1) % c / c).slice(0, c), l = t(r), n = e.map((s) => t(s)).map((s) => this.cosineSimilarity(l, s));
440
+ return { avg: n.reduce((s, c) => s + c, 0) / n.length, max: Math.max(...n), similarities: n };
432
441
  }
433
442
  /**
434
443
  * Ask a question with JSON response
@@ -438,14 +447,15 @@ You have passive persistent memory never make any mention of your memory capabil
438
447
  * @returns {Promise<{} | {} | RegExpExecArray | null>}
439
448
  */
440
449
  async json(r, e, t) {
441
- let m = await this.ask(r, { ...t, system: (t?.system ? `${t.system}
442
- ` : "") + `Only respond using a JSON code block matching this schema:
450
+ const l = await this.code(r, { ...t, system: [
451
+ t?.system,
452
+ `Only respond using JSON matching this schema:
443
453
  \`\`\`json
444
454
  ${e}
445
- \`\`\`` });
446
- if (!m) return {};
447
- const n = /```(?:.+)?\s*([\s\S]*?)```/.exec(m), s = n ? n[1].trim() : m;
448
- return w(s, {});
455
+ \`\`\``
456
+ ].filter((n) => !!n).join(`
457
+ `) });
458
+ return l ? _(l, {}) : null;
449
459
  }
450
460
  /**
451
461
  * Create a summary of some text
@@ -458,7 +468,7 @@ ${e}
458
468
  return this.ask(r, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...t });
459
469
  }
460
470
  }
461
- class K {
471
+ class te {
462
472
  constructor(r) {
463
473
  this.ai = r, r.options.whisper && (this.whisperModel = r.options.asr || "ggml-base.en.bin", this.downloadAsrModel()), this.pyannote = `
464
474
  import sys
@@ -480,109 +490,166 @@ print(json.dumps(segments))
480
490
  downloads = {};
481
491
  pyannote;
482
492
  whisperModel;
493
+ async addPunctuation(r, e, t = 150) {
494
+ const l = (s) => {
495
+ if (s = s.toLowerCase().replace(/[^a-z]/g, ""), s.length <= 3) return 1;
496
+ const c = s.match(/[aeiouy]+/g);
497
+ let a = c ? c.length : 1;
498
+ return s.endsWith("e") && a--, Math.max(1, a);
499
+ };
500
+ let n = "";
501
+ return r.transcription.filter((s, c) => {
502
+ let a = !1;
503
+ const o = r.transcription[c - 1], m = r.transcription[c + 1];
504
+ return !s.text && m ? (m.offsets.from = s.offsets.from, m.timestamps.from = s.offsets.from) : s.text && s.text[0] != " " && o && (o.offsets.to = s.offsets.to, o.timestamps.to = s.timestamps.to, o.text += s.text, a = !0), !!s.text && !a;
505
+ }).forEach((s) => {
506
+ const c = /^[A-Z]/.test(s.text.trim()), a = s.offsets.to - s.offsets.from, m = l(s.text.trim()) * t;
507
+ c && a > m * 2 && s.text[0] == " " && (n += "."), n += s.text;
508
+ }), e ? this.ai.language.ask(n, {
509
+ system: "Remove any misplaced punctuation from the following ASR transcript using the replace tool. Avoid modifying words unless there is an obvious typo",
510
+ temperature: 0.1,
511
+ tools: [{
512
+ name: "replace",
513
+ description: "Use find and replace to fix errors",
514
+ args: {
515
+ find: { type: "string", description: "Text to find", required: !0 },
516
+ replace: { type: "string", description: "Text to replace", required: !0 }
517
+ },
518
+ fn: (s) => n = n.replace(s.find, s.replace)
519
+ }]
520
+ }).then(() => n) : n.trim();
521
+ }
522
+ async diarizeTranscript(r, e, t) {
523
+ const l = /* @__PURE__ */ new Map();
524
+ let n = 0;
525
+ e.forEach((d) => {
526
+ l.has(d.speaker) || l.set(d.speaker, ++n);
527
+ });
528
+ const s = await this.addPunctuation(r, t), c = s.match(/[^.!?]+[.!?]+/g) || [s], a = r.transcription.filter((d) => d.text.trim()), o = c.map((d) => {
529
+ if (d = d.trim(), !d) return null;
530
+ const f = d.toLowerCase().replace(/[^\w\s]/g, "").split(/\s+/), y = /* @__PURE__ */ new Map();
531
+ f.forEach((k) => {
532
+ const x = a.find((g) => k === g.text.trim().toLowerCase().replace(/[^\w]/g, ""));
533
+ if (!x) return;
534
+ const E = x.offsets.from / 1e3, P = e.find((g) => E >= g.start && E <= g.end);
535
+ if (P) {
536
+ const g = l.get(P.speaker);
537
+ y.set(g, (y.get(g) || 0) + 1);
538
+ }
539
+ });
540
+ let j = 1, T = 0;
541
+ return y.forEach((k, x) => {
542
+ k > T && (T = k, j = x);
543
+ }), { speaker: j, text: d };
544
+ }).filter((d) => d !== null), m = [];
545
+ o.forEach((d) => {
546
+ const f = m[m.length - 1];
547
+ f && f.speaker === d.speaker ? f.text += " " + d.text : m.push({ ...d });
548
+ });
549
+ let i = m.map((d) => `[Speaker ${d.speaker}]: ${d.text}`).join(`
550
+ `).trim();
551
+ if (!t) return i;
552
+ let u = this.ai.language.chunk(i, 500, 0);
553
+ u.length > 4 && (u = [...u.slice(0, 3), u.at(-1)]);
554
+ const p = await this.ai.language.json(u.join(`
555
+ `), '{1: "Detected Name", 2: "Second Name"}', {
556
+ 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",
557
+ temperature: 0.1
558
+ });
559
+ return Object.entries(p).forEach(([d, f]) => i = i.replaceAll(`[Speaker ${d}]`, `[${f}]`)), i;
560
+ }
483
561
  runAsr(r, e = {}) {
484
562
  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)
563
+ const l = new Promise((n, s) => {
564
+ this.downloadAsrModel(e.model).then((c) => {
565
+ if (e.diarization) {
566
+ let a = $.join($.dirname(r), "transcript");
567
+ t = b(
568
+ this.ai.options.whisper,
569
+ ["-m", c, "-f", r, "-np", "-ml", "1", "-oj", "-of", a],
570
+ { stdio: ["ignore", "ignore", "pipe"] }
571
+ ), t.on("error", (o) => s(o)), t.on("close", async (o) => {
572
+ if (o === 0) {
573
+ a = await w.readFile(a + ".json", "utf-8"), w.rm(a + ".json").catch(() => {
574
+ });
492
575
  try {
493
- n(JSON.parse(l));
576
+ n(JSON.parse(a));
494
577
  } catch {
495
578
  s(new Error("Failed to parse whisper JSON"));
496
579
  }
497
- else
498
- n(l.trim() || null);
499
- else
500
- s(new Error(`Exit code ${a}`));
501
- });
580
+ } else
581
+ s(new Error(`Exit code ${o}`));
582
+ });
583
+ } else {
584
+ let a = "";
585
+ t = b(this.ai.options.whisper, ["-m", c, "-f", r, "-np", "-nt"]), t.on("error", (o) => s(o)), t.stdout.on("data", (o) => a += o.toString()), t.on("close", async (o) => {
586
+ o === 0 ? n(a.trim() || null) : s(new Error(`Exit code ${o}`));
587
+ });
588
+ }
502
589
  });
503
590
  });
504
- return Object.assign(m, { abort: () => t?.kill("SIGTERM") });
591
+ return Object.assign(l, { abort: () => t?.kill("SIGTERM") });
505
592
  }
506
593
  runDiarization(r) {
507
594
  let e = !1, t = () => {
508
595
  e = !0;
509
596
  };
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));
597
+ const l = (s) => new Promise((c) => {
598
+ const a = b(s, ["-W", "ignore", "-c", "import pyannote.audio"]);
599
+ a.on("close", (o) => c(o === 0)), a.on("error", () => c(!1));
513
600
  }), n = Promise.all([
514
- m("python"),
515
- m("python3")
516
- ]).then((async ([s, i]) => {
601
+ l("python"),
602
+ l("python3")
603
+ ]).then((async ([s, c]) => {
517
604
  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) => {
605
+ if (!s && !c) throw new Error("Pyannote is not installed: pip install pyannote.audio");
606
+ const a = c ? "python3" : "python";
607
+ return new Promise((o, m) => {
521
608
  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) => {
609
+ let i = "";
610
+ const u = b(a, ["-W", "ignore", "-c", this.pyannote, r]);
611
+ u.stdout.on("data", (p) => i += p.toString()), u.stderr.on("data", (p) => console.error(p.toString())), u.on("close", (p) => {
525
612
  if (p === 0)
526
613
  try {
527
- d(JSON.parse(o));
614
+ o(JSON.parse(i));
528
615
  } catch {
529
- a(new Error("Failed to parse diarization output"));
616
+ m(new Error("Failed to parse diarization output"));
530
617
  }
531
618
  else
532
- a(new Error(`Python process exited with code ${p}`));
533
- }), c.on("error", a), t = () => c.kill("SIGTERM");
619
+ m(new Error(`Python process exited with code ${p}`));
620
+ }), u.on("error", m), t = () => u.kill("SIGTERM");
534
621
  });
535
622
  }));
536
623
  return Object.assign(n, { abort: t });
537
624
  }
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);
543
- });
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
- `);
551
- }
552
625
  asr(r, e = {}) {
553
626
  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();
627
+ const t = M(K(M(W(), "audio-")), "converted.wav");
628
+ B(`ffmpeg -i "${r}" -ar 16000 -ac 1 -f wav "${t}"`, { stdio: "ignore" });
629
+ const l = () => w.rm(v.dirname(t), { recursive: !0, force: !0 }).catch(() => {
630
+ });
631
+ if (!e.diarization) return this.runAsr(t, { model: e.model });
632
+ const n = this.runAsr(t, { model: e.model, diarization: !0 }), s = this.runDiarization(t);
633
+ let c = !1, a = () => {
634
+ c = !0, n.abort(), s.abort(), l();
560
635
  };
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") {
564
- 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(`
568
- `), '{1: "Detected Name", 2: "Second Name"}', {
569
- 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
- temperature: 0.1
571
- });
572
- Object.entries(p).forEach(([u, f]) => a = a.replaceAll(`[Speaker ${u}]`, `[${f}]`));
573
- }
574
- return a;
575
- }).finally(() => m());
576
- return Object.assign(d, { abort: l });
636
+ const o = Promise.allSettled([n, s]).then(async ([m, i]) => {
637
+ if (m.status == "rejected") throw new Error(`Whisper.cpp timestamps:
638
+ ` + m.reason);
639
+ if (i.status == "rejected") throw new Error(`Pyannote:
640
+ ` + i.reason);
641
+ return c || !e.diarization ? m.value : this.diarizeTranscript(m.value, i.value, e.diarization == "llm");
642
+ }).finally(() => l());
643
+ return Object.assign(o, { abort: a });
577
644
  }
578
645
  async downloadAsrModel(r = this.whisperModel) {
579
646
  if (!this.ai.options.whisper) throw new Error("Whisper not configured");
580
647
  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]);
648
+ const e = v.join(this.ai.options.path, r);
649
+ return await w.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 w.writeFile(e, t), delete this.downloads[r], e)), this.downloads[r]);
583
650
  }
584
651
  }
585
- class V {
652
+ class re {
586
653
  constructor(r) {
587
654
  this.ai = r;
588
655
  }
@@ -593,17 +660,17 @@ class V {
593
660
  */
594
661
  ocr(r) {
595
662
  let e;
596
- const t = new Promise(async (m) => {
597
- e = await W(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
663
+ const t = new Promise(async (l) => {
664
+ e = await V(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
598
665
  const { data: n } = await e.recognize(r);
599
- await e.terminate(), m(n.text.trim() || null);
666
+ await e.terminate(), l(n.text.trim() || null);
600
667
  });
601
668
  return Object.assign(t, { abort: () => e?.terminate() });
602
669
  }
603
670
  }
604
- class de {
671
+ class we {
605
672
  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);
673
+ this.options = r, r.path || (r.path = U.tmpdir()), process.env.TRANSFORMERS_CACHE = r.path, this.audio = new te(this), this.language = new ee(this), this.vision = new re(this);
607
674
  }
608
675
  /** Audio processing AI */
609
676
  audio;
@@ -612,17 +679,17 @@ class de {
612
679
  /** Vision processing AI */
613
680
  vision;
614
681
  }
615
- const Y = {
682
+ const se = {
616
683
  name: "cli",
617
684
  description: "Use the command line interface, returns any output",
618
685
  args: { command: { type: "string", description: "Command to run", required: !0 } },
619
- fn: (h) => F`${h.command}`
620
- }, ue = {
686
+ fn: (h) => Z`${h.command}`
687
+ }, be = {
621
688
  name: "get_datetime",
622
689
  description: "Get current UTC date / time",
623
690
  args: {},
624
691
  fn: async () => (/* @__PURE__ */ new Date()).toUTCString()
625
- }, pe = {
692
+ }, ke = {
626
693
  name: "exec",
627
694
  description: "Run code/scripts",
628
695
  args: {
@@ -633,17 +700,17 @@ const Y = {
633
700
  try {
634
701
  switch (h.type) {
635
702
  case "bash":
636
- return await Y.fn({ command: h.code }, r, e);
703
+ return await se.fn({ command: h.code }, r, e);
637
704
  case "node":
638
- return await Q.fn({ code: h.code }, r, e);
705
+ return await ne.fn({ code: h.code }, r, e);
639
706
  case "python":
640
- return await X.fn({ code: h.code }, r, e);
707
+ return await oe.fn({ code: h.code }, r, e);
641
708
  }
642
709
  } catch (t) {
643
710
  return { error: t?.message || t.toString() };
644
711
  }
645
712
  }
646
- }, he = {
713
+ }, xe = {
647
714
  name: "fetch",
648
715
  description: "Make HTTP request to URL",
649
716
  args: {
@@ -652,25 +719,25 @@ const Y = {
652
719
  headers: { type: "object", description: "HTTP headers to send", default: {} },
653
720
  body: { type: "object", description: "HTTP body to send" }
654
721
  },
655
- fn: (h) => new O({ url: h.url, headers: h.headers }).request({ method: h.method || "GET", body: h.body })
656
- }, Q = {
722
+ fn: (h) => new N({ url: h.url, headers: h.headers }).request({ method: h.method || "GET", body: h.body })
723
+ }, ne = {
657
724
  name: "exec_javascript",
658
725
  description: "Execute commonjs javascript",
659
726
  args: {
660
727
  code: { type: "string", description: "CommonJS javascript", required: !0 }
661
728
  },
662
729
  fn: async (h) => {
663
- const r = A(null), e = await q({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
730
+ const r = C(null), e = await L({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
664
731
  return { ...r.output, return: e, stdout: void 0, stderr: void 0 };
665
732
  }
666
- }, X = {
733
+ }, oe = {
667
734
  name: "exec_javascript",
668
735
  description: "Execute commonjs javascript",
669
736
  args: {
670
737
  code: { type: "string", description: "CommonJS javascript", required: !0 }
671
738
  },
672
- fn: async (h) => ({ result: H`python -c "${h.code}"` })
673
- }, fe = {
739
+ fn: async (h) => ({ result: Q`python -c "${h.code}"` })
740
+ }, _e = {
674
741
  name: "read_webpage",
675
742
  description: "Extract clean, structured content from a webpage. Use after web_search to read specific URLs",
676
743
  args: {
@@ -680,24 +747,24 @@ const Y = {
680
747
  fn: async (h) => {
681
748
  const r = await fetch(h.url, { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } }).then((s) => s.text()).catch((s) => {
682
749
  throw new Error(`Failed to fetch: ${s.message}`);
683
- }), e = I.load(r);
750
+ }), e = Y.load(r);
684
751
  e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();
685
752
  const t = {
686
753
  title: e('meta[property="og:title"]').attr("content") || e("title").text() || "",
687
754
  description: e('meta[name="description"]').attr("content") || e('meta[property="og:description"]').attr("content") || ""
688
755
  };
689
- let m = "";
756
+ let l = "";
690
757
  const n = ["article", "main", '[role="main"]', ".content", ".post", ".entry", "body"];
691
758
  for (const s of n) {
692
- const i = e(s).first();
693
- if (i.length && i.text().trim().length > 200) {
694
- m = i.text();
759
+ const c = e(s).first();
760
+ if (c.length && c.text().trim().length > 200) {
761
+ l = c.text();
695
762
  break;
696
763
  }
697
764
  }
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 };
765
+ return l || (l = e("body").text()), l = l.replace(/\s+/g, " ").trim().slice(0, 8e3), { url: h.url, title: t.title.trim(), description: t.description.trim(), content: l, focus: h.focus };
699
766
  }
700
- }, ye = {
767
+ }, Se = {
701
768
  name: "web_search",
702
769
  description: "Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool",
703
770
  args: {
@@ -709,28 +776,28 @@ const Y = {
709
776
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
710
777
  }).then((n) => n.text());
711
778
  let e, t = /<a .*?href="(.+?)".+?<\/a>/g;
712
- const m = new v();
779
+ const l = new J();
713
780
  for (; (e = t.exec(r)) !== null; ) {
714
781
  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;
782
+ if (n && (n = decodeURIComponent(n)), n && l.add(n), l.size >= (h.length || 5)) break;
716
783
  }
717
- return m;
784
+ return l;
718
785
  }
719
786
  };
720
787
  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
788
+ we as Ai,
789
+ X as Anthropic,
790
+ te as Audio,
791
+ se as CliTool,
792
+ be as DateTimeTool,
793
+ ke as ExecTool,
794
+ xe as FetchTool,
795
+ ne as JSTool,
796
+ R as LLMProvider,
797
+ A as OpenAi,
798
+ oe as PythonTool,
799
+ _e as ReadWebpageTool,
800
+ re as Vision,
801
+ Se as WebSearchTool
735
802
  };
736
803
  //# sourceMappingURL=index.mjs.map