@ztimson/ai-utils 0.7.0 → 0.7.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,5 +1,5 @@
1
1
  import * as $ from "node:os";
2
- import { objectMap as _, JSONAttemptParse as g, findByProp as k, 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 g, 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 l of s)
23
- if (typeof l.content == "string")
24
- t.push({ timestamp: e, ...l });
22
+ for (let m of s)
23
+ if (typeof m.content == "string")
24
+ t.push({ timestamp: e, ...m });
25
25
  else {
26
- const r = l.content?.filter((n) => n.type == "text").map((n) => n.text).join(`
26
+ const r = m.content?.filter((n) => n.type == "text").map((n) => n.text).join(`
27
27
 
28
28
  `);
29
- r && t.push({ timestamp: e, role: l.role, content: r }), l.content.forEach((n) => {
29
+ r && t.push({ timestamp: e, role: m.role, content: r }), m.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 i = t.findLast((o) => o.id == n.tool_use_id);
34
- i && (i[n.is_error ? "error" : "content"] = n.content);
33
+ const a = t.findLast((i) => i.id == n.tool_use_id);
34
+ a && (a[n.is_error ? "error" : "content"] = n.content);
35
35
  }
36
36
  });
37
37
  }
@@ -52,9 +52,9 @@ class W extends q {
52
52
  }
53
53
  ask(s, e = {}) {
54
54
  const t = new AbortController();
55
- return Object.assign(new Promise(async (l) => {
55
+ return Object.assign(new Promise(async (m) => {
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 || [], i = {
57
+ const n = e.tools || this.ai.options.llm?.tools || [], a = {
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 || "",
@@ -64,7 +64,7 @@ class W extends q {
64
64
  description: d.description,
65
65
  input_schema: {
66
66
  type: "object",
67
- properties: d.args ? _(d.args, (c, m) => ({ ...m, required: void 0 })) : {},
67
+ properties: d.args ? k(d.args, (c, l) => ({ ...l, required: void 0 })) : {},
68
68
  required: d.args ? Object.entries(d.args).filter((c) => c[1].required).map((c) => c[0]) : []
69
69
  },
70
70
  fn: void 0
@@ -72,58 +72,58 @@ class W extends q {
72
72
  messages: r,
73
73
  stream: !!e.stream
74
74
  };
75
- let o, a = !0;
75
+ let i, o = !0;
76
76
  do {
77
- if (o = await this.client.messages.create(i).catch((c) => {
77
+ if (i = await this.client.messages.create(a).catch((c) => {
78
78
  throw c.message += `
79
79
 
80
80
  Messages:
81
81
  ${JSON.stringify(r, null, 2)}`, c;
82
82
  }), e.stream) {
83
- a ? a = !1 : e.stream({ text: `
83
+ o ? o = !1 : e.stream({ text: `
84
84
 
85
- ` }), o.content = [];
86
- for await (const c of o) {
85
+ ` }), i.content = [];
86
+ for await (const c of i) {
87
87
  if (t.signal.aborted) break;
88
88
  if (c.type === "content_block_start")
89
- c.content_block.type === "text" ? o.content.push({ type: "text", text: "" }) : c.content_block.type === "tool_use" && o.content.push({ type: "tool_use", id: c.content_block.id, name: c.content_block.name, input: "" });
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
90
  else if (c.type === "content_block_delta")
91
91
  if (c.delta.type === "text_delta") {
92
- const m = c.delta.text;
93
- o.content.at(-1).text += m, e.stream({ text: m });
94
- } else c.delta.type === "input_json_delta" && (o.content.at(-1).input += c.delta.partial_json);
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
95
  else if (c.type === "content_block_stop") {
96
- const m = o.content.at(-1);
97
- m.input != null && (m.input = m.input ? g(m.input, {}) : {});
96
+ const l = i.content.at(-1);
97
+ l.input != null && (l.input = l.input ? g(l.input, {}) : {});
98
98
  } else if (c.type === "message_stop")
99
99
  break;
100
100
  }
101
101
  }
102
- const d = o.content.filter((c) => c.type === "tool_use");
102
+ const d = i.content.filter((c) => c.type === "tool_use");
103
103
  if (d.length && !t.signal.aborted) {
104
- r.push({ role: "assistant", content: o.content });
105
- const c = await Promise.all(d.map(async (m) => {
106
- const p = n.find(k("name", m.name));
107
- if (e.stream && e.stream({ tool: m.name }), !p) return { tool_use_id: m.id, is_error: !0, content: "Tool not found" };
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" };
108
108
  try {
109
- const u = await p.fn(m.input, e?.stream, this.ai);
110
- return { type: "tool_result", tool_use_id: m.id, content: b(u) };
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) };
111
111
  } catch (u) {
112
- return { type: "tool_result", tool_use_id: m.id, is_error: !0, content: u?.message || u?.toString() || "Unknown" };
112
+ return { type: "tool_result", tool_use_id: l.id, is_error: !0, content: u?.message || u?.toString() || "Unknown" };
113
113
  }
114
114
  }));
115
- r.push({ role: "user", content: c }), i.messages = r;
115
+ r.push({ role: "user", content: c }), a.messages = r;
116
116
  }
117
- } while (!t.signal.aborted && o.content.some((d) => d.type === "tool_use"));
118
- r.push({ role: "assistant", content: o.content.filter((d) => d.type == "text").map((d) => d.text).join(`
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(`
119
119
 
120
- `) }), r = this.toStandard(r), e.stream && e.stream({ done: !0 }), e.history && e.history.splice(0, e.history.length, ...r), l(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), m(r.at(-1)?.content);
121
121
  }), { abort: () => t.abort() });
122
122
  }
123
123
  }
124
124
  class w extends q {
125
- constructor(s, e, t, l) {
126
- super(), this.ai = s, this.host = e, this.token = t, this.model = l, this.client = new U(M({
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({
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 l = t.tool_calls.map((r) => ({
136
+ const m = t.tool_calls.map((r) => ({
137
137
  role: "tool",
138
138
  id: r.id,
139
139
  name: r.function.name,
140
140
  args: g(r.function.arguments, {}),
141
141
  timestamp: t.timestamp
142
142
  }));
143
- s.splice(e, 1, ...l), e += l.length - 1;
143
+ s.splice(e, 1, ...m), e += m.length - 1;
144
144
  } else if (t.role === "tool" && t.content) {
145
- const l = s.find((r) => t.tool_call_id == r.id);
146
- l && (t.content.includes('"error":') ? l.error = t.content : l.content = t.content), s.splice(e, 1), e--;
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--;
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: l, ...r } = t;
167
+ const { timestamp: m, ...r } = t;
168
168
  e.push(r);
169
169
  }
170
170
  return e;
@@ -172,49 +172,49 @@ class w extends q {
172
172
  }
173
173
  ask(s, e = {}) {
174
174
  const t = new AbortController();
175
- return Object.assign(new Promise(async (l, r) => {
175
+ return Object.assign(new Promise(async (m, 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 i = e.tools || this.ai.options.llm?.tools || [], o = {
178
+ const a = e.tools || this.ai.options.llm?.tools || [], i = {
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: i.map((c) => ({
184
+ tools: a.map((c) => ({
185
185
  type: "function",
186
186
  function: {
187
187
  name: c.name,
188
188
  description: c.description,
189
189
  parameters: {
190
190
  type: "object",
191
- properties: c.args ? _(c.args, (m, p) => ({ ...p, required: void 0 })) : {},
192
- required: c.args ? Object.entries(c.args).filter((m) => m[1].required).map((m) => m[0]) : []
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]) : []
193
193
  }
194
194
  }
195
195
  }))
196
196
  };
197
- let a, d = !0;
197
+ let o, d = !0;
198
198
  do {
199
- if (a = await this.client.chat.completions.create(o).catch((m) => {
200
- throw m.message += `
199
+ if (o = await this.client.chat.completions.create(i).catch((l) => {
200
+ throw l.message += `
201
201
 
202
202
  Messages:
203
- ${JSON.stringify(n, null, 2)}`, m;
203
+ ${JSON.stringify(n, null, 2)}`, l;
204
204
  }), e.stream) {
205
205
  d ? d = !1 : e.stream({ text: `
206
206
 
207
- ` }), a.choices = [{ message: { content: "", tool_calls: [] } }];
208
- for await (const m of a) {
207
+ ` }), o.choices = [{ message: { content: "", tool_calls: [] } }];
208
+ for await (const l of o) {
209
209
  if (t.signal.aborted) break;
210
- m.choices[0].delta.content && (a.choices[0].message.content += m.choices[0].delta.content, e.stream({ text: m.choices[0].delta.content })), m.choices[0].delta.tool_calls && (a.choices[0].message.tool_calls = m.choices[0].delta.tool_calls);
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);
211
211
  }
212
212
  }
213
- const c = a.choices[0].message.tool_calls || [];
213
+ const c = o.choices[0].message.tool_calls || [];
214
214
  if (c.length && !t.signal.aborted) {
215
- n.push(a.choices[0].message);
216
- const m = await Promise.all(c.map(async (p) => {
217
- const u = i?.find(k("name", p.function.name));
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));
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
220
  const f = g(p.function.arguments, {}), y = await u.fn(f, e.stream, this.ai);
@@ -223,10 +223,10 @@ ${JSON.stringify(n, null, 2)}`, m;
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(...m), o.messages = n;
226
+ n.push(...l), i.messages = n;
227
227
  }
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), l(n.at(-1)?.content);
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);
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 l = () => {
250
+ let m = () => {
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 i = async (a, d, c = 50) => {
258
- const [m, p] = await Promise.all([
257
+ const a = async (o, d, c = 50) => {
258
+ const [l, p] = await Promise.all([
259
259
  d ? this.embedding(d) : Promise.resolve(null),
260
- a ? this.embedding(a) : Promise.resolve(null)
260
+ o ? this.embedding(o) : Promise.resolve(null)
261
261
  ]);
262
- return (e.memory || []).map((u) => ({ ...u, score: m ? this.cosineSimilarity(u.embeddings[0], m[0].embedding) : 1 })).filter((u) => u.score >= 0.8).map((u) => ({ ...u, score: p ? this.cosineSimilarity(u.embeddings[1], p[0].embedding) : u.score })).filter((u) => u.score >= 0.2).toSorted((u, f) => u.score - f.score).slice(0, c);
263
- }, o = await i(s);
264
- o.length && e.history.push({ role: "assistant", content: `Things I remembered:
265
- ` + o.map((a) => `${a.owner}: ${a.fact}`).join(`
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(`
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: (a) => {
275
- if (!a.subject && !a.query) throw new Error("Either a subject or query argument is required");
276
- return i(a.query, a.subject, a.limit || 5);
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);
277
277
  }
278
278
  }];
279
279
  }
280
280
  const n = await this.models[t].ask(s, e);
281
281
  if (e.memory) {
282
- const i = e.history?.findIndex((o) => o.role == "assistant" && o.content.startsWith("Things I remembered:"));
283
- i != null && i >= 0 && e.history?.splice(i, 1);
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);
284
284
  }
285
285
  if (e.compress || e.memory) {
286
- let i = null;
286
+ let a = null;
287
287
  if (e.compress)
288
- i = await this.ai.language.compressHistory(e.history, e.compress.max, e.compress.min, e), e.history.splice(0, e.history.length, ...i.history);
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);
289
289
  else {
290
- const o = e.history?.findLastIndex((a) => a.role == "user") ?? -1;
291
- i = await this.ai.language.compressHistory(o != -1 ? e.history.slice(o) : e.history, 0, 0, e);
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);
292
292
  }
293
293
  if (e.memory) {
294
- const o = e.memory.filter((a) => !i.memory.some((d) => this.cosineSimilarity(a.embeddings[1], d.embeddings[1]) > 0.8)).concat(i.memory);
295
- e.memory.splice(0, e.memory.length, ...o);
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);
296
296
  }
297
297
  }
298
298
  return r(n);
299
- }), { abort: l });
299
+ }), { abort: m });
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, l) {
309
+ async compressHistory(s, e, t, m) {
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 i = 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"), d = await this.json(a.map((u) => `${u.role}: ${u.content}`).join(`
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(`
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: l?.model,
321
- temperature: l?.temperature || 0.3
322
- }), c = /* @__PURE__ */ new Date(), m = await Promise.all((d?.facts || [])?.map(async ([u, f]) => {
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
323
  const y = await Promise.all([this.embedding(u), this.embedding(`${u}: ${f}`)]);
324
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() }, ...o];
326
- return i && p.splice(0, 0, i), { history: p, memory: m };
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 };
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, l = 0, r = 0;
337
- for (let i = 0; i < s.length; i++)
338
- t += s[i] * e[i], l += s[i] * s[i], r += e[i] * e[i];
339
- const n = Math.sqrt(l) * Math.sqrt(r);
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);
340
340
  return n === 0 ? 0 : t / n;
341
341
  }
342
342
  /**
@@ -347,25 +347,25 @@ 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 l = (o, a = "") => o ? Object.entries(o).flatMap(([d, c]) => {
351
- const m = a ? `${a}${isNaN(+d) ? `.${d}` : `[${d}]`}` : d;
352
- return typeof c == "object" && !Array.isArray(c) ? l(c, m) : `${m}: ${Array.isArray(c) ? c.join(", ") : c}`;
353
- }) : [], n = (typeof s == "object" ? l(s) : s.split(`
354
- `)).flatMap((o) => [...o.split(/\s+/).filter(Boolean), `
355
- `]), i = [];
356
- for (let o = 0; o < n.length; ) {
357
- let a = "", d = o;
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
358
  for (; d < n.length; ) {
359
- const m = a + (a ? " " : "") + n[d];
360
- if (this.estimateTokens(m.replace(/\s*\n\s*/g, `
361
- `)) > e && a) break;
362
- a = m, d++;
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++;
363
363
  }
364
- const c = a.replace(/\s*\n\s*/g, `
364
+ const c = o.replace(/\s*\n\s*/g, `
365
365
  `).trim();
366
- c && i.push(c), o = Math.max(d - t, d === o ? o + 1 : d);
366
+ c && a.push(c), i = Math.max(d - t, d === i ? i + 1 : d);
367
367
  }
368
- return i;
368
+ return a;
369
369
  }
370
370
  /**
371
371
  * Create a vector representation of a string
@@ -375,19 +375,19 @@ You have passive persistent memory never make any mention of your memory capabil
375
375
  * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings
376
376
  */
377
377
  embedding(s, e = 500, t = 50) {
378
- const l = (n) => new Promise((i, o) => {
379
- const a = new x(S(T(j(import.meta.url)), "embedder.js")), d = ({ embedding: m }) => {
380
- a.terminate(), i(m);
381
- }, c = (m) => {
382
- a.terminate(), o(m);
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);
383
383
  };
384
- a.on("message", d), a.on("error", c), a.on("exit", (m) => {
385
- m !== 0 && o(new Error(`Worker exited with code ${m}`));
386
- }), a.postMessage({ text: n, model: this.ai.options?.embedder || "bge-small-en-v1.5", modelDir: this.ai.options.path });
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
387
  }), r = this.chunk(s, e, t);
388
- return Promise.all(r.map(async (n, i) => ({
389
- index: i,
390
- embedding: await l(n),
388
+ return Promise.all(r.map(async (n, a) => ({
389
+ index: a,
390
+ embedding: await m(n),
391
391
  text: n,
392
392
  tokens: this.estimateTokens(n)
393
393
  })));
@@ -409,8 +409,8 @@ You have passive persistent memory never make any mention of your memory capabil
409
409
  */
410
410
  fuzzyMatch(s, ...e) {
411
411
  if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
412
- const t = (n, i = 10) => n.toLowerCase().split("").map((o, a) => o.charCodeAt(0) * (a + 1) % i / i).slice(0, i), l = t(s), r = e.map((n) => t(n)).map((n) => this.cosineSimilarity(l, n));
413
- return { avg: r.reduce((n, i) => n + i, 0) / r.length, max: Math.max(...r), similarities: r };
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 };
414
414
  }
415
415
  /**
416
416
  * Ask a question with JSON response
@@ -420,13 +420,13 @@ You have passive persistent memory never make any mention of your memory capabil
420
420
  * @returns {Promise<{} | {} | RegExpExecArray | null>}
421
421
  */
422
422
  async json(s, e, t) {
423
- let l = await this.ask(s, { ...t, system: (t?.system ? `${t.system}
423
+ let m = await this.ask(s, { ...t, system: (t?.system ? `${t.system}
424
424
  ` : "") + `Only respond using a JSON code block matching this schema:
425
425
  \`\`\`json
426
426
  ${e}
427
427
  \`\`\`` });
428
- if (!l) return {};
429
- const r = /```(?:.+)?\s*([\s\S]*?)```/.exec(l), n = r ? r[1].trim() : l;
428
+ if (!m) return {};
429
+ const r = /```(?:.+)?\s*([\s\S]*?)```/.exec(m), n = r ? r[1].trim() : m;
430
430
  return g(n, {});
431
431
  }
432
432
  /**
@@ -445,35 +445,38 @@ class I {
445
445
  this.ai = s;
446
446
  }
447
447
  asr(s, e = {}) {
448
- const { model: t = this.ai.options.asr || "whisper-base", speaker: l = !1 } = e;
448
+ const { model: t = this.ai.options.asr || "whisper-base", speaker: m = !1 } = e;
449
449
  let r = !1;
450
450
  const n = () => {
451
451
  r = !0;
452
452
  };
453
- let i = new Promise((o, a) => {
453
+ let a = new Promise((i, o) => {
454
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 ? a(new Error(f)) : (u && console.warn(u), o(p)));
456
- }, m = (p) => {
457
- d.terminate(), r || a(p);
455
+ d.terminate(), !r && (f ? o(new Error(f)) : (u && console.warn(u), i(p)));
456
+ }, l = (p) => {
457
+ d.terminate(), r || o(p);
458
458
  };
459
- d.on("message", c), d.on("error", m), d.on("exit", (p) => {
460
- p !== 0 && !r && a(new Error(`Worker exited with code ${p}`));
461
- }), d.postMessage({ file: s, model: t, speaker: l, modelDir: this.ai.options.path, token: this.ai.options.hfToken });
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 });
462
462
  });
463
463
  if (e.speaker == "id") {
464
464
  if (!this.ai.language.defaultModel) throw new Error("Configure an LLM for advanced ASR speaker detection");
465
- i = i.then(async (o) => {
466
- if (!o) return o;
467
- const a = await this.ai.language.json(o, '{1: "Detected Name"}', {
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(`
470
+ `), '{1: "Detected Name"}', {
468
471
  system: "Use this following transcript to identify speakers. Only identify speakers you are sure about",
469
- temperature: 0.2
472
+ temperature: 0.1
470
473
  });
471
- return Object.entries(a).forEach(([d, c]) => {
472
- o = o.replaceAll(`[Speaker ${d}]`, `[${c}]`);
473
- }), o;
474
+ return Object.entries(d).forEach(([c, l]) => {
475
+ i = i.replaceAll(`[Speaker ${c}]`, `[${l}]`);
476
+ }), i;
474
477
  });
475
478
  }
476
- return Object.assign(i, { abort: n });
479
+ return Object.assign(a, { abort: n });
477
480
  }
478
481
  canDiarization = R;
479
482
  }
@@ -488,10 +491,10 @@ class J {
488
491
  */
489
492
  ocr(s) {
490
493
  let e;
491
- const t = new Promise(async (l) => {
494
+ const t = new Promise(async (m) => {
492
495
  e = await L(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
493
496
  const { data: r } = await e.recognize(s);
494
- await e.terminate(), l(r.text.trim() || null);
497
+ await e.terminate(), m(r.text.trim() || null);
495
498
  });
496
499
  return Object.assign(t, { abort: () => e?.terminate() });
497
500
  }
@@ -581,16 +584,16 @@ const H = {
581
584
  title: e('meta[property="og:title"]').attr("content") || e("title").text() || "",
582
585
  description: e('meta[name="description"]').attr("content") || e('meta[property="og:description"]').attr("content") || ""
583
586
  };
584
- let l = "";
587
+ let m = "";
585
588
  const r = ["article", "main", '[role="main"]', ".content", ".post", ".entry", "body"];
586
589
  for (const n of r) {
587
- const i = e(n).first();
588
- if (i.length && i.text().trim().length > 200) {
589
- l = i.text();
590
+ const a = e(n).first();
591
+ if (a.length && a.text().trim().length > 200) {
592
+ m = a.text();
590
593
  break;
591
594
  }
592
595
  }
593
- 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 };
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 };
594
597
  }
595
598
  }, ce = {
596
599
  name: "web_search",
@@ -604,12 +607,12 @@ const H = {
604
607
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
605
608
  }).then((r) => r.text());
606
609
  let e, t = /<a .*?href="(.+?)".+?<\/a>/g;
607
- const l = new O();
610
+ const m = new O();
608
611
  for (; (e = t.exec(s)) !== null; ) {
609
612
  let r = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
610
- if (r && (r = decodeURIComponent(r)), r && l.add(r), l.size >= (h.length || 5)) break;
613
+ if (r && (r = decodeURIComponent(r)), r && m.add(r), m.size >= (h.length || 5)) break;
611
614
  }
612
- return l;
615
+ return m;
613
616
  }
614
617
  };
615
618
  export {