@ztimson/ai-utils 0.8.1 → 0.8.3

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