@ztimson/ai-utils 0.1.16 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,39 +1,33 @@
1
- import { createWorker as S } from "tesseract.js";
2
- import { objectMap as _, JSONAttemptParse as w, findByProp as b, JSONSanitize as y, Http as j, consoleInterceptor as T, fn as q, ASet as v } from "@ztimson/utils";
3
- import { Anthropic as P } from "@anthropic-ai/sdk";
4
- import { Ollama as A } from "ollama";
5
- import { OpenAI as E } from "openai";
6
- import x from "node:fs/promises";
1
+ import { createWorker as D } from "tesseract.js";
2
+ import { objectMap as k, JSONAttemptParse as b, findByProp as x, JSONSanitize as y, Http as T, consoleInterceptor as q, fn as v, ASet as P } from "@ztimson/utils";
3
+ import { Anthropic as A } from "@anthropic-ai/sdk";
4
+ import { Ollama as E } from "ollama";
5
+ import { OpenAI as M } from "openai";
6
+ import j from "node:fs/promises";
7
7
  import O from "node:path";
8
- import * as g from "@tensorflow/tfjs";
9
- import { spawn as M } from "node:child_process";
10
- import { $ as U, $Sync as $ } from "@ztimson/node-utils";
11
- class k {
8
+ import * as _ from "@tensorflow/tfjs";
9
+ import { spawn as U } from "node:child_process";
10
+ import { $, $Sync as L } from "@ztimson/node-utils";
11
+ class S {
12
12
  }
13
- class L extends k {
13
+ class R extends S {
14
14
  constructor(t, e, n) {
15
- super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new P({ apiKey: e });
15
+ super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new A({ apiKey: e });
16
16
  }
17
17
  client;
18
18
  toStandard(t) {
19
- const e = [];
20
- for (let n = 0; n < t.length; n++) {
21
- const i = t[n];
22
- if (typeof i.content != "string" && (i.role == "assistant" ? i.content.filter((o) => o.type == "tool_use").forEach((o) => {
23
- e.push({ role: "tool", id: o.id, name: o.name, args: o.input });
24
- }) : i.role == "user" && i.content.filter((o) => o.type == "tool_result").forEach((o) => {
25
- const p = e.find((c) => c.id == o.tool_use_id);
26
- p && (p[o.is_error ? "error" : "content"] = o.content);
27
- }), i.content = i.content.filter((o) => o.type == "text").map((o) => o.text).join(`
28
-
29
- `)), i.content) {
30
- const o = e.at(-1);
31
- o && o.role == "assistant" && i.role == "assistant" ? o.content += `
19
+ for (let e = 0; e < t.length; e++) {
20
+ const n = e;
21
+ typeof t[n].content != "string" && (t[n].role == "assistant" ? t[n].content.filter((o) => o.type == "tool_use").forEach((o) => {
22
+ e++, t.splice(e, 0, { role: "tool", id: o.id, name: o.name, args: o.input, timestamp: Date.now() });
23
+ }) : t[n].role == "user" && t[n].content.filter((o) => o.type == "tool_result").forEach((o) => {
24
+ const m = t.find((u) => u.id == o.tool_use_id);
25
+ m[o.is_error ? "error" : "content"] = o.content;
26
+ }), t[n].content = t[n].content.filter((o) => o.type == "text").map((o) => o.text).join(`
32
27
 
33
- ` + i.content : e.push({ role: i.role, content: i.content });
34
- }
28
+ `)), t[n].timestamp || (t[n].timestamp = Date.now());
35
29
  }
36
- return e;
30
+ return t.filter((e) => !!e.content);
37
31
  }
38
32
  fromStandard(t) {
39
33
  for (let e = 0; e < t.length; e++)
@@ -42,17 +36,17 @@ class L extends k {
42
36
  t.splice(
43
37
  e,
44
38
  1,
45
- { role: "assistant", content: [{ type: "tool_use", id: n.id, name: n.name, input: n.args }] },
46
- { role: "user", content: [{ type: "tool_result", tool_use_id: n.id, is_error: !!n.error, content: n.error || n.content }] }
39
+ { role: "assistant", content: [{ type: "tool_use", id: n.id, name: n.name, input: n.args }], timestamp: n.timestamp },
40
+ { role: "user", content: [{ type: "tool_result", tool_use_id: n.id, is_error: !!n.error, content: n.error || n.content }], timestamp: Date.now() }
47
41
  ), e++;
48
42
  }
49
43
  return t;
50
44
  }
51
45
  ask(t, e = {}) {
52
- const n = new AbortController(), i = new Promise(async (o, p) => {
53
- let c = this.fromStandard([...e.history || [], { role: "user", content: t }]);
46
+ const n = new AbortController(), o = new Promise(async (m, u) => {
47
+ let c = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
54
48
  e.compress && (c = await this.ai.llm.compress(c, e.compress.max, e.compress.min, e));
55
- const m = {
49
+ const d = {
56
50
  model: e.model || this.model,
57
51
  max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
58
52
  system: e.system || this.ai.options.system || "",
@@ -62,154 +56,166 @@ class L extends k {
62
56
  description: a.description,
63
57
  input_schema: {
64
58
  type: "object",
65
- properties: a.args ? _(a.args, (r, d) => ({ ...d, required: void 0 })) : {},
66
- required: a.args ? Object.entries(a.args).filter((r) => r[1].required).map((r) => r[0]) : []
59
+ properties: a.args ? k(a.args, (s, l) => ({ ...l, required: void 0 })) : {},
60
+ required: a.args ? Object.entries(a.args).filter((s) => s[1].required).map((s) => s[0]) : []
67
61
  },
68
62
  fn: void 0
69
63
  })),
70
64
  messages: c,
71
65
  stream: !!e.stream
72
66
  };
73
- let l, s = !0;
67
+ let i;
68
+ const r = [];
74
69
  do {
75
- if (l = await this.client.messages.create(m), e.stream) {
76
- s || e.stream({ text: `
70
+ if (i = await this.client.messages.create(d), e.stream) {
71
+ r.length && e.stream({ text: `
77
72
 
78
- ` }), s = !1, l.content = [];
79
- for await (const r of l) {
73
+ ` }), i.content = [];
74
+ for await (const s of i) {
80
75
  if (n.signal.aborted) break;
81
- if (r.type === "content_block_start")
82
- r.content_block.type === "text" ? l.content.push({ type: "text", text: "" }) : r.content_block.type === "tool_use" && l.content.push({ type: "tool_use", id: r.content_block.id, name: r.content_block.name, input: "" });
83
- else if (r.type === "content_block_delta")
84
- if (r.delta.type === "text_delta") {
85
- const d = r.delta.text;
86
- l.content.at(-1).text += d, e.stream({ text: d });
87
- } else r.delta.type === "input_json_delta" && (l.content.at(-1).input += r.delta.partial_json);
88
- else if (r.type === "content_block_stop") {
89
- const d = l.content.at(-1);
90
- d.input != null && (d.input = d.input ? w(d.input, {}) : {});
91
- } else if (r.type === "message_stop")
76
+ if (s.type === "content_block_start")
77
+ s.content_block.type === "text" ? i.content.push({ type: "text", text: "" }) : s.content_block.type === "tool_use" && i.content.push({ type: "tool_use", id: s.content_block.id, name: s.content_block.name, input: "" });
78
+ else if (s.type === "content_block_delta")
79
+ if (s.delta.type === "text_delta") {
80
+ const l = s.delta.text;
81
+ i.content.at(-1).text += l, e.stream({ text: l });
82
+ } else s.delta.type === "input_json_delta" && (i.content.at(-1).input += s.delta.partial_json);
83
+ else if (s.type === "content_block_stop") {
84
+ const l = i.content.at(-1);
85
+ l.input != null && (l.input = l.input ? b(l.input, {}) : {});
86
+ } else if (s.type === "message_stop")
92
87
  break;
93
88
  }
94
89
  }
95
- const a = l.content.filter((r) => r.type === "tool_use");
90
+ r.push({ role: "assistant", content: i.content, timestamp: Date.now() });
91
+ const a = i.content.filter((s) => s.type === "tool_use");
96
92
  if (a.length && !n.signal.aborted) {
97
- c.push({ role: "assistant", content: l.content });
98
- const r = await Promise.all(a.map(async (d) => {
99
- const f = e.tools?.find(b("name", d.name));
100
- if (!f) return { tool_use_id: d.id, is_error: !0, content: "Tool not found" };
93
+ c.push({ role: "assistant", content: i.content, timestamp: Date.now() });
94
+ const l = { role: "user", content: await Promise.all(a.map(async (f) => {
95
+ const h = e.tools?.find(x("name", f.name));
96
+ if (!h) return { tool_use_id: f.id, is_error: !0, content: "Tool not found" };
101
97
  try {
102
- const h = await f.fn(d.input, this.ai);
103
- return { type: "tool_result", tool_use_id: d.id, content: y(h) };
104
- } catch (h) {
105
- return { type: "tool_result", tool_use_id: d.id, is_error: !0, content: h?.message || h?.toString() || "Unknown" };
98
+ const g = await h.fn(f.input, this.ai);
99
+ return { type: "tool_result", tool_use_id: f.id, content: y(g) };
100
+ } catch (g) {
101
+ return { type: "tool_result", tool_use_id: f.id, is_error: !0, content: g?.message || g?.toString() || "Unknown" };
106
102
  }
107
- }));
108
- c.push({ role: "user", content: r }), m.messages = c;
103
+ })), timestamp: Date.now() };
104
+ c.push(l), r.push(l), d.messages = c;
109
105
  }
110
- } while (!n.signal.aborted && l.content.some((a) => a.type === "tool_use"));
111
- e.stream && e.stream({ done: !0 }), o(this.toStandard([...c, {
112
- role: "assistant",
113
- content: l.content.filter((a) => a.type == "text").map((a) => a.text).join(`
106
+ } while (!n.signal.aborted && i.content.some((a) => a.type === "tool_use"));
107
+ const w = r.filter((a) => a.role === "assistant").map((a) => a.content.filter((s) => s.type == "text").map((s) => s.text).join(`
114
108
 
115
- `)
116
- }]));
109
+ `)).filter((a) => a).join(`
110
+
111
+ `);
112
+ e.stream && e.stream({ done: !0 }), m(this.toStandard([...c, { role: "assistant", content: w, timestamp: Date.now() }]));
117
113
  });
118
- return Object.assign(i, { abort: () => n.abort() });
114
+ return Object.assign(o, { abort: () => n.abort() });
119
115
  }
120
116
  }
121
- class R extends k {
117
+ class I extends S {
122
118
  constructor(t, e, n) {
123
- super(), this.ai = t, this.host = e, this.model = n, this.client = new A({ host: e });
119
+ super(), this.ai = t, this.host = e, this.model = n, this.client = new E({ host: e });
124
120
  }
125
121
  client;
126
122
  toStandard(t) {
127
- for (let e = 0; e < t.length; e++)
123
+ for (let e = 0; e < t.length; e++) {
128
124
  if (t[e].role == "assistant" && t[e].tool_calls)
129
125
  t[e].content ? delete t[e].tool_calls : (t.splice(e, 1), e--);
130
126
  else if (t[e].role == "tool") {
131
127
  const n = t[e].content.startsWith('{"error":');
132
- t[e] = { role: "tool", name: t[e].tool_name, args: t[e].args, [n ? "error" : "content"]: t[e].content };
128
+ t[e] = { role: "tool", name: t[e].tool_name, args: t[e].args, [n ? "error" : "content"]: t[e].content, timestamp: t[e].timestamp };
133
129
  }
130
+ t[e]?.timestamp || (t[e].timestamp = Date.now());
131
+ }
134
132
  return t;
135
133
  }
136
134
  fromStandard(t) {
137
- return t.map((e) => e.role != "tool" ? e : { role: "tool", tool_name: e.name, content: e.error || e.content });
135
+ return t.map((e) => e.role != "tool" ? e : { role: "tool", tool_name: e.name, content: e.error || e.content, timestamp: e.timestamp });
138
136
  }
139
137
  ask(t, e = {}) {
140
- const n = new AbortController(), i = new Promise(async (o, p) => {
141
- let c = e.system || this.ai.options.system, m = this.fromStandard([...e.history || [], { role: "user", content: t }]);
142
- m[0].roll == "system" && (c ? m.shift() : c = m.shift()), e.compress && (m = await this.ai.llm.compress(m, e.compress.max, e.compress.min)), e.system && m.unshift({ role: "system", content: c });
143
- const l = {
138
+ const n = new AbortController(), o = new Promise(async (m, u) => {
139
+ let c = e.system || this.ai.options.system, d = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
140
+ d[0].roll == "system" && (c ? d.shift() : c = d.shift()), e.compress && (d = await this.ai.llm.compress(d, e.compress.max, e.compress.min)), e.system && d.unshift({ role: "system", content: c });
141
+ const i = {
144
142
  model: e.model || this.model,
145
- messages: m,
143
+ messages: d,
146
144
  stream: !!e.stream,
147
145
  signal: n.signal,
148
146
  options: {
149
147
  temperature: e.temperature || this.ai.options.temperature || 0.7,
150
148
  num_predict: e.max_tokens || this.ai.options.max_tokens || 4096
151
149
  },
152
- tools: (e.tools || this.ai.options.tools || []).map((a) => ({
150
+ tools: (e.tools || this.ai.options.tools || []).map((s) => ({
153
151
  type: "function",
154
152
  function: {
155
- name: a.name,
156
- description: a.description,
153
+ name: s.name,
154
+ description: s.description,
157
155
  parameters: {
158
156
  type: "object",
159
- properties: a.args ? _(a.args, (r, d) => ({ ...d, required: void 0 })) : {},
160
- required: a.args ? Object.entries(a.args).filter((r) => r[1].required).map((r) => r[0]) : []
157
+ properties: s.args ? k(s.args, (l, f) => ({ ...f, required: void 0 })) : {},
158
+ required: s.args ? Object.entries(s.args).filter((l) => l[1].required).map((l) => l[0]) : []
161
159
  }
162
160
  }
163
161
  }))
164
162
  };
165
- let s;
163
+ let r;
164
+ const w = [];
166
165
  do {
167
- if (s = await this.client.chat(l), e.stream) {
168
- s.message = { role: "assistant", content: "", tool_calls: [] };
169
- for await (const a of s)
170
- if (n.signal.aborted || (a.message?.content && (s.message.content += a.message.content, e.stream({ text: a.message.content })), a.message?.tool_calls && (s.message.tool_calls = a.message.tool_calls), a.done)) break;
166
+ if (r = await this.client.chat(i), e.stream) {
167
+ w.length && e.stream({ text: `
168
+
169
+ ` }), r.message = { role: "assistant", content: "", tool_calls: [] };
170
+ for await (const s of r)
171
+ if (n.signal.aborted || (s.message?.content && (r.message.content += s.message.content, e.stream({ text: s.message.content })), s.message?.tool_calls && (r.message.tool_calls = s.message.tool_calls), s.done)) break;
171
172
  }
172
- if (s.message?.tool_calls?.length && !n.signal.aborted) {
173
- m.push(s.message);
174
- const a = await Promise.all(s.message.tool_calls.map(async (r) => {
175
- const d = (e.tools || this.ai.options.tools)?.find(b("name", r.function.name));
176
- if (!d) return { role: "tool", tool_name: r.function.name, content: '{"error": "Tool not found"}' };
177
- const f = typeof r.function.arguments == "string" ? w(r.function.arguments, {}) : r.function.arguments;
173
+ if (w.push({ role: "assistant", content: r.message?.content, timestamp: Date.now() }), r.message?.tool_calls?.length && !n.signal.aborted) {
174
+ d.push({ ...r.message, timestamp: Date.now() });
175
+ const s = await Promise.all(r.message.tool_calls.map(async (l) => {
176
+ const f = (e.tools || this.ai.options.tools)?.find(x("name", l.function.name));
177
+ if (!f) return { role: "tool", tool_name: l.function.name, content: '{"error": "Tool not found"}', timestamp: Date.now() };
178
+ const h = typeof l.function.arguments == "string" ? b(l.function.arguments, {}) : l.function.arguments;
178
179
  try {
179
- const h = await d.fn(f, this.ai);
180
- return { role: "tool", tool_name: r.function.name, args: f, content: y(h) };
181
- } catch (h) {
182
- return { role: "tool", tool_name: r.function.name, args: f, content: y({ error: h?.message || h?.toString() || "Unknown" }) };
180
+ const g = await f.fn(h, this.ai);
181
+ return { role: "tool", tool_name: l.function.name, args: h, content: y(g), timestamp: Date.now() };
182
+ } catch (g) {
183
+ return { role: "tool", tool_name: l.function.name, args: h, content: y({ error: g?.message || g?.toString() || "Unknown" }), timestamp: Date.now() };
183
184
  }
184
185
  }));
185
- m.push(...a), l.messages = m;
186
+ d.push(...s), w.push(...s), i.messages = d;
186
187
  }
187
- } while (!n.signal.aborted && s.message?.tool_calls?.length);
188
- e.stream && e.stream({ done: !0 }), o(this.toStandard([...m, { role: "assistant", content: s.message?.content }]));
188
+ } while (!n.signal.aborted && r.message?.tool_calls?.length);
189
+ const a = w.filter((s) => s.role === "assistant").map((s) => s.content).filter((s) => s).join(`
190
+
191
+ `);
192
+ e.stream && e.stream({ done: !0 }), m(this.toStandard([...d, { role: "assistant", content: a, timestamp: Date.now() }]));
189
193
  });
190
- return Object.assign(i, { abort: () => n.abort() });
194
+ return Object.assign(o, { abort: () => n.abort() });
191
195
  }
192
196
  }
193
- class J extends k {
197
+ class J extends S {
194
198
  constructor(t, e, n) {
195
- super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new E({ apiKey: e });
199
+ super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new M({ apiKey: e });
196
200
  }
197
201
  client;
198
202
  toStandard(t) {
199
203
  for (let e = 0; e < t.length; e++) {
200
204
  const n = t[e];
201
205
  if (n.role === "assistant" && n.tool_calls) {
202
- const i = n.tool_calls.map((o) => ({
206
+ const o = n.tool_calls.map((m) => ({
203
207
  role: "tool",
204
- id: o.id,
205
- name: o.function.name,
206
- args: w(o.function.arguments, {})
208
+ id: m.id,
209
+ name: m.function.name,
210
+ args: b(m.function.arguments, {}),
211
+ timestamp: n.timestamp
207
212
  }));
208
- t.splice(e, 1, ...i), e += i.length - 1;
213
+ t.splice(e, 1, ...o), e += o.length - 1;
209
214
  } else if (n.role === "tool" && n.content) {
210
- const i = t.find((o) => n.tool_call_id == o.id);
211
- i && (n.content.includes('"error":') ? i.error = n.content : i.content = n.content), t.splice(e, 1), e--;
215
+ const o = t.find((m) => n.tool_call_id == m.id);
216
+ o && (n.content.includes('"error":') ? o.error = n.content : o.content = n.content), t.splice(e, 1), e--;
212
217
  }
218
+ t[e]?.timestamp || (t[e].timestamp = Date.now());
213
219
  }
214
220
  return t;
215
221
  }
@@ -219,69 +225,78 @@ class J extends k {
219
225
  content: null,
220
226
  tool_calls: [{ id: n.id, type: "function", function: { name: n.name, arguments: JSON.stringify(n.args) } }],
221
227
  refusal: null,
222
- annotations: []
228
+ annotations: [],
229
+ timestamp: n.timestamp
223
230
  }, {
224
231
  role: "tool",
225
232
  tool_call_id: n.id,
226
- content: n.error || n.content
233
+ content: n.error || n.content,
234
+ timestamp: Date.now()
227
235
  }) : e.push(n), e), []);
228
236
  }
229
237
  ask(t, e = {}) {
230
- const n = new AbortController(), i = new Promise(async (o, p) => {
231
- let c = this.fromStandard([...e.history || [], { role: "user", content: t }]);
238
+ const n = new AbortController(), o = new Promise(async (m, u) => {
239
+ let c = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
232
240
  e.compress && (c = await this.ai.llm.compress(c, e.compress.max, e.compress.min, e));
233
- const m = {
241
+ const d = {
234
242
  model: e.model || this.model,
235
243
  messages: c,
236
244
  stream: !!e.stream,
237
245
  max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
238
246
  temperature: e.temperature || this.ai.options.temperature || 0.7,
239
- tools: (e.tools || this.ai.options.tools || []).map((s) => ({
247
+ tools: (e.tools || this.ai.options.tools || []).map((a) => ({
240
248
  type: "function",
241
249
  function: {
242
- name: s.name,
243
- description: s.description,
250
+ name: a.name,
251
+ description: a.description,
244
252
  parameters: {
245
253
  type: "object",
246
- properties: s.args ? _(s.args, (a, r) => ({ ...r, required: void 0 })) : {},
247
- required: s.args ? Object.entries(s.args).filter((a) => a[1].required).map((a) => a[0]) : []
254
+ properties: a.args ? k(a.args, (s, l) => ({ ...l, required: void 0 })) : {},
255
+ required: a.args ? Object.entries(a.args).filter((s) => s[1].required).map((s) => s[0]) : []
248
256
  }
249
257
  }
250
258
  }))
251
259
  };
252
- let l;
260
+ let i;
261
+ const r = [];
253
262
  do {
254
- if (l = await this.client.chat.completions.create(m), e.stream) {
255
- l.choices = [];
256
- for await (const a of l) {
263
+ if (i = await this.client.chat.completions.create(d), e.stream) {
264
+ r.length && e.stream({ text: `
265
+
266
+ ` }), i.choices = [{ message: { content: "", tool_calls: [] } }];
267
+ for await (const s of i) {
257
268
  if (n.signal.aborted) break;
258
- a.choices[0].delta.content && e.stream({ text: a.choices[0].delta.content });
269
+ s.choices[0].delta.content && (i.choices[0].message.content += s.choices[0].delta.content, e.stream({ text: s.choices[0].delta.content })), s.choices[0].delta.tool_calls && (i.choices[0].message.tool_calls = s.choices[0].delta.tool_calls);
259
270
  }
260
271
  }
261
- const s = l.choices[0].message.tool_calls || [];
262
- if (s.length && !n.signal.aborted) {
263
- c.push(l.choices[0].message);
264
- const a = await Promise.all(s.map(async (r) => {
265
- const d = e.tools?.find(b("name", r.function.name));
266
- if (!d) return { role: "tool", tool_call_id: r.id, content: '{"error": "Tool not found"}' };
272
+ r.push({ role: "assistant", content: i.choices[0].message.content || "", timestamp: Date.now() });
273
+ const a = i.choices[0].message.tool_calls || [];
274
+ if (a.length && !n.signal.aborted) {
275
+ c.push({ ...i.choices[0].message, timestamp: Date.now() });
276
+ const s = await Promise.all(a.map(async (l) => {
277
+ const f = e.tools?.find(x("name", l.function.name));
278
+ if (!f) return { role: "tool", tool_call_id: l.id, content: '{"error": "Tool not found"}', timestamp: Date.now() };
267
279
  try {
268
- const f = w(r.function.arguments, {}), h = await d.fn(f, this.ai);
269
- return { role: "tool", tool_call_id: r.id, content: y(h) };
270
- } catch (f) {
271
- return { role: "tool", tool_call_id: r.id, content: y({ error: f?.message || f?.toString() || "Unknown" }) };
280
+ const h = b(l.function.arguments, {}), g = await f.fn(h, this.ai);
281
+ return { role: "tool", tool_call_id: l.id, content: y(g), timestamp: Date.now() };
282
+ } catch (h) {
283
+ return { role: "tool", tool_call_id: l.id, content: y({ error: h?.message || h?.toString() || "Unknown" }), timestamp: Date.now() };
272
284
  }
273
285
  }));
274
- c.push(...a), m.messages = c;
286
+ c.push(...s), r.push(...s), d.messages = c;
275
287
  }
276
- } while (!n.signal.aborted && l.choices?.[0]?.message?.tool_calls?.length);
277
- e.stream && e.stream({ done: !0 }), o(this.toStandard([...c, { role: "assistant", content: l.choices[0].message.content || "" }]));
288
+ } while (!n.signal.aborted && i.choices?.[0]?.message?.tool_calls?.length);
289
+ const w = r.filter((a) => a.role === "assistant").map((a) => a.content).filter((a) => a).join(`
290
+
291
+ `);
292
+ e.stream && e.stream({ done: !0 }), m(this.toStandard([...c, { role: "assistant", content: w, timestamp: Date.now() }]));
278
293
  });
279
- return Object.assign(i, { abort: () => n.abort() });
294
+ return Object.assign(o, { abort: () => n.abort() });
280
295
  }
281
296
  }
282
297
  class W {
283
298
  constructor(t, e) {
284
- this.ai = t, this.options = e, e.anthropic?.token && (this.providers.anthropic = new L(this.ai, e.anthropic.token, e.anthropic.model)), e.ollama?.host && (this.providers.ollama = new R(this.ai, e.ollama.host, e.ollama.model)), e.openAi?.token && (this.providers.openAi = new J(this.ai, e.openAi.token, e.openAi.model));
299
+ this.ai = t, this.options = e, e.anthropic?.token && (this.providers.anthropic = new R(this.ai, e.anthropic.token, e.anthropic.model)), e.ollama?.host && (this.providers.ollama = new I(this.ai, e.ollama.host, e.ollama.model)), e.openAi?.token && (this.providers.openAi = new J(this.ai, e.openAi.token, e.openAi.model));
285
300
  }
286
301
  providers = {};
287
302
  /**
@@ -303,17 +318,17 @@ class W {
303
318
  * @param {LLMRequest} options LLM options
304
319
  * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0
305
320
  */
306
- async compress(t, e, n, i) {
321
+ async compress(t, e, n, o) {
307
322
  if (this.estimateTokens(t) < e) return t;
308
- let o = 0, p = 0;
309
- for (let s of t.toReversed())
310
- if (p += this.estimateTokens(s.content), p < n) o++;
323
+ let m = 0, u = 0;
324
+ for (let r of t.toReversed())
325
+ if (u += this.estimateTokens(r.content), u < n) m++;
311
326
  else break;
312
- if (t.length <= o) return t;
313
- const c = o == 0 ? [] : t.slice(-o), m = (o == 0 ? t : t.slice(0, -o)).filter((s) => s.role === "assistant" || s.role === "user");
314
- return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(m.map((s) => `${s.role}: ${s.content}`).join(`
327
+ if (t.length <= m) return t;
328
+ const c = m == 0 ? [] : t.slice(-m), d = (m == 0 ? t : t.slice(0, -m)).filter((r) => r.role === "assistant" || r.role === "user");
329
+ return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(d.map((r) => `${r.role}: ${r.content}`).join(`
315
330
 
316
- `), 250, i)}` }, ...c];
331
+ `), 250, o)}`, timestamp: Date.now() }, ...c];
317
332
  }
318
333
  /**
319
334
  * Estimate variable as tokens
@@ -335,7 +350,7 @@ class W {
335
350
  system: "Respond using a JSON blob",
336
351
  ...e
337
352
  });
338
- return n?.[0]?.content ? w(new RegExp("{[sS]*}").exec(n[0].content), {}) : {};
353
+ return n?.[0]?.content ? b(new RegExp("{[sS]*}").exec(n[0].content), {}) : {};
339
354
  }
340
355
  /**
341
356
  * Create a summary of some text
@@ -345,10 +360,10 @@ class W {
345
360
  * @returns {Promise<string>} Summary
346
361
  */
347
362
  summarize(t, e, n) {
348
- return this.ask(t, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...n }).then((i) => i.pop()?.content || null);
363
+ return this.ask(t, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...n }).then((o) => o.pop()?.content || null);
349
364
  }
350
365
  }
351
- class X {
366
+ class Z {
352
367
  constructor(t) {
353
368
  this.options = t, this.llm = new W(this, t), this.options.whisper?.binary && (this.whisperModel = this.options.whisper?.model.endsWith(".bin") ? this.options.whisper?.model : this.options.whisper?.model + ".bin", this.downloadAsrModel());
354
369
  }
@@ -366,12 +381,12 @@ class X {
366
381
  if (!this.options.whisper?.binary) throw new Error("Whisper not configured");
367
382
  let n = () => {
368
383
  };
369
- return { response: new Promise((o, p) => {
384
+ return { response: new Promise((m, u) => {
370
385
  this.downloadAsrModel(e).then((c) => {
371
- let m = "";
372
- const l = M(this.options.whisper?.binary, ["-nt", "-np", "-m", c, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
373
- n = () => l.kill("SIGTERM"), l.on("error", (s) => p(s)), l.stdout.on("data", (s) => m += s.toString()), l.on("close", (s) => {
374
- s === 0 ? o(m.trim() || null) : p(new Error(`Exit code ${s}`));
386
+ let d = "";
387
+ const i = U(this.options.whisper?.binary, ["-nt", "-np", "-m", c, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
388
+ n = () => i.kill("SIGTERM"), i.on("error", (r) => u(r)), i.stdout.on("data", (r) => d += r.toString()), i.on("close", (r) => {
389
+ r === 0 ? m(d.trim() || null) : u(new Error(`Exit code ${r}`));
375
390
  });
376
391
  });
377
392
  }), abort: n };
@@ -386,7 +401,7 @@ class X {
386
401
  if (!this.options.whisper?.binary) throw new Error("Whisper not configured");
387
402
  t.endsWith(".bin") || (t += ".bin");
388
403
  const e = O.join(this.options.whisper.path, t);
389
- return await x.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[t] ? this.downloads[t] : (this.downloads[t] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then((n) => n.arrayBuffer()).then((n) => Buffer.from(n)).then(async (n) => (await x.writeFile(e, n), delete this.downloads[t], e)), this.downloads[t]);
404
+ return await j.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[t] ? this.downloads[t] : (this.downloads[t] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then((n) => n.arrayBuffer()).then((n) => Buffer.from(n)).then(async (n) => (await j.writeFile(e, n), delete this.downloads[t], e)), this.downloads[t]);
390
405
  }
391
406
  /**
392
407
  * Convert image to text using Optical Character Recognition
@@ -400,9 +415,9 @@ class X {
400
415
  e?.terminate();
401
416
  },
402
417
  response: new Promise(async (n) => {
403
- e = await S("eng");
404
- const { data: i } = await e.recognize(t);
405
- await e.terminate(), n(i.text.trim() || null);
418
+ e = await D("eng");
419
+ const { data: o } = await e.recognize(t);
420
+ await e.terminate(), n(o.text.trim() || null);
406
421
  })
407
422
  };
408
423
  }
@@ -414,46 +429,46 @@ class X {
414
429
  */
415
430
  semanticSimilarity(t, ...e) {
416
431
  if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
417
- const n = (c, m = 10) => c.toLowerCase().split("").map((l, s) => l.charCodeAt(0) * (s + 1) % m / m).slice(0, m), i = (c, m) => {
418
- if (c.length !== m.length) throw new Error("Vectors must be same length");
419
- const l = g.tensor1d(c), s = g.tensor1d(m), a = g.dot(l, s), r = g.norm(l), d = g.norm(s);
420
- return r.dataSync()[0] === 0 || d.dataSync()[0] === 0 ? 0 : a.dataSync()[0] / (r.dataSync()[0] * d.dataSync()[0]);
421
- }, o = n(t), p = e.map((c) => n(c)).map((c) => i(o, c));
422
- return { avg: p.reduce((c, m) => c + m, 0) / p.length, max: Math.max(...p), similarities: p };
432
+ const n = (c, d = 10) => c.toLowerCase().split("").map((i, r) => i.charCodeAt(0) * (r + 1) % d / d).slice(0, d), o = (c, d) => {
433
+ if (c.length !== d.length) throw new Error("Vectors must be same length");
434
+ const i = _.tensor1d(c), r = _.tensor1d(d), w = _.dot(i, r), a = _.norm(i), s = _.norm(r);
435
+ return a.dataSync()[0] === 0 || s.dataSync()[0] === 0 ? 0 : w.dataSync()[0] / (a.dataSync()[0] * s.dataSync()[0]);
436
+ }, m = n(t), u = e.map((c) => n(c)).map((c) => o(m, c));
437
+ return { avg: u.reduce((c, d) => c + d, 0) / u.length, max: Math.max(...u), similarities: u };
423
438
  }
424
439
  }
425
- const I = {
440
+ const N = {
426
441
  name: "cli",
427
442
  description: "Use the command line interface, returns any output",
428
443
  args: { command: { type: "string", description: "Command to run", required: !0 } },
429
- fn: (u) => U`${u.command}`
430
- }, Y = {
444
+ fn: (p) => $`${p.command}`
445
+ }, ee = {
431
446
  name: "get_datetime",
432
447
  description: "Get current date and time",
433
448
  args: {},
434
449
  fn: async () => (/* @__PURE__ */ new Date()).toISOString()
435
- }, Z = {
450
+ }, te = {
436
451
  name: "exec",
437
452
  description: "Run code/scripts",
438
453
  args: {
439
454
  language: { type: "string", description: "Execution language", enum: ["cli", "node", "python"], required: !0 },
440
455
  code: { type: "string", description: "Code to execute", required: !0 }
441
456
  },
442
- fn: async (u, t) => {
457
+ fn: async (p, t) => {
443
458
  try {
444
- switch (u.type) {
459
+ switch (p.type) {
445
460
  case "bash":
446
- return await I.fn({ command: u.code }, t);
461
+ return await N.fn({ command: p.code }, t);
447
462
  case "node":
448
- return await N.fn({ code: u.code }, t);
463
+ return await z.fn({ code: p.code }, t);
449
464
  case "python":
450
- return await z.fn({ code: u.code }, t);
465
+ return await G.fn({ code: p.code }, t);
451
466
  }
452
467
  } catch (e) {
453
468
  return { error: e?.message || e.toString() };
454
469
  }
455
470
  }
456
- }, ee = {
471
+ }, ne = {
457
472
  name: "fetch",
458
473
  description: "Make HTTP request to URL",
459
474
  args: {
@@ -462,54 +477,54 @@ const I = {
462
477
  headers: { type: "object", description: "HTTP headers to send", default: {} },
463
478
  body: { type: "object", description: "HTTP body to send" }
464
479
  },
465
- fn: (u) => new j({ url: u.url, headers: u.headers }).request({ method: u.method || "GET", body: u.body })
466
- }, N = {
480
+ fn: (p) => new T({ url: p.url, headers: p.headers }).request({ method: p.method || "GET", body: p.body })
481
+ }, z = {
467
482
  name: "exec_javascript",
468
483
  description: "Execute commonjs javascript",
469
484
  args: {
470
485
  code: { type: "string", description: "CommonJS javascript", required: !0 }
471
486
  },
472
- fn: async (u) => {
473
- const t = T(null), e = await q({ console: t }, u.code, !0).catch((n) => t.output.error.push(n));
487
+ fn: async (p) => {
488
+ const t = q(null), e = await v({ console: t }, p.code, !0).catch((n) => t.output.error.push(n));
474
489
  return { ...t.output, return: e, stdout: void 0, stderr: void 0 };
475
490
  }
476
- }, z = {
491
+ }, G = {
477
492
  name: "exec_javascript",
478
493
  description: "Execute commonjs javascript",
479
494
  args: {
480
495
  code: { type: "string", description: "CommonJS javascript", required: !0 }
481
496
  },
482
- fn: async (u) => ({ result: $`python -c "${u.code}"` })
483
- }, te = {
497
+ fn: async (p) => ({ result: L`python -c "${p.code}"` })
498
+ }, se = {
484
499
  name: "search",
485
500
  description: "Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",
486
501
  args: {
487
502
  query: { type: "string", description: "Search string", required: !0 },
488
503
  length: { type: "string", description: "Number of results to return", default: 5 }
489
504
  },
490
- fn: async (u) => {
491
- const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(u.query)}`, {
505
+ fn: async (p) => {
506
+ const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(p.query)}`, {
492
507
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
493
- }).then((o) => o.text());
508
+ }).then((m) => m.text());
494
509
  let e, n = /<a .*?href="(.+?)".+?<\/a>/g;
495
- const i = new v();
510
+ const o = new P();
496
511
  for (; (e = n.exec(t)) !== null; ) {
497
- let o = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
498
- if (o && (o = decodeURIComponent(o)), o && i.add(o), i.size >= (u.length || 5)) break;
512
+ let m = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
513
+ if (m && (m = decodeURIComponent(m)), m && o.add(m), o.size >= (p.length || 5)) break;
499
514
  }
500
- return i;
515
+ return o;
501
516
  }
502
517
  };
503
518
  export {
504
- X as Ai,
505
- L as Anthropic,
506
- I as CliTool,
507
- Y as DateTimeTool,
508
- Z as ExecTool,
509
- ee as FetchTool,
510
- N as JSTool,
519
+ Z as Ai,
520
+ R as Anthropic,
521
+ N as CliTool,
522
+ ee as DateTimeTool,
523
+ te as ExecTool,
524
+ ne as FetchTool,
525
+ z as JSTool,
511
526
  W as LLM,
512
- z as PythonTool,
513
- te as SearchTool
527
+ G as PythonTool,
528
+ se as SearchTool
514
529
  };
515
530
  //# sourceMappingURL=index.mjs.map