@ztimson/ai-utils 0.7.1 → 0.7.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,5 +1,5 @@
1
1
  import * as $ from "node:os";
2
- import { objectMap as k, JSONAttemptParse as g, findByProp as _, JSONSanitize as b, clean as M, Http as E, consoleInterceptor as P, fn as A, ASet as O } from "@ztimson/utils";
2
+ import { objectMap as k, JSONAttemptParse as y, findByProp as _, JSONSanitize as b, clean as M, Http as E, consoleInterceptor as P, fn as A, ASet as O } from "@ztimson/utils";
3
3
  import { Anthropic as v } from "@anthropic-ai/sdk";
4
4
  import { OpenAI as U } from "openai";
5
5
  import { Worker as x } from "worker_threads";
@@ -19,19 +19,19 @@ class W extends q {
19
19
  client;
20
20
  toStandard(s) {
21
21
  const e = Date.now(), t = [];
22
- for (let m of s)
23
- if (typeof m.content == "string")
24
- t.push({ timestamp: e, ...m });
22
+ for (let c of s)
23
+ if (typeof c.content == "string")
24
+ t.push({ timestamp: e, ...c });
25
25
  else {
26
- const r = m.content?.filter((n) => n.type == "text").map((n) => n.text).join(`
26
+ const r = c.content?.filter((n) => n.type == "text").map((n) => n.text).join(`
27
27
 
28
28
  `);
29
- r && t.push({ timestamp: e, role: m.role, content: r }), m.content.forEach((n) => {
29
+ r && t.push({ timestamp: e, role: c.role, content: r }), c.content.forEach((n) => {
30
30
  if (n.type == "tool_use")
31
31
  t.push({ timestamp: e, role: "tool", id: n.id, name: n.name, args: n.input, content: void 0 });
32
32
  else if (n.type == "tool_result") {
33
- const a = t.findLast((i) => i.id == n.tool_use_id);
34
- a && (a[n.is_error ? "error" : "content"] = n.content);
33
+ const l = t.findLast((o) => o.id == n.tool_use_id);
34
+ l && (l[n.is_error ? "error" : "content"] = n.content);
35
35
  }
36
36
  });
37
37
  }
@@ -52,78 +52,78 @@ class W extends q {
52
52
  }
53
53
  ask(s, e = {}) {
54
54
  const t = new AbortController();
55
- return Object.assign(new Promise(async (m) => {
55
+ return Object.assign(new Promise(async (c) => {
56
56
  let r = this.fromStandard([...e.history || [], { role: "user", content: s, timestamp: Date.now() }]);
57
- const n = e.tools || this.ai.options.llm?.tools || [], a = {
57
+ const n = e.tools || this.ai.options.llm?.tools || [], l = {
58
58
  model: e.model || this.model,
59
59
  max_tokens: e.max_tokens || this.ai.options.llm?.max_tokens || 4096,
60
60
  system: e.system || this.ai.options.llm?.system || "",
61
61
  temperature: e.temperature || this.ai.options.llm?.temperature || 0.7,
62
- tools: n.map((d) => ({
63
- name: d.name,
64
- description: d.description,
62
+ tools: n.map((m) => ({
63
+ name: m.name,
64
+ description: m.description,
65
65
  input_schema: {
66
66
  type: "object",
67
- properties: d.args ? k(d.args, (c, l) => ({ ...l, required: void 0 })) : {},
68
- required: d.args ? Object.entries(d.args).filter((c) => c[1].required).map((c) => c[0]) : []
67
+ properties: m.args ? k(m.args, (i, d) => ({ ...d, required: void 0 })) : {},
68
+ required: m.args ? Object.entries(m.args).filter((i) => i[1].required).map((i) => i[0]) : []
69
69
  },
70
70
  fn: void 0
71
71
  })),
72
72
  messages: r,
73
73
  stream: !!e.stream
74
74
  };
75
- let i, o = !0;
75
+ let o, a = !0;
76
76
  do {
77
- if (i = await this.client.messages.create(a).catch((c) => {
78
- throw c.message += `
77
+ if (o = await this.client.messages.create(l).catch((i) => {
78
+ throw i.message += `
79
79
 
80
80
  Messages:
81
- ${JSON.stringify(r, null, 2)}`, c;
81
+ ${JSON.stringify(r, null, 2)}`, i;
82
82
  }), e.stream) {
83
- o ? o = !1 : e.stream({ text: `
83
+ a ? a = !1 : e.stream({ text: `
84
84
 
85
- ` }), i.content = [];
86
- for await (const c of i) {
85
+ ` }), o.content = [];
86
+ for await (const i of o) {
87
87
  if (t.signal.aborted) break;
88
- if (c.type === "content_block_start")
89
- c.content_block.type === "text" ? i.content.push({ type: "text", text: "" }) : c.content_block.type === "tool_use" && i.content.push({ type: "tool_use", id: c.content_block.id, name: c.content_block.name, input: "" });
90
- else if (c.type === "content_block_delta")
91
- if (c.delta.type === "text_delta") {
92
- const l = c.delta.text;
93
- i.content.at(-1).text += l, e.stream({ text: l });
94
- } else c.delta.type === "input_json_delta" && (i.content.at(-1).input += c.delta.partial_json);
95
- else if (c.type === "content_block_stop") {
96
- const l = i.content.at(-1);
97
- l.input != null && (l.input = l.input ? g(l.input, {}) : {});
98
- } else if (c.type === "message_stop")
88
+ if (i.type === "content_block_start")
89
+ i.content_block.type === "text" ? o.content.push({ type: "text", text: "" }) : i.content_block.type === "tool_use" && o.content.push({ type: "tool_use", id: i.content_block.id, name: i.content_block.name, input: "" });
90
+ else if (i.type === "content_block_delta")
91
+ if (i.delta.type === "text_delta") {
92
+ const d = i.delta.text;
93
+ o.content.at(-1).text += d, e.stream({ text: d });
94
+ } else i.delta.type === "input_json_delta" && (o.content.at(-1).input += i.delta.partial_json);
95
+ else if (i.type === "content_block_stop") {
96
+ const d = o.content.at(-1);
97
+ d.input != null && (d.input = d.input ? y(d.input, {}) : {});
98
+ } else if (i.type === "message_stop")
99
99
  break;
100
100
  }
101
101
  }
102
- const d = i.content.filter((c) => c.type === "tool_use");
103
- if (d.length && !t.signal.aborted) {
104
- r.push({ role: "assistant", content: i.content });
105
- const c = await Promise.all(d.map(async (l) => {
106
- const p = n.find(_("name", l.name));
107
- if (e.stream && e.stream({ tool: l.name }), !p) return { tool_use_id: l.id, is_error: !0, content: "Tool not found" };
102
+ const m = o.content.filter((i) => i.type === "tool_use");
103
+ if (m.length && !t.signal.aborted) {
104
+ r.push({ role: "assistant", content: o.content });
105
+ const i = await Promise.all(m.map(async (d) => {
106
+ const p = n.find(_("name", d.name));
107
+ if (e.stream && e.stream({ tool: d.name }), !p) return { tool_use_id: d.id, is_error: !0, content: "Tool not found" };
108
108
  try {
109
- const u = await p.fn(l.input, e?.stream, this.ai);
110
- return { type: "tool_result", tool_use_id: l.id, content: b(u) };
109
+ const u = await p.fn(d.input, e?.stream, this.ai);
110
+ return { type: "tool_result", tool_use_id: d.id, content: b(u) };
111
111
  } catch (u) {
112
- return { type: "tool_result", tool_use_id: l.id, is_error: !0, content: u?.message || u?.toString() || "Unknown" };
112
+ return { type: "tool_result", tool_use_id: d.id, is_error: !0, content: u?.message || u?.toString() || "Unknown" };
113
113
  }
114
114
  }));
115
- r.push({ role: "user", content: c }), a.messages = r;
115
+ r.push({ role: "user", content: i }), l.messages = r;
116
116
  }
117
- } while (!t.signal.aborted && i.content.some((d) => d.type === "tool_use"));
118
- r.push({ role: "assistant", content: i.content.filter((d) => d.type == "text").map((d) => d.text).join(`
117
+ } while (!t.signal.aborted && o.content.some((m) => m.type === "tool_use"));
118
+ r.push({ role: "assistant", content: o.content.filter((m) => m.type == "text").map((m) => m.text).join(`
119
119
 
120
- `) }), r = this.toStandard(r), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...r), m(r.at(-1)?.content);
120
+ `) }), r = this.toStandard(r), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...r), c(r.at(-1)?.content);
121
121
  }), { abort: () => t.abort() });
122
122
  }
123
123
  }
124
124
  class w extends q {
125
- constructor(s, e, t, m) {
126
- super(), this.ai = s, this.host = e, this.token = t, this.model = m, this.client = new U(M({
125
+ constructor(s, e, t, c) {
126
+ super(), this.ai = s, this.host = e, this.token = t, this.model = c, this.client = new U(M({
127
127
  baseURL: e,
128
128
  apiKey: t
129
129
  }));
@@ -133,17 +133,17 @@ class w extends q {
133
133
  for (let e = 0; e < s.length; e++) {
134
134
  const t = s[e];
135
135
  if (t.role === "assistant" && t.tool_calls) {
136
- const m = t.tool_calls.map((r) => ({
136
+ const c = t.tool_calls.map((r) => ({
137
137
  role: "tool",
138
138
  id: r.id,
139
139
  name: r.function.name,
140
- args: g(r.function.arguments, {}),
140
+ args: y(r.function.arguments, {}),
141
141
  timestamp: t.timestamp
142
142
  }));
143
- s.splice(e, 1, ...m), e += m.length - 1;
143
+ s.splice(e, 1, ...c), e += c.length - 1;
144
144
  } else if (t.role === "tool" && t.content) {
145
- const m = s.find((r) => t.tool_call_id == r.id);
146
- m && (t.content.includes('"error":') ? m.error = t.content : m.content = t.content), s.splice(e, 1), e--;
145
+ const c = s.find((r) => t.tool_call_id == r.id);
146
+ c && (t.content.includes('"error":') ? c.error = t.content : c.content = t.content), s.splice(e, 1), e--;
147
147
  }
148
148
  s[e]?.timestamp || (s[e].timestamp = Date.now());
149
149
  }
@@ -164,7 +164,7 @@ class w extends q {
164
164
  content: t.error || t.content
165
165
  });
166
166
  else {
167
- const { timestamp: m, ...r } = t;
167
+ const { timestamp: c, ...r } = t;
168
168
  e.push(r);
169
169
  }
170
170
  return e;
@@ -172,61 +172,61 @@ class w extends q {
172
172
  }
173
173
  ask(s, e = {}) {
174
174
  const t = new AbortController();
175
- return Object.assign(new Promise(async (m, r) => {
175
+ return Object.assign(new Promise(async (c, r) => {
176
176
  e.system && e.history?.[0]?.role != "system" && e.history?.splice(0, 0, { role: "system", content: e.system, timestamp: Date.now() });
177
177
  let n = this.fromStandard([...e.history || [], { role: "user", content: s, timestamp: Date.now() }]);
178
- const a = e.tools || this.ai.options.llm?.tools || [], i = {
178
+ const l = e.tools || this.ai.options.llm?.tools || [], o = {
179
179
  model: e.model || this.model,
180
180
  messages: n,
181
181
  stream: !!e.stream,
182
182
  max_tokens: e.max_tokens || this.ai.options.llm?.max_tokens || 4096,
183
183
  temperature: e.temperature || this.ai.options.llm?.temperature || 0.7,
184
- tools: a.map((c) => ({
184
+ tools: l.map((i) => ({
185
185
  type: "function",
186
186
  function: {
187
- name: c.name,
188
- description: c.description,
187
+ name: i.name,
188
+ description: i.description,
189
189
  parameters: {
190
190
  type: "object",
191
- properties: c.args ? k(c.args, (l, p) => ({ ...p, required: void 0 })) : {},
192
- required: c.args ? Object.entries(c.args).filter((l) => l[1].required).map((l) => l[0]) : []
191
+ properties: i.args ? k(i.args, (d, p) => ({ ...p, required: void 0 })) : {},
192
+ required: i.args ? Object.entries(i.args).filter((d) => d[1].required).map((d) => d[0]) : []
193
193
  }
194
194
  }
195
195
  }))
196
196
  };
197
- let o, d = !0;
197
+ let a, m = !0;
198
198
  do {
199
- if (o = await this.client.chat.completions.create(i).catch((l) => {
200
- throw l.message += `
199
+ if (a = await this.client.chat.completions.create(o).catch((d) => {
200
+ throw d.message += `
201
201
 
202
202
  Messages:
203
- ${JSON.stringify(n, null, 2)}`, l;
203
+ ${JSON.stringify(n, null, 2)}`, d;
204
204
  }), e.stream) {
205
- d ? d = !1 : e.stream({ text: `
205
+ m ? m = !1 : e.stream({ text: `
206
206
 
207
- ` }), o.choices = [{ message: { content: "", tool_calls: [] } }];
208
- for await (const l of o) {
207
+ ` }), a.choices = [{ message: { content: "", tool_calls: [] } }];
208
+ for await (const d of a) {
209
209
  if (t.signal.aborted) break;
210
- l.choices[0].delta.content && (o.choices[0].message.content += l.choices[0].delta.content, e.stream({ text: l.choices[0].delta.content })), l.choices[0].delta.tool_calls && (o.choices[0].message.tool_calls = l.choices[0].delta.tool_calls);
210
+ d.choices[0].delta.content && (a.choices[0].message.content += d.choices[0].delta.content, e.stream({ text: d.choices[0].delta.content })), d.choices[0].delta.tool_calls && (a.choices[0].message.tool_calls = d.choices[0].delta.tool_calls);
211
211
  }
212
212
  }
213
- const c = o.choices[0].message.tool_calls || [];
214
- if (c.length && !t.signal.aborted) {
215
- n.push(o.choices[0].message);
216
- const l = await Promise.all(c.map(async (p) => {
217
- const u = a?.find(_("name", p.function.name));
213
+ const i = a.choices[0].message.tool_calls || [];
214
+ if (i.length && !t.signal.aborted) {
215
+ n.push(a.choices[0].message);
216
+ const d = await Promise.all(i.map(async (p) => {
217
+ const u = l?.find(_("name", p.function.name));
218
218
  if (e.stream && e.stream({ tool: p.function.name }), !u) return { role: "tool", tool_call_id: p.id, content: '{"error": "Tool not found"}' };
219
219
  try {
220
- const f = g(p.function.arguments, {}), y = await u.fn(f, e.stream, this.ai);
221
- return { role: "tool", tool_call_id: p.id, content: b(y) };
220
+ const f = y(p.function.arguments, {}), g = await u.fn(f, e.stream, this.ai);
221
+ return { role: "tool", tool_call_id: p.id, content: b(g) };
222
222
  } catch (f) {
223
223
  return { role: "tool", tool_call_id: p.id, content: b({ error: f?.message || f?.toString() || "Unknown" }) };
224
224
  }
225
225
  }));
226
- n.push(...l), i.messages = n;
226
+ n.push(...d), o.messages = n;
227
227
  }
228
- } while (!t.signal.aborted && o.choices?.[0]?.message?.tool_calls?.length);
229
- n.push({ role: "assistant", content: o.choices[0].message.content || "" }), 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);
228
+ } while (!t.signal.aborted && a.choices?.[0]?.message?.tool_calls?.length);
229
+ n.push({ role: "assistant", content: a.choices[0].message.content || "" }), n = this.toStandard(n), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...n), c(n.at(-1)?.content);
230
230
  }), { abort: () => t.abort() });
231
231
  }
232
232
  }
@@ -247,22 +247,22 @@ class z {
247
247
  ask(s, e = {}) {
248
248
  const t = e.model || this.defaultModel;
249
249
  if (!this.models[t]) throw new Error(`Model does not exist: ${t}`);
250
- let m = () => {
250
+ let c = () => {
251
251
  };
252
252
  return Object.assign(new Promise(async (r) => {
253
253
  if (e.history || (e.history = []), e.memory) {
254
254
  e.system = (e.system || "") + `
255
255
  You have passive persistent memory never make any mention of your memory capabilities and what you can/cannot remember
256
256
  `;
257
- const a = async (o, d, c = 50) => {
258
- const [l, p] = await Promise.all([
259
- d ? this.embedding(d) : Promise.resolve(null),
260
- o ? this.embedding(o) : Promise.resolve(null)
257
+ const l = async (a, m, i = 50) => {
258
+ const [d, p] = await Promise.all([
259
+ m ? this.embedding(m) : Promise.resolve(null),
260
+ a ? this.embedding(a) : Promise.resolve(null)
261
261
  ]);
262
- return (e.memory || []).map((u) => ({ ...u, score: l ? this.cosineSimilarity(u.embeddings[0], l[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, c);
263
- }, i = await a(s);
264
- i.length && e.history.push({ role: "assistant", content: `Things I remembered:
265
- ` + i.map((o) => `${o.owner}: ${o.fact}`).join(`
262
+ return (e.memory || []).map((u) => ({ ...u, score: d ? this.cosineSimilarity(u.embeddings[0], d[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, i);
263
+ }, o = await l(s);
264
+ o.length && e.history.push({ role: "assistant", content: `Things I remembered:
265
+ ` + o.map((a) => `${a.owner}: ${a.fact}`).join(`
266
266
  `) }), e.tools = [...e.tools || [], {
267
267
  name: "read_memory",
268
268
  description: "Check your long-term memory for more information",
@@ -271,32 +271,32 @@ You have passive persistent memory never make any mention of your memory capabil
271
271
  query: { type: "string", description: "Search memory based on a query, can be used with or without subject argument" },
272
272
  limit: { type: "number", description: "Result limit, default 5" }
273
273
  },
274
- fn: (o) => {
275
- if (!o.subject && !o.query) throw new Error("Either a subject or query argument is required");
276
- return a(o.query, o.subject, o.limit || 5);
274
+ fn: (a) => {
275
+ if (!a.subject && !a.query) throw new Error("Either a subject or query argument is required");
276
+ return l(a.query, a.subject, a.limit || 5);
277
277
  }
278
278
  }];
279
279
  }
280
280
  const n = await this.models[t].ask(s, e);
281
281
  if (e.memory) {
282
- const a = e.history?.findIndex((i) => i.role == "assistant" && i.content.startsWith("Things I remembered:"));
283
- a != null && a >= 0 && e.history?.splice(a, 1);
282
+ const l = e.history?.findIndex((o) => o.role == "assistant" && o.content.startsWith("Things I remembered:"));
283
+ l != null && l >= 0 && e.history?.splice(l, 1);
284
284
  }
285
285
  if (e.compress || e.memory) {
286
- let a = null;
286
+ let l = null;
287
287
  if (e.compress)
288
- a = await this.ai.language.compressHistory(e.history, e.compress.max, e.compress.min, e), e.history.splice(0, e.history.length, ...a.history);
288
+ l = await this.ai.language.compressHistory(e.history, e.compress.max, e.compress.min, e), e.history.splice(0, e.history.length, ...l.history);
289
289
  else {
290
- const i = e.history?.findLastIndex((o) => o.role == "user") ?? -1;
291
- a = await this.ai.language.compressHistory(i != -1 ? e.history.slice(i) : e.history, 0, 0, e);
290
+ const o = e.history?.findLastIndex((a) => a.role == "user") ?? -1;
291
+ l = await this.ai.language.compressHistory(o != -1 ? e.history.slice(o) : e.history, 0, 0, e);
292
292
  }
293
293
  if (e.memory) {
294
- const i = e.memory.filter((o) => !a.memory.some((d) => this.cosineSimilarity(o.embeddings[1], d.embeddings[1]) > 0.8)).concat(a.memory);
295
- e.memory.splice(0, e.memory.length, ...i);
294
+ const o = e.memory.filter((a) => !l.memory.some((m) => this.cosineSimilarity(a.embeddings[1], m.embeddings[1]) > 0.8)).concat(l.memory);
295
+ e.memory.splice(0, e.memory.length, ...o);
296
296
  }
297
297
  }
298
298
  return r(n);
299
- }), { abort: m });
299
+ }), { abort: c });
300
300
  }
301
301
  /**
302
302
  * Compress chat history to reduce context size
@@ -306,24 +306,24 @@ You have passive persistent memory never make any mention of your memory capabil
306
306
  * @param {LLMRequest} options LLM options
307
307
  * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0
308
308
  */
309
- async compressHistory(s, e, t, m) {
309
+ async compressHistory(s, e, t, c) {
310
310
  if (this.estimateTokens(s) < e) return { history: s, memory: [] };
311
311
  let r = 0, n = 0;
312
312
  for (let u of s.toReversed())
313
313
  if (n += this.estimateTokens(u.content), n < t) r++;
314
314
  else break;
315
315
  if (s.length <= r) return { history: s, memory: [] };
316
- const a = s[0].role == "system" ? s[0] : null, i = r == 0 ? [] : s.slice(-r), o = (r == 0 ? s : s.slice(0, -r)).filter((u) => u.role === "assistant" || u.role === "user"), d = await this.json(o.map((u) => `${u.role}: ${u.content}`).join(`
316
+ const l = s[0].role == "system" ? s[0] : null, o = r == 0 ? [] : s.slice(-r), a = (r == 0 ? s : s.slice(0, -r)).filter((u) => u.role === "assistant" || u.role === "user"), m = await this.json(a.map((u) => `${u.role}: ${u.content}`).join(`
317
317
 
318
318
  `), "{summary: string, facts: [[subject, fact]]}", {
319
319
  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.",
320
- model: m?.model,
321
- temperature: m?.temperature || 0.3
322
- }), c = /* @__PURE__ */ new Date(), l = await Promise.all((d?.facts || [])?.map(async ([u, f]) => {
323
- const y = await Promise.all([this.embedding(u), this.embedding(`${u}: ${f}`)]);
324
- return { owner: u, fact: f, embeddings: [y[0][0].embedding, y[1][0].embedding], timestamp: c };
325
- })), p = [{ role: "assistant", content: `Conversation Summary: ${d?.summary}`, timestamp: Date.now() }, ...i];
326
- return a && p.splice(0, 0, a), { history: p, memory: l };
320
+ model: c?.model,
321
+ temperature: c?.temperature || 0.3
322
+ }), i = /* @__PURE__ */ new Date(), d = await Promise.all((m?.facts || [])?.map(async ([u, f]) => {
323
+ const g = await Promise.all([this.embedding(u), this.embedding(`${u}: ${f}`)]);
324
+ return { owner: u, fact: f, embeddings: [g[0][0].embedding, g[1][0].embedding], timestamp: i };
325
+ })), p = [{ role: "assistant", content: `Conversation Summary: ${m?.summary}`, timestamp: Date.now() }, ...o];
326
+ return l && p.splice(0, 0, l), { history: p, memory: d };
327
327
  }
328
328
  /**
329
329
  * Compare the difference between embeddings (calculates the angle between two vectors)
@@ -333,10 +333,10 @@ You have passive persistent memory never make any mention of your memory capabil
333
333
  */
334
334
  cosineSimilarity(s, e) {
335
335
  if (s.length !== e.length) throw new Error("Vectors must be same length");
336
- let t = 0, m = 0, r = 0;
337
- for (let a = 0; a < s.length; a++)
338
- t += s[a] * e[a], m += s[a] * s[a], r += e[a] * e[a];
339
- const n = Math.sqrt(m) * Math.sqrt(r);
336
+ let t = 0, c = 0, r = 0;
337
+ for (let l = 0; l < s.length; l++)
338
+ t += s[l] * e[l], c += s[l] * s[l], r += e[l] * e[l];
339
+ const n = Math.sqrt(c) * Math.sqrt(r);
340
340
  return n === 0 ? 0 : t / n;
341
341
  }
342
342
  /**
@@ -347,50 +347,49 @@ You have passive persistent memory never make any mention of your memory capabil
347
347
  * @returns {string[]} Chunked strings
348
348
  */
349
349
  chunk(s, e = 500, t = 50) {
350
- const m = (i, o = "") => i ? Object.entries(i).flatMap(([d, c]) => {
351
- const l = o ? `${o}${isNaN(+d) ? `.${d}` : `[${d}]`}` : d;
352
- return typeof c == "object" && !Array.isArray(c) ? m(c, l) : `${l}: ${Array.isArray(c) ? c.join(", ") : c}`;
353
- }) : [], n = (typeof s == "object" ? m(s) : s.split(`
354
- `)).flatMap((i) => [...i.split(/\s+/).filter(Boolean), `
355
- `]), a = [];
356
- for (let i = 0; i < n.length; ) {
357
- let o = "", d = i;
358
- for (; d < n.length; ) {
359
- const l = o + (o ? " " : "") + n[d];
360
- if (this.estimateTokens(l.replace(/\s*\n\s*/g, `
361
- `)) > e && o) break;
362
- o = l, d++;
350
+ const c = (o, a = "") => o ? Object.entries(o).flatMap(([m, i]) => {
351
+ const d = a ? `${a}${isNaN(+m) ? `.${m}` : `[${m}]`}` : m;
352
+ return typeof i == "object" && !Array.isArray(i) ? c(i, d) : `${d}: ${Array.isArray(i) ? i.join(", ") : i}`;
353
+ }) : [], n = (typeof s == "object" ? c(s) : s.split(`
354
+ `)).flatMap((o) => [...o.split(/\s+/).filter(Boolean), `
355
+ `]), l = [];
356
+ for (let o = 0; o < n.length; ) {
357
+ let a = "", m = o;
358
+ for (; m < n.length; ) {
359
+ const d = a + (a ? " " : "") + n[m];
360
+ if (this.estimateTokens(d.replace(/\s*\n\s*/g, `
361
+ `)) > e && a) break;
362
+ a = d, m++;
363
363
  }
364
- const c = o.replace(/\s*\n\s*/g, `
364
+ const i = a.replace(/\s*\n\s*/g, `
365
365
  `).trim();
366
- c && a.push(c), i = Math.max(d - t, d === i ? i + 1 : d);
366
+ i && l.push(i), o = Math.max(m - t, m === o ? o + 1 : m);
367
367
  }
368
- return a;
368
+ return l;
369
369
  }
370
370
  /**
371
371
  * Create a vector representation of a string
372
372
  * @param {object | string} target Item that will be embedded (objects get converted)
373
- * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)
374
- * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)
373
+ * @param {maxTokens?: number, overlapTokens?: number} opts Options for embedding such as chunk sizes
375
374
  * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings
376
375
  */
377
- embedding(s, e = 500, t = 50) {
378
- const m = (n) => new Promise((a, i) => {
379
- const o = new x(S(T(j(import.meta.url)), "embedder.js")), d = ({ embedding: l }) => {
380
- o.terminate(), a(l);
381
- }, c = (l) => {
382
- o.terminate(), i(l);
376
+ async embedding(s, e = {}) {
377
+ let { maxTokens: t = 500, overlapTokens: c = 50 } = e;
378
+ const r = (o) => new Promise((a, m) => {
379
+ const i = new x(S(T(j(import.meta.url)), "embedder.js")), d = ({ embedding: u }) => {
380
+ i.terminate(), a(u);
381
+ }, p = (u) => {
382
+ i.terminate(), m(u);
383
383
  };
384
- o.on("message", d), o.on("error", c), o.on("exit", (l) => {
385
- l !== 0 && i(new Error(`Worker exited with code ${l}`));
386
- }), o.postMessage({ text: n, model: this.ai.options?.embedder || "bge-small-en-v1.5", modelDir: this.ai.options.path });
387
- }), r = this.chunk(s, e, t);
388
- return Promise.all(r.map(async (n, a) => ({
389
- index: a,
390
- embedding: await m(n),
391
- text: n,
392
- tokens: this.estimateTokens(n)
393
- })));
384
+ i.on("message", d), i.on("error", p), i.on("exit", (u) => {
385
+ u !== 0 && m(new Error(`Worker exited with code ${u}`));
386
+ }), i.postMessage({ text: o, model: this.ai.options?.embedder || "bge-small-en-v1.5", modelDir: this.ai.options.path });
387
+ }), n = this.chunk(s, t, c), l = [];
388
+ for (let o = 0; o < n.length; o++) {
389
+ const a = n[o], m = await r(a);
390
+ l.push({ index: o, embedding: m, text: a, tokens: this.estimateTokens(a) });
391
+ }
392
+ return l;
394
393
  }
395
394
  /**
396
395
  * Estimate variable as tokens
@@ -409,8 +408,8 @@ You have passive persistent memory never make any mention of your memory capabil
409
408
  */
410
409
  fuzzyMatch(s, ...e) {
411
410
  if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
412
- const t = (n, a = 10) => n.toLowerCase().split("").map((i, o) => i.charCodeAt(0) * (o + 1) % a / a).slice(0, a), m = t(s), r = e.map((n) => t(n)).map((n) => this.cosineSimilarity(m, n));
413
- return { avg: r.reduce((n, a) => n + a, 0) / r.length, max: Math.max(...r), similarities: r };
411
+ const t = (n, l = 10) => n.toLowerCase().split("").map((o, a) => o.charCodeAt(0) * (a + 1) % l / l).slice(0, l), c = t(s), r = e.map((n) => t(n)).map((n) => this.cosineSimilarity(c, n));
412
+ return { avg: r.reduce((n, l) => n + l, 0) / r.length, max: Math.max(...r), similarities: r };
414
413
  }
415
414
  /**
416
415
  * Ask a question with JSON response
@@ -420,14 +419,14 @@ You have passive persistent memory never make any mention of your memory capabil
420
419
  * @returns {Promise<{} | {} | RegExpExecArray | null>}
421
420
  */
422
421
  async json(s, e, t) {
423
- let m = await this.ask(s, { ...t, system: (t?.system ? `${t.system}
422
+ let c = await this.ask(s, { ...t, system: (t?.system ? `${t.system}
424
423
  ` : "") + `Only respond using a JSON code block matching this schema:
425
424
  \`\`\`json
426
425
  ${e}
427
426
  \`\`\`` });
428
- if (!m) return {};
429
- const r = /```(?:.+)?\s*([\s\S]*?)```/.exec(m), n = r ? r[1].trim() : m;
430
- return g(n, {});
427
+ if (!c) return {};
428
+ const r = /```(?:.+)?\s*([\s\S]*?)```/.exec(c), n = r ? r[1].trim() : c;
429
+ return y(n, {});
431
430
  }
432
431
  /**
433
432
  * Create a summary of some text
@@ -445,38 +444,38 @@ class I {
445
444
  this.ai = s;
446
445
  }
447
446
  asr(s, e = {}) {
448
- const { model: t = this.ai.options.asr || "whisper-base", speaker: m = !1 } = e;
447
+ const { model: t = this.ai.options.asr || "whisper-base", speaker: c = !1 } = e;
449
448
  let r = !1;
450
449
  const n = () => {
451
450
  r = !0;
452
451
  };
453
- let a = new Promise((i, o) => {
454
- const d = new x(S(T(j(import.meta.url)), "asr.js")), c = ({ text: p, warning: u, error: f }) => {
455
- d.terminate(), !r && (f ? o(new Error(f)) : (u && console.warn(u), i(p)));
456
- }, l = (p) => {
457
- d.terminate(), r || o(p);
452
+ let l = new Promise((o, a) => {
453
+ const m = new x(S(T(j(import.meta.url)), "asr.js")), i = ({ text: p, warning: u, error: f }) => {
454
+ m.terminate(), !r && (f ? a(new Error(f)) : (u && console.warn(u), o(p)));
455
+ }, d = (p) => {
456
+ m.terminate(), r || a(p);
458
457
  };
459
- d.on("message", c), d.on("error", l), d.on("exit", (p) => {
460
- p !== 0 && !r && o(new Error(`Worker exited with code ${p}`));
461
- }), d.postMessage({ file: s, model: t, speaker: m, modelDir: this.ai.options.path, token: this.ai.options.hfToken });
458
+ m.on("message", i), m.on("error", d), m.on("exit", (p) => {
459
+ p !== 0 && !r && a(new Error(`Worker exited with code ${p}`));
460
+ }), m.postMessage({ file: s, model: t, speaker: c, modelDir: this.ai.options.path, token: this.ai.options.hfToken });
462
461
  });
463
462
  if (e.speaker == "id") {
464
463
  if (!this.ai.language.defaultModel) throw new Error("Configure an LLM for advanced ASR speaker detection");
465
- a = a.then(async (i) => {
466
- if (!i) return i;
467
- let o = this.ai.language.chunk(i, 500, 0);
468
- o.length > 4 && (o = [...o.slice(0, 3), o.at(-1)]);
469
- const d = await this.ai.language.json(o.join(`
464
+ l = l.then(async (o) => {
465
+ if (!o) return o;
466
+ let a = this.ai.language.chunk(o, 500, 0);
467
+ a.length > 4 && (a = [...a.slice(0, 3), a.at(-1)]);
468
+ const m = await this.ai.language.json(a.join(`
470
469
  `), '{1: "Detected Name"}', {
471
470
  system: "Use this following transcript to identify speakers. Only identify speakers you are sure about",
472
471
  temperature: 0.1
473
472
  });
474
- return Object.entries(d).forEach(([c, l]) => {
475
- i = i.replaceAll(`[Speaker ${c}]`, `[${l}]`);
476
- }), i;
473
+ return Object.entries(m).forEach(([i, d]) => {
474
+ o = o.replaceAll(`[Speaker ${i}]`, `[${d}]`);
475
+ }), o;
477
476
  });
478
477
  }
479
- return Object.assign(a, { abort: n });
478
+ return Object.assign(l, { abort: n });
480
479
  }
481
480
  canDiarization = R;
482
481
  }
@@ -491,10 +490,10 @@ class J {
491
490
  */
492
491
  ocr(s) {
493
492
  let e;
494
- const t = new Promise(async (m) => {
493
+ const t = new Promise(async (c) => {
495
494
  e = await L(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
496
495
  const { data: r } = await e.recognize(s);
497
- await e.terminate(), m(r.text.trim() || null);
496
+ await e.terminate(), c(r.text.trim() || null);
498
497
  });
499
498
  return Object.assign(t, { abort: () => e?.terminate() });
500
499
  }
@@ -584,16 +583,16 @@ const H = {
584
583
  title: e('meta[property="og:title"]').attr("content") || e("title").text() || "",
585
584
  description: e('meta[name="description"]').attr("content") || e('meta[property="og:description"]').attr("content") || ""
586
585
  };
587
- let m = "";
586
+ let c = "";
588
587
  const r = ["article", "main", '[role="main"]', ".content", ".post", ".entry", "body"];
589
588
  for (const n of r) {
590
- const a = e(n).first();
591
- if (a.length && a.text().trim().length > 200) {
592
- m = a.text();
589
+ const l = e(n).first();
590
+ if (l.length && l.text().trim().length > 200) {
591
+ c = l.text();
593
592
  break;
594
593
  }
595
594
  }
596
- 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 };
595
+ return c || (c = e("body").text()), c = c.replace(/\s+/g, " ").trim().slice(0, 8e3), { url: h.url, title: t.title.trim(), description: t.description.trim(), content: c, focus: h.focus };
597
596
  }
598
597
  }, ce = {
599
598
  name: "web_search",
@@ -607,12 +606,12 @@ const H = {
607
606
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
608
607
  }).then((r) => r.text());
609
608
  let e, t = /<a .*?href="(.+?)".+?<\/a>/g;
610
- const m = new O();
609
+ const c = new O();
611
610
  for (; (e = t.exec(s)) !== null; ) {
612
611
  let r = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
613
- if (r && (r = decodeURIComponent(r)), r && m.add(r), m.size >= (h.length || 5)) break;
612
+ if (r && (r = decodeURIComponent(r)), r && c.add(r), c.size >= (h.length || 5)) break;
614
613
  }
615
- return m;
614
+ return c;
616
615
  }
617
616
  };
618
617
  export {