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