@ztimson/ai-utils 0.2.7 → 0.3.0
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/ai.d.ts +13 -5
- package/dist/antrhopic.d.ts +2 -2
- package/dist/audio.d.ts +5 -17
- package/dist/index.js +14 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +306 -278
- package/dist/index.mjs.map +1 -1
- package/dist/llm.d.ts +2 -2
- package/dist/ollama.d.ts +2 -2
- package/dist/open-ai.d.ts +2 -2
- package/dist/provider.d.ts +1 -3
- package/dist/vision.d.ts +3 -6
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -1,126 +1,127 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
|
|
1
|
+
import * as M from "node:os";
|
|
2
|
+
import { platform as E, arch as T } from "node:os";
|
|
3
|
+
import { deepCopy as A, objectMap as x, JSONAttemptParse as _, findByProp as j, JSONSanitize as k, Http as q, consoleInterceptor as O, fn as $, ASet as v } from "@ztimson/utils";
|
|
4
|
+
import { Anthropic as R } from "@anthropic-ai/sdk";
|
|
5
|
+
import { Ollama as L } from "ollama";
|
|
6
|
+
import { OpenAI as U } from "openai";
|
|
7
|
+
import { Worker as B } from "worker_threads";
|
|
8
|
+
import { fileURLToPath as W } from "url";
|
|
9
|
+
import { join as I, dirname as D } from "path";
|
|
10
|
+
import { spawn as P } from "node:child_process";
|
|
11
|
+
import b from "node:fs/promises";
|
|
12
|
+
import y from "node:path";
|
|
13
|
+
import { createWorker as N } from "tesseract.js";
|
|
14
|
+
import { $ as H, $Sync as J } from "@ztimson/node-utils";
|
|
15
|
+
class S {
|
|
15
16
|
}
|
|
16
|
-
class
|
|
17
|
-
constructor(t, e,
|
|
18
|
-
super(), this.ai = t, this.apiToken = e, this.model =
|
|
17
|
+
class F extends S {
|
|
18
|
+
constructor(t, e, n) {
|
|
19
|
+
super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new R({ apiKey: e });
|
|
19
20
|
}
|
|
20
21
|
client;
|
|
21
22
|
toStandard(t) {
|
|
22
23
|
for (let e = 0; e < t.length; e++) {
|
|
23
|
-
const
|
|
24
|
-
typeof t[
|
|
25
|
-
e++, t.splice(e, 0, { role: "tool", id:
|
|
26
|
-
}) : t[
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
}), t[
|
|
24
|
+
const n = e;
|
|
25
|
+
typeof t[n].content != "string" && (t[n].role == "assistant" ? t[n].content.filter((s) => s.type == "tool_use").forEach((s) => {
|
|
26
|
+
e++, t.splice(e, 0, { role: "tool", id: s.id, name: s.name, args: s.input, timestamp: Date.now() });
|
|
27
|
+
}) : t[n].role == "user" && t[n].content.filter((s) => s.type == "tool_result").forEach((s) => {
|
|
28
|
+
const r = t.find((l) => l.id == s.tool_use_id);
|
|
29
|
+
r[s.is_error ? "error" : "content"] = s.content;
|
|
30
|
+
}), t[n].content = t[n].content.filter((s) => s.type == "text").map((s) => s.text).join(`
|
|
30
31
|
|
|
31
|
-
`)), t[
|
|
32
|
+
`)), t[n].timestamp || (t[n].timestamp = Date.now());
|
|
32
33
|
}
|
|
33
34
|
return t.filter((e) => !!e.content);
|
|
34
35
|
}
|
|
35
36
|
fromStandard(t) {
|
|
36
37
|
for (let e = 0; e < t.length; e++)
|
|
37
38
|
if (t[e].role == "tool") {
|
|
38
|
-
const
|
|
39
|
+
const n = t[e];
|
|
39
40
|
t.splice(
|
|
40
41
|
e,
|
|
41
42
|
1,
|
|
42
|
-
{ role: "assistant", content: [{ type: "tool_use", id:
|
|
43
|
-
{ role: "user", content: [{ type: "tool_result", tool_use_id:
|
|
43
|
+
{ role: "assistant", content: [{ type: "tool_use", id: n.id, name: n.name, input: n.args }] },
|
|
44
|
+
{ role: "user", content: [{ type: "tool_result", tool_use_id: n.id, is_error: !!n.error, content: n.error || n.content }] }
|
|
44
45
|
), e++;
|
|
45
46
|
}
|
|
46
|
-
return t.map(({ timestamp: e, ...
|
|
47
|
+
return t.map(({ timestamp: e, ...n }) => n);
|
|
47
48
|
}
|
|
48
49
|
ask(t, e = {}) {
|
|
49
|
-
const
|
|
50
|
-
let
|
|
51
|
-
const
|
|
52
|
-
e.compress && (
|
|
53
|
-
const
|
|
50
|
+
const n = new AbortController(), s = new Promise(async (r, l) => {
|
|
51
|
+
let o = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
|
|
52
|
+
const d = A(o);
|
|
53
|
+
e.compress && (o = await this.ai.language.compressHistory(o, e.compress.max, e.compress.min, e));
|
|
54
|
+
const p = e.tools || this.ai.options.tools || [], a = {
|
|
54
55
|
model: e.model || this.model,
|
|
55
56
|
max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
|
|
56
57
|
system: e.system || this.ai.options.system || "",
|
|
57
58
|
temperature: e.temperature || this.ai.options.temperature || 0.7,
|
|
58
|
-
tools:
|
|
59
|
-
name:
|
|
60
|
-
description:
|
|
59
|
+
tools: p.map((i) => ({
|
|
60
|
+
name: i.name,
|
|
61
|
+
description: i.description,
|
|
61
62
|
input_schema: {
|
|
62
63
|
type: "object",
|
|
63
|
-
properties:
|
|
64
|
-
required:
|
|
64
|
+
properties: i.args ? x(i.args, (c, f) => ({ ...f, required: void 0 })) : {},
|
|
65
|
+
required: i.args ? Object.entries(i.args).filter((c) => c[1].required).map((c) => c[0]) : []
|
|
65
66
|
},
|
|
66
67
|
fn: void 0
|
|
67
68
|
})),
|
|
68
|
-
messages:
|
|
69
|
+
messages: o,
|
|
69
70
|
stream: !!e.stream
|
|
70
71
|
};
|
|
71
72
|
let m, h = !0;
|
|
72
73
|
do {
|
|
73
|
-
if (m = await this.client.messages.create(
|
|
74
|
-
throw
|
|
74
|
+
if (m = await this.client.messages.create(a).catch((c) => {
|
|
75
|
+
throw c.message += `
|
|
75
76
|
|
|
76
77
|
Messages:
|
|
77
|
-
${JSON.stringify(
|
|
78
|
+
${JSON.stringify(o, null, 2)}`, c;
|
|
78
79
|
}), e.stream) {
|
|
79
80
|
h ? h = !1 : e.stream({ text: `
|
|
80
81
|
|
|
81
82
|
` }), m.content = [];
|
|
82
|
-
for await (const
|
|
83
|
-
if (
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
else if (
|
|
87
|
-
if (
|
|
88
|
-
const f =
|
|
83
|
+
for await (const c of m) {
|
|
84
|
+
if (n.signal.aborted) break;
|
|
85
|
+
if (c.type === "content_block_start")
|
|
86
|
+
c.content_block.type === "text" ? m.content.push({ type: "text", text: "" }) : c.content_block.type === "tool_use" && m.content.push({ type: "tool_use", id: c.content_block.id, name: c.content_block.name, input: "" });
|
|
87
|
+
else if (c.type === "content_block_delta")
|
|
88
|
+
if (c.delta.type === "text_delta") {
|
|
89
|
+
const f = c.delta.text;
|
|
89
90
|
m.content.at(-1).text += f, e.stream({ text: f });
|
|
90
|
-
} else
|
|
91
|
-
else if (
|
|
91
|
+
} else c.delta.type === "input_json_delta" && (m.content.at(-1).input += c.delta.partial_json);
|
|
92
|
+
else if (c.type === "content_block_stop") {
|
|
92
93
|
const f = m.content.at(-1);
|
|
93
94
|
f.input != null && (f.input = f.input ? _(f.input, {}) : {});
|
|
94
|
-
} else if (
|
|
95
|
+
} else if (c.type === "message_stop")
|
|
95
96
|
break;
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
const g =
|
|
103
|
-
if (!g) return { tool_use_id: f.id, is_error: !0, content: "Tool not found" };
|
|
99
|
+
const i = m.content.filter((c) => c.type === "tool_use");
|
|
100
|
+
if (i.length && !n.signal.aborted) {
|
|
101
|
+
o.push({ role: "assistant", content: m.content }), d.push({ role: "assistant", content: m.content });
|
|
102
|
+
const c = await Promise.all(i.map(async (f) => {
|
|
103
|
+
const g = p.find(j("name", f.name));
|
|
104
|
+
if (e.stream && e.stream({ tool: f.name }), !g) return { tool_use_id: f.id, is_error: !0, content: "Tool not found" };
|
|
104
105
|
try {
|
|
105
106
|
const w = await g.fn(f.input, this.ai);
|
|
106
|
-
return { type: "tool_result", tool_use_id: f.id, content:
|
|
107
|
+
return { type: "tool_result", tool_use_id: f.id, content: k(w) };
|
|
107
108
|
} catch (w) {
|
|
108
109
|
return { type: "tool_result", tool_use_id: f.id, is_error: !0, content: w?.message || w?.toString() || "Unknown" };
|
|
109
110
|
}
|
|
110
111
|
}));
|
|
111
|
-
|
|
112
|
+
o.push({ role: "user", content: c }), a.messages = o;
|
|
112
113
|
}
|
|
113
|
-
} while (!
|
|
114
|
-
e.stream && e.stream({ done: !0 }),
|
|
114
|
+
} while (!n.signal.aborted && m.content.some((i) => i.type === "tool_use"));
|
|
115
|
+
e.stream && e.stream({ done: !0 }), r(this.toStandard([...o, { role: "assistant", content: m.content.filter((i) => i.type == "text").map((i) => i.text).join(`
|
|
115
116
|
|
|
116
117
|
`) }]));
|
|
117
118
|
});
|
|
118
|
-
return Object.assign(
|
|
119
|
+
return Object.assign(s, { abort: () => n.abort() });
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
|
-
class z extends
|
|
122
|
-
constructor(t, e,
|
|
123
|
-
super(), this.ai = t, this.host = e, this.model =
|
|
122
|
+
class z extends S {
|
|
123
|
+
constructor(t, e, n) {
|
|
124
|
+
super(), this.ai = t, this.host = e, this.model = n, this.client = new L({ host: e });
|
|
124
125
|
}
|
|
125
126
|
client;
|
|
126
127
|
toStandard(t) {
|
|
@@ -128,8 +129,8 @@ class z extends x {
|
|
|
128
129
|
if (t[e].role == "assistant" && t[e].tool_calls)
|
|
129
130
|
t[e].content ? delete t[e].tool_calls : (t.splice(e, 1), e--);
|
|
130
131
|
else if (t[e].role == "tool") {
|
|
131
|
-
const
|
|
132
|
-
t[e] = { role: "tool", name: t[e].tool_name, args: t[e].args, [
|
|
132
|
+
const n = t[e].content.startsWith('{"error":');
|
|
133
|
+
t[e] = { role: "tool", name: t[e].tool_name, args: t[e].args, [n ? "error" : "content"]: t[e].content, timestamp: t[e].timestamp };
|
|
133
134
|
}
|
|
134
135
|
t[e]?.timestamp || (t[e].timestamp = Date.now());
|
|
135
136
|
}
|
|
@@ -137,183 +138,183 @@ class z extends x {
|
|
|
137
138
|
}
|
|
138
139
|
fromStandard(t) {
|
|
139
140
|
return t.map((e) => {
|
|
140
|
-
const { timestamp:
|
|
141
|
-
return e.role != "tool" ?
|
|
141
|
+
const { timestamp: n, ...s } = e;
|
|
142
|
+
return e.role != "tool" ? s : { role: "tool", tool_name: e.name, content: e.error || e.content };
|
|
142
143
|
});
|
|
143
144
|
}
|
|
144
145
|
ask(t, e = {}) {
|
|
145
|
-
const
|
|
146
|
-
let
|
|
147
|
-
|
|
148
|
-
const
|
|
146
|
+
const n = new AbortController(), s = new Promise(async (r, l) => {
|
|
147
|
+
let o = e.system || this.ai.options.system, d = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
|
|
148
|
+
d[0].roll == "system" && (o ? d.shift() : o = d.shift()), e.compress && (d = await this.ai.language.compressHistory(d, e.compress.max, e.compress.min)), e.system && d.unshift({ role: "system", content: o });
|
|
149
|
+
const p = e.tools || this.ai.options.tools || [], a = {
|
|
149
150
|
model: e.model || this.model,
|
|
150
|
-
messages:
|
|
151
|
+
messages: d,
|
|
151
152
|
stream: !!e.stream,
|
|
152
|
-
signal:
|
|
153
|
+
signal: n.signal,
|
|
153
154
|
options: {
|
|
154
155
|
temperature: e.temperature || this.ai.options.temperature || 0.7,
|
|
155
156
|
num_predict: e.max_tokens || this.ai.options.max_tokens || 4096
|
|
156
157
|
},
|
|
157
|
-
tools:
|
|
158
|
+
tools: p.map((i) => ({
|
|
158
159
|
type: "function",
|
|
159
160
|
function: {
|
|
160
|
-
name:
|
|
161
|
-
description:
|
|
161
|
+
name: i.name,
|
|
162
|
+
description: i.description,
|
|
162
163
|
parameters: {
|
|
163
164
|
type: "object",
|
|
164
|
-
properties:
|
|
165
|
-
required:
|
|
165
|
+
properties: i.args ? x(i.args, (c, f) => ({ ...f, required: void 0 })) : {},
|
|
166
|
+
required: i.args ? Object.entries(i.args).filter((c) => c[1].required).map((c) => c[0]) : []
|
|
166
167
|
}
|
|
167
168
|
}
|
|
168
169
|
}))
|
|
169
170
|
};
|
|
170
171
|
let m, h = !0;
|
|
171
172
|
do {
|
|
172
|
-
if (m = await this.client.chat(
|
|
173
|
-
throw
|
|
173
|
+
if (m = await this.client.chat(a).catch((i) => {
|
|
174
|
+
throw i.message += `
|
|
174
175
|
|
|
175
176
|
Messages:
|
|
176
|
-
${JSON.stringify(
|
|
177
|
+
${JSON.stringify(d, null, 2)}`, i;
|
|
177
178
|
}), e.stream) {
|
|
178
179
|
h ? h = !1 : e.stream({ text: `
|
|
179
180
|
|
|
180
181
|
` }), m.message = { role: "assistant", content: "", tool_calls: [] };
|
|
181
|
-
for await (const
|
|
182
|
-
if (
|
|
182
|
+
for await (const i of m)
|
|
183
|
+
if (n.signal.aborted || (i.message?.content && (m.message.content += i.message.content, e.stream({ text: i.message.content })), i.message?.tool_calls && (m.message.tool_calls = i.message.tool_calls), i.done)) break;
|
|
183
184
|
}
|
|
184
|
-
if (m.message?.tool_calls?.length && !
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
const f =
|
|
188
|
-
if (!f) return { role: "tool", tool_name:
|
|
189
|
-
const g = typeof
|
|
185
|
+
if (m.message?.tool_calls?.length && !n.signal.aborted) {
|
|
186
|
+
d.push(m.message);
|
|
187
|
+
const i = await Promise.all(m.message.tool_calls.map(async (c) => {
|
|
188
|
+
const f = p.find(j("name", c.function.name));
|
|
189
|
+
if (e.stream && e.stream({ tool: c.function.name }), !f) return { role: "tool", tool_name: c.function.name, content: '{"error": "Tool not found"}' };
|
|
190
|
+
const g = typeof c.function.arguments == "string" ? _(c.function.arguments, {}) : c.function.arguments;
|
|
190
191
|
try {
|
|
191
192
|
const w = await f.fn(g, this.ai);
|
|
192
|
-
return { role: "tool", tool_name:
|
|
193
|
+
return { role: "tool", tool_name: c.function.name, args: g, content: k(w) };
|
|
193
194
|
} catch (w) {
|
|
194
|
-
return { role: "tool", tool_name:
|
|
195
|
+
return { role: "tool", tool_name: c.function.name, args: g, content: k({ error: w?.message || w?.toString() || "Unknown" }) };
|
|
195
196
|
}
|
|
196
197
|
}));
|
|
197
|
-
|
|
198
|
+
d.push(...i), a.messages = d;
|
|
198
199
|
}
|
|
199
|
-
} while (!
|
|
200
|
-
e.stream && e.stream({ done: !0 }),
|
|
200
|
+
} while (!n.signal.aborted && m.message?.tool_calls?.length);
|
|
201
|
+
e.stream && e.stream({ done: !0 }), r(this.toStandard([...d, { role: "assistant", content: m.message?.content }]));
|
|
201
202
|
});
|
|
202
|
-
return Object.assign(
|
|
203
|
+
return Object.assign(s, { abort: () => n.abort() });
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
|
-
class
|
|
206
|
-
constructor(t, e,
|
|
207
|
-
super(), this.ai = t, this.apiToken = e, this.model =
|
|
206
|
+
class G extends S {
|
|
207
|
+
constructor(t, e, n) {
|
|
208
|
+
super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new U({ apiKey: e });
|
|
208
209
|
}
|
|
209
210
|
client;
|
|
210
211
|
toStandard(t) {
|
|
211
212
|
for (let e = 0; e < t.length; e++) {
|
|
212
|
-
const
|
|
213
|
-
if (
|
|
214
|
-
const
|
|
213
|
+
const n = t[e];
|
|
214
|
+
if (n.role === "assistant" && n.tool_calls) {
|
|
215
|
+
const s = n.tool_calls.map((r) => ({
|
|
215
216
|
role: "tool",
|
|
216
|
-
id:
|
|
217
|
-
name:
|
|
218
|
-
args: _(
|
|
219
|
-
timestamp:
|
|
217
|
+
id: r.id,
|
|
218
|
+
name: r.function.name,
|
|
219
|
+
args: _(r.function.arguments, {}),
|
|
220
|
+
timestamp: n.timestamp
|
|
220
221
|
}));
|
|
221
|
-
t.splice(e, 1, ...
|
|
222
|
-
} else if (
|
|
223
|
-
const
|
|
224
|
-
|
|
222
|
+
t.splice(e, 1, ...s), e += s.length - 1;
|
|
223
|
+
} else if (n.role === "tool" && n.content) {
|
|
224
|
+
const s = t.find((r) => n.tool_call_id == r.id);
|
|
225
|
+
s && (n.content.includes('"error":') ? s.error = n.content : s.content = n.content), t.splice(e, 1), e--;
|
|
225
226
|
}
|
|
226
227
|
t[e]?.timestamp || (t[e].timestamp = Date.now());
|
|
227
228
|
}
|
|
228
229
|
return t;
|
|
229
230
|
}
|
|
230
231
|
fromStandard(t) {
|
|
231
|
-
return t.reduce((e,
|
|
232
|
-
if (
|
|
232
|
+
return t.reduce((e, n) => {
|
|
233
|
+
if (n.role === "tool")
|
|
233
234
|
e.push({
|
|
234
235
|
role: "assistant",
|
|
235
236
|
content: null,
|
|
236
|
-
tool_calls: [{ id:
|
|
237
|
+
tool_calls: [{ id: n.id, type: "function", function: { name: n.name, arguments: JSON.stringify(n.args) } }],
|
|
237
238
|
refusal: null,
|
|
238
239
|
annotations: []
|
|
239
240
|
}, {
|
|
240
241
|
role: "tool",
|
|
241
|
-
tool_call_id:
|
|
242
|
-
content:
|
|
242
|
+
tool_call_id: n.id,
|
|
243
|
+
content: n.error || n.content
|
|
243
244
|
});
|
|
244
245
|
else {
|
|
245
|
-
const { timestamp:
|
|
246
|
-
e.push(
|
|
246
|
+
const { timestamp: s, ...r } = n;
|
|
247
|
+
e.push(r);
|
|
247
248
|
}
|
|
248
249
|
return e;
|
|
249
250
|
}, []);
|
|
250
251
|
}
|
|
251
252
|
ask(t, e = {}) {
|
|
252
|
-
const
|
|
253
|
-
let
|
|
254
|
-
e.compress && (
|
|
255
|
-
const
|
|
253
|
+
const n = new AbortController(), s = new Promise(async (r, l) => {
|
|
254
|
+
let o = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
|
|
255
|
+
e.compress && (o = await this.ai.language.compressHistory(o, e.compress.max, e.compress.min, e));
|
|
256
|
+
const d = e.tools || this.ai.options.tools || [], p = {
|
|
256
257
|
model: e.model || this.model,
|
|
257
|
-
messages:
|
|
258
|
+
messages: o,
|
|
258
259
|
stream: !!e.stream,
|
|
259
260
|
max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
|
|
260
261
|
temperature: e.temperature || this.ai.options.temperature || 0.7,
|
|
261
|
-
tools:
|
|
262
|
+
tools: d.map((h) => ({
|
|
262
263
|
type: "function",
|
|
263
264
|
function: {
|
|
264
265
|
name: h.name,
|
|
265
266
|
description: h.description,
|
|
266
267
|
parameters: {
|
|
267
268
|
type: "object",
|
|
268
|
-
properties: h.args ?
|
|
269
|
-
required: h.args ? Object.entries(h.args).filter((
|
|
269
|
+
properties: h.args ? x(h.args, (i, c) => ({ ...c, required: void 0 })) : {},
|
|
270
|
+
required: h.args ? Object.entries(h.args).filter((i) => i[1].required).map((i) => i[0]) : []
|
|
270
271
|
}
|
|
271
272
|
}
|
|
272
273
|
}))
|
|
273
274
|
};
|
|
274
|
-
let
|
|
275
|
+
let a, m = !0;
|
|
275
276
|
do {
|
|
276
|
-
if (
|
|
277
|
-
throw
|
|
277
|
+
if (a = await this.client.chat.completions.create(p).catch((i) => {
|
|
278
|
+
throw i.message += `
|
|
278
279
|
|
|
279
280
|
Messages:
|
|
280
|
-
${JSON.stringify(
|
|
281
|
+
${JSON.stringify(o, null, 2)}`, i;
|
|
281
282
|
}), e.stream) {
|
|
282
283
|
m ? m = !1 : e.stream({ text: `
|
|
283
284
|
|
|
284
|
-
` }),
|
|
285
|
-
for await (const
|
|
286
|
-
if (
|
|
287
|
-
|
|
285
|
+
` }), a.choices = [{ message: { content: "", tool_calls: [] } }];
|
|
286
|
+
for await (const i of a) {
|
|
287
|
+
if (n.signal.aborted) break;
|
|
288
|
+
i.choices[0].delta.content && (a.choices[0].message.content += i.choices[0].delta.content, e.stream({ text: i.choices[0].delta.content })), i.choices[0].delta.tool_calls && (a.choices[0].message.tool_calls = i.choices[0].delta.tool_calls);
|
|
288
289
|
}
|
|
289
290
|
}
|
|
290
|
-
const h =
|
|
291
|
-
if (h.length && !
|
|
292
|
-
|
|
293
|
-
const
|
|
294
|
-
const f =
|
|
295
|
-
if (!f) return { role: "tool", tool_call_id:
|
|
291
|
+
const h = a.choices[0].message.tool_calls || [];
|
|
292
|
+
if (h.length && !n.signal.aborted) {
|
|
293
|
+
o.push(a.choices[0].message);
|
|
294
|
+
const i = await Promise.all(h.map(async (c) => {
|
|
295
|
+
const f = d?.find(j("name", c.function.name));
|
|
296
|
+
if (e.stream && e.stream({ tool: c.function.name }), !f) return { role: "tool", tool_call_id: c.id, content: '{"error": "Tool not found"}' };
|
|
296
297
|
try {
|
|
297
|
-
const g = _(
|
|
298
|
-
return { role: "tool", tool_call_id:
|
|
298
|
+
const g = _(c.function.arguments, {}), w = await f.fn(g, this.ai);
|
|
299
|
+
return { role: "tool", tool_call_id: c.id, content: k(w) };
|
|
299
300
|
} catch (g) {
|
|
300
|
-
return { role: "tool", tool_call_id:
|
|
301
|
+
return { role: "tool", tool_call_id: c.id, content: k({ error: g?.message || g?.toString() || "Unknown" }) };
|
|
301
302
|
}
|
|
302
303
|
}));
|
|
303
|
-
|
|
304
|
+
o.push(...i), p.messages = o;
|
|
304
305
|
}
|
|
305
|
-
} while (!
|
|
306
|
-
e.stream && e.stream({ done: !0 }),
|
|
306
|
+
} while (!n.signal.aborted && a.choices?.[0]?.message?.tool_calls?.length);
|
|
307
|
+
e.stream && e.stream({ done: !0 }), r(this.toStandard([...o, { role: "assistant", content: a.choices[0].message.content || "" }]));
|
|
307
308
|
});
|
|
308
|
-
return Object.assign(
|
|
309
|
+
return Object.assign(s, { abort: () => n.abort() });
|
|
309
310
|
}
|
|
310
311
|
}
|
|
311
|
-
class
|
|
312
|
+
class Q {
|
|
312
313
|
constructor(t) {
|
|
313
|
-
this.ai = t, this.embedWorker = new
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
}), t.options.anthropic?.token && (this.providers.anthropic = new
|
|
314
|
+
this.ai = t, this.embedWorker = new B(I(D(W(import.meta.url)), "embedder.js")), this.embedWorker.on("message", ({ id: e, embedding: n }) => {
|
|
315
|
+
const s = this.embedQueue.get(e);
|
|
316
|
+
s && (s.resolve(n), this.embedQueue.delete(e));
|
|
317
|
+
}), t.options.anthropic?.token && (this.providers.anthropic = new F(this.ai, t.options.anthropic.token, t.options.anthropic.model)), t.options.ollama?.host && (this.providers.ollama = new z(this.ai, t.options.ollama.host, t.options.ollama.model)), t.options.openAi?.token && (this.providers.openAi = new G(this.ai, t.options.openAi.token, t.options.openAi.model));
|
|
317
318
|
}
|
|
318
319
|
embedWorker = null;
|
|
319
320
|
embedQueue = /* @__PURE__ */ new Map();
|
|
@@ -326,9 +327,9 @@ class G {
|
|
|
326
327
|
* @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history
|
|
327
328
|
*/
|
|
328
329
|
ask(t, e = {}) {
|
|
329
|
-
let
|
|
330
|
-
if (e.model && (typeof e.model == "object" ?
|
|
331
|
-
return this.providers[
|
|
330
|
+
let n = [null, null];
|
|
331
|
+
if (e.model && (typeof e.model == "object" ? n = e.model : n = [e.model, this.ai.options[e.model]?.model]), (!e.model || n[1] == null) && (typeof this.ai.options.model == "object" ? n = this.ai.options.model : n = [this.ai.options.model, this.ai.options[this.ai.options.model]?.model]), !n[0] || !n[1]) throw new Error(`Unknown LLM provider or model: ${n[0]} / ${n[1]}`);
|
|
332
|
+
return this.providers[n[0]].ask(t, { ...e, model: n[1] });
|
|
332
333
|
}
|
|
333
334
|
/**
|
|
334
335
|
* Compress chat history to reduce context size
|
|
@@ -338,57 +339,57 @@ class G {
|
|
|
338
339
|
* @param {LLMRequest} options LLM options
|
|
339
340
|
* @returns {Promise<LLMMessage[]>} New chat history will summary at index 0
|
|
340
341
|
*/
|
|
341
|
-
async compressHistory(t, e,
|
|
342
|
+
async compressHistory(t, e, n, s) {
|
|
342
343
|
if (this.estimateTokens(t) < e) return t;
|
|
343
|
-
let
|
|
344
|
-
for (let
|
|
345
|
-
if (
|
|
344
|
+
let r = 0, l = 0;
|
|
345
|
+
for (let a of t.toReversed())
|
|
346
|
+
if (l += this.estimateTokens(a.content), l < n) r++;
|
|
346
347
|
else break;
|
|
347
|
-
if (t.length <=
|
|
348
|
-
const
|
|
349
|
-
return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(
|
|
348
|
+
if (t.length <= r) return t;
|
|
349
|
+
const o = r == 0 ? [] : t.slice(-r), d = (r == 0 ? t : t.slice(0, -r)).filter((a) => a.role === "assistant" || a.role === "user");
|
|
350
|
+
return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(d.map((a) => `${a.role}: ${a.content}`).join(`
|
|
350
351
|
|
|
351
|
-
`), 250,
|
|
352
|
+
`), 250, s)}`, timestamp: Date.now() }, ...o];
|
|
352
353
|
}
|
|
353
354
|
cosineSimilarity(t, e) {
|
|
354
355
|
if (t.length !== e.length) throw new Error("Vectors must be same length");
|
|
355
|
-
let
|
|
356
|
-
for (let
|
|
357
|
-
|
|
358
|
-
const
|
|
359
|
-
return
|
|
360
|
-
}
|
|
361
|
-
chunk(t, e = 500,
|
|
362
|
-
const
|
|
363
|
-
const h =
|
|
364
|
-
return typeof m == "object" && !Array.isArray(m) ?
|
|
365
|
-
}) : [],
|
|
366
|
-
`)).flatMap((
|
|
367
|
-
`]),
|
|
368
|
-
for (let
|
|
369
|
-
let
|
|
370
|
-
for (;
|
|
371
|
-
const h =
|
|
356
|
+
let n = 0, s = 0, r = 0;
|
|
357
|
+
for (let o = 0; o < t.length; o++)
|
|
358
|
+
n += t[o] * e[o], s += t[o] * t[o], r += e[o] * e[o];
|
|
359
|
+
const l = Math.sqrt(s) * Math.sqrt(r);
|
|
360
|
+
return l === 0 ? 0 : n / l;
|
|
361
|
+
}
|
|
362
|
+
chunk(t, e = 500, n = 50) {
|
|
363
|
+
const s = (d, p = "") => d ? Object.entries(d).flatMap(([a, m]) => {
|
|
364
|
+
const h = p ? `${p}${isNaN(+a) ? `.${a}` : `[${a}]`}` : a;
|
|
365
|
+
return typeof m == "object" && !Array.isArray(m) ? s(m, h) : `${h}: ${Array.isArray(m) ? m.join(", ") : m}`;
|
|
366
|
+
}) : [], l = (typeof t == "object" ? s(t) : t.split(`
|
|
367
|
+
`)).flatMap((d) => [...d.split(/\s+/).filter(Boolean), `
|
|
368
|
+
`]), o = [];
|
|
369
|
+
for (let d = 0; d < l.length; ) {
|
|
370
|
+
let p = "", a = d;
|
|
371
|
+
for (; a < l.length; ) {
|
|
372
|
+
const h = p + (p ? " " : "") + l[a];
|
|
372
373
|
if (this.estimateTokens(h.replace(/\s*\n\s*/g, `
|
|
373
|
-
`)) > e &&
|
|
374
|
-
|
|
374
|
+
`)) > e && p) break;
|
|
375
|
+
p = h, a++;
|
|
375
376
|
}
|
|
376
|
-
const m =
|
|
377
|
+
const m = p.replace(/\s*\n\s*/g, `
|
|
377
378
|
`).trim();
|
|
378
|
-
m &&
|
|
379
|
+
m && o.push(m), d = Math.max(a - n, a === d ? d + 1 : a);
|
|
379
380
|
}
|
|
380
|
-
return
|
|
381
|
-
}
|
|
382
|
-
embedding(t, e = 500,
|
|
383
|
-
const
|
|
384
|
-
const
|
|
385
|
-
this.embedQueue.set(
|
|
386
|
-
}),
|
|
387
|
-
return Promise.all(
|
|
388
|
-
index:
|
|
389
|
-
embedding: await
|
|
390
|
-
text:
|
|
391
|
-
tokens: this.estimateTokens(
|
|
381
|
+
return o;
|
|
382
|
+
}
|
|
383
|
+
embedding(t, e = 500, n = 50) {
|
|
384
|
+
const s = (l) => new Promise((o, d) => {
|
|
385
|
+
const p = this.embedId++;
|
|
386
|
+
this.embedQueue.set(p, { resolve: o, reject: d }), this.embedWorker?.postMessage({ id: p, text: l });
|
|
387
|
+
}), r = this.chunk(t, e, n);
|
|
388
|
+
return Promise.all(r.map(async (l, o) => ({
|
|
389
|
+
index: o,
|
|
390
|
+
embedding: await s(l),
|
|
391
|
+
text: l,
|
|
392
|
+
tokens: this.estimateTokens(l)
|
|
392
393
|
})));
|
|
393
394
|
}
|
|
394
395
|
/**
|
|
@@ -408,8 +409,8 @@ class G {
|
|
|
408
409
|
*/
|
|
409
410
|
fuzzyMatch(t, ...e) {
|
|
410
411
|
if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
|
|
411
|
-
const
|
|
412
|
-
return { avg:
|
|
412
|
+
const n = (l, o = 10) => l.toLowerCase().split("").map((d, p) => d.charCodeAt(0) * (p + 1) % o / o).slice(0, o), s = n(t), r = e.map((l) => n(l)).map((l) => this.cosineSimilarity(s, l));
|
|
413
|
+
return { avg: r.reduce((l, o) => l + o, 0) / r.length, max: Math.max(...r), similarities: r };
|
|
413
414
|
}
|
|
414
415
|
/**
|
|
415
416
|
* Ask a question with JSON response
|
|
@@ -418,11 +419,11 @@ class G {
|
|
|
418
419
|
* @returns {Promise<{} | {} | RegExpExecArray | null>}
|
|
419
420
|
*/
|
|
420
421
|
async json(t, e) {
|
|
421
|
-
let
|
|
422
|
+
let n = await this.ask(t, {
|
|
422
423
|
system: "Respond using a JSON blob",
|
|
423
424
|
...e
|
|
424
425
|
});
|
|
425
|
-
return
|
|
426
|
+
return n?.[0]?.content ? _(new RegExp("{[sS]*}").exec(n[0].content), {}) : {};
|
|
426
427
|
}
|
|
427
428
|
/**
|
|
428
429
|
* Create a summary of some text
|
|
@@ -431,75 +432,102 @@ class G {
|
|
|
431
432
|
* @param options LLM request options
|
|
432
433
|
* @returns {Promise<string>} Summary
|
|
433
434
|
*/
|
|
434
|
-
summarize(t, e,
|
|
435
|
-
return this.ask(t, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...
|
|
435
|
+
summarize(t, e, n) {
|
|
436
|
+
return this.ask(t, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...n }).then((s) => s.pop()?.content || null);
|
|
436
437
|
}
|
|
437
438
|
}
|
|
438
|
-
class
|
|
439
|
+
class C {
|
|
439
440
|
constructor(t) {
|
|
440
|
-
this.ai = t, t.options.whisper?.binary && (this.whisperModel = t.options.whisper?.model.endsWith(".bin") ? t.options.whisper?.model : t.options.whisper?.model + ".bin", this.downloadAsrModel())
|
|
441
|
+
if (this.ai = t, t.options.whisper?.binary && (this.whisperModel = t.options.whisper?.model.endsWith(".bin") ? t.options.whisper?.model : t.options.whisper?.model + ".bin", this.downloadAsrModel()), t.options.piper?.model) {
|
|
442
|
+
if (!t.options.piper.model.startsWith("http") || !t.options.piper.model.endsWith(".onnx"))
|
|
443
|
+
throw new Error("Piper model should be a URL to an onnx file to download");
|
|
444
|
+
if (E() != "linux" || T() != "x64" && T() != "arm64")
|
|
445
|
+
throw new Error("Piper TTS only supported on Linux x64/arm64");
|
|
446
|
+
this.piperBinary = y.join(import.meta.dirname, "../bin/piper"), this.downloadTtsModel();
|
|
447
|
+
}
|
|
441
448
|
}
|
|
442
449
|
downloads = {};
|
|
443
450
|
whisperModel;
|
|
444
|
-
|
|
445
|
-
* Convert audio to text using Auditory Speech Recognition
|
|
446
|
-
* @param {string} path Path to audio
|
|
447
|
-
* @param model Whisper model
|
|
448
|
-
* @returns {Promise<any>} Extracted text
|
|
449
|
-
*/
|
|
451
|
+
piperBinary;
|
|
450
452
|
asr(t, e = this.whisperModel) {
|
|
451
453
|
if (!this.ai.options.whisper?.binary) throw new Error("Whisper not configured");
|
|
454
|
+
let n = () => {
|
|
455
|
+
};
|
|
456
|
+
const s = new Promise(async (r, l) => {
|
|
457
|
+
const o = await this.downloadAsrModel(e);
|
|
458
|
+
let d = "";
|
|
459
|
+
const p = P(this.ai.options.whisper?.binary, ["-nt", "-np", "-m", o, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
|
|
460
|
+
n = () => p.kill("SIGTERM"), p.on("error", (a) => l(a)), p.stdout.on("data", (a) => d += a.toString()), p.on("close", (a) => {
|
|
461
|
+
a === 0 ? r(d.trim() || null) : l(new Error(`Exit code ${a}`));
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
return Object.assign(s, { abort: n });
|
|
465
|
+
}
|
|
466
|
+
tts(t, e, n = this.ai.options.piper?.model) {
|
|
467
|
+
if (!this.piperBinary) throw new Error("Piper not configured");
|
|
468
|
+
if (!n) throw new Error("Invalid Piper model");
|
|
452
469
|
let s = () => {
|
|
453
470
|
};
|
|
454
|
-
|
|
455
|
-
this.
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
s = () => u.kill("SIGTERM"), u.on("error", (c) => d(c)), u.stdout.on("data", (c) => l += c.toString()), u.on("close", (c) => {
|
|
459
|
-
c === 0 ? i(l.trim() || null) : d(new Error(`Exit code ${c}`));
|
|
460
|
-
});
|
|
471
|
+
const r = new Promise(async (l, o) => {
|
|
472
|
+
const d = await this.downloadTtsModel(n), p = e || y.join(M.tmpdir(), `piper_${Date.now()}.wav`), a = P(this.piperBinary, ["--model", d, "--output_file", p], {
|
|
473
|
+
stdio: ["pipe", "ignore", "ignore"],
|
|
474
|
+
env: { ...process.env, LD_LIBRARY_PATH: y.dirname(this.piperBinary) }
|
|
461
475
|
});
|
|
462
|
-
|
|
476
|
+
s = () => a.kill("SIGTERM"), a.stdin.write(t), a.stdin.end(), a.on("error", (m) => o(m)), a.on("close", async (m) => {
|
|
477
|
+
if (m === 0)
|
|
478
|
+
if (e)
|
|
479
|
+
l(e);
|
|
480
|
+
else {
|
|
481
|
+
const h = await b.readFile(p);
|
|
482
|
+
await b.unlink(p).catch(() => {
|
|
483
|
+
}), l(h);
|
|
484
|
+
}
|
|
485
|
+
else
|
|
486
|
+
o(new Error(`Exit code ${m}`));
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
return Object.assign(r, { abort: s });
|
|
463
490
|
}
|
|
464
|
-
/**
|
|
465
|
-
* Downloads the specified Whisper model if it is not already present locally.
|
|
466
|
-
*
|
|
467
|
-
* @param {string} model Whisper model that will be downloaded
|
|
468
|
-
* @return {Promise<string>} Absolute path to model file, resolves once downloaded
|
|
469
|
-
*/
|
|
470
491
|
async downloadAsrModel(t = this.whisperModel) {
|
|
471
492
|
if (!this.ai.options.whisper?.binary) throw new Error("Whisper not configured");
|
|
472
493
|
t.endsWith(".bin") || (t += ".bin");
|
|
473
|
-
const e =
|
|
474
|
-
return await
|
|
494
|
+
const e = y.join(this.ai.options.path, t);
|
|
495
|
+
return await b.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 b.writeFile(e, n), delete this.downloads[t], e)), this.downloads[t]);
|
|
496
|
+
}
|
|
497
|
+
async downloadTtsModel(t = this.ai.options.piper?.model) {
|
|
498
|
+
if (!t) throw new Error("Invalid Piper model");
|
|
499
|
+
const e = t.split("/").pop(), n = y.join(this.ai.options.path, e), [s, r] = await Promise.all([
|
|
500
|
+
b.stat(n).then(() => !0).catch(() => !1),
|
|
501
|
+
b.stat(n + ".json").then(() => !0).catch(() => !1)
|
|
502
|
+
]);
|
|
503
|
+
return s && r ? n : this.downloads[e] ? this.downloads[e] : (this.downloads[e] = Promise.all([
|
|
504
|
+
s ? Promise.resolve() : fetch(t).then((l) => l.arrayBuffer()).then((l) => b.writeFile(n, Buffer.from(l))),
|
|
505
|
+
r ? Promise.resolve() : fetch(t + ".json").then((l) => l.arrayBuffer()).then((l) => b.writeFile(n + ".json", Buffer.from(l)))
|
|
506
|
+
]).then(() => (delete this.downloads[e], n)), this.downloads[e]);
|
|
475
507
|
}
|
|
476
508
|
}
|
|
477
|
-
class
|
|
509
|
+
class K {
|
|
478
510
|
constructor(t) {
|
|
479
511
|
this.ai = t;
|
|
480
512
|
}
|
|
481
513
|
/**
|
|
482
514
|
* Convert image to text using Optical Character Recognition
|
|
483
515
|
* @param {string} path Path to image
|
|
484
|
-
* @returns {
|
|
516
|
+
* @returns {AbortablePromise<string | null>} Promise of extracted text with abort method
|
|
485
517
|
*/
|
|
486
518
|
ocr(t) {
|
|
487
519
|
let e;
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
const { data: n } = await e.recognize(t);
|
|
495
|
-
await e.terminate(), s(n.text.trim() || null);
|
|
496
|
-
})
|
|
497
|
-
};
|
|
520
|
+
const n = new Promise(async (s) => {
|
|
521
|
+
e = await N(this.ai.options.tesseract?.model || "eng", 2, { cachePath: this.ai.options.path });
|
|
522
|
+
const { data: r } = await e.recognize(t);
|
|
523
|
+
await e.terminate(), s(r.text.trim() || null);
|
|
524
|
+
});
|
|
525
|
+
return Object.assign(n, { abort: () => e?.terminate() });
|
|
498
526
|
}
|
|
499
527
|
}
|
|
500
|
-
class
|
|
528
|
+
class pe {
|
|
501
529
|
constructor(t) {
|
|
502
|
-
this.options = t, t.path || (t.path =
|
|
530
|
+
this.options = t, t.path || (t.path = M.tmpdir()), process.env.TRANSFORMERS_CACHE = t.path, this.audio = new C(this), this.language = new Q(this), this.vision = new K(this);
|
|
503
531
|
}
|
|
504
532
|
/** Audio processing AI */
|
|
505
533
|
audio;
|
|
@@ -508,38 +536,38 @@ class le {
|
|
|
508
536
|
/** Vision processing AI */
|
|
509
537
|
vision;
|
|
510
538
|
}
|
|
511
|
-
const
|
|
539
|
+
const V = {
|
|
512
540
|
name: "cli",
|
|
513
541
|
description: "Use the command line interface, returns any output",
|
|
514
542
|
args: { command: { type: "string", description: "Command to run", required: !0 } },
|
|
515
|
-
fn: (
|
|
516
|
-
},
|
|
543
|
+
fn: (u) => H`${u.command}`
|
|
544
|
+
}, ue = {
|
|
517
545
|
name: "get_datetime",
|
|
518
546
|
description: "Get current date and time",
|
|
519
547
|
args: {},
|
|
520
548
|
fn: async () => (/* @__PURE__ */ new Date()).toISOString()
|
|
521
|
-
},
|
|
549
|
+
}, fe = {
|
|
522
550
|
name: "exec",
|
|
523
551
|
description: "Run code/scripts",
|
|
524
552
|
args: {
|
|
525
553
|
language: { type: "string", description: "Execution language", enum: ["cli", "node", "python"], required: !0 },
|
|
526
554
|
code: { type: "string", description: "Code to execute", required: !0 }
|
|
527
555
|
},
|
|
528
|
-
fn: async (
|
|
556
|
+
fn: async (u, t) => {
|
|
529
557
|
try {
|
|
530
|
-
switch (
|
|
558
|
+
switch (u.type) {
|
|
531
559
|
case "bash":
|
|
532
|
-
return await
|
|
560
|
+
return await V.fn({ command: u.code }, t);
|
|
533
561
|
case "node":
|
|
534
|
-
return await
|
|
562
|
+
return await Y.fn({ code: u.code }, t);
|
|
535
563
|
case "python":
|
|
536
|
-
return await
|
|
564
|
+
return await X.fn({ code: u.code }, t);
|
|
537
565
|
}
|
|
538
566
|
} catch (e) {
|
|
539
567
|
return { error: e?.message || e.toString() };
|
|
540
568
|
}
|
|
541
569
|
}
|
|
542
|
-
},
|
|
570
|
+
}, he = {
|
|
543
571
|
name: "fetch",
|
|
544
572
|
description: "Make HTTP request to URL",
|
|
545
573
|
args: {
|
|
@@ -548,54 +576,54 @@ const Q = {
|
|
|
548
576
|
headers: { type: "object", description: "HTTP headers to send", default: {} },
|
|
549
577
|
body: { type: "object", description: "HTTP body to send" }
|
|
550
578
|
},
|
|
551
|
-
fn: (
|
|
552
|
-
},
|
|
579
|
+
fn: (u) => new q({ url: u.url, headers: u.headers }).request({ method: u.method || "GET", body: u.body })
|
|
580
|
+
}, Y = {
|
|
553
581
|
name: "exec_javascript",
|
|
554
582
|
description: "Execute commonjs javascript",
|
|
555
583
|
args: {
|
|
556
584
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
557
585
|
},
|
|
558
|
-
fn: async (
|
|
559
|
-
const t =
|
|
586
|
+
fn: async (u) => {
|
|
587
|
+
const t = O(null), e = await $({ console: t }, u.code, !0).catch((n) => t.output.error.push(n));
|
|
560
588
|
return { ...t.output, return: e, stdout: void 0, stderr: void 0 };
|
|
561
589
|
}
|
|
562
|
-
},
|
|
590
|
+
}, X = {
|
|
563
591
|
name: "exec_javascript",
|
|
564
592
|
description: "Execute commonjs javascript",
|
|
565
593
|
args: {
|
|
566
594
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
567
595
|
},
|
|
568
|
-
fn: async (
|
|
569
|
-
},
|
|
596
|
+
fn: async (u) => ({ result: J`python -c "${u.code}"` })
|
|
597
|
+
}, ge = {
|
|
570
598
|
name: "search",
|
|
571
599
|
description: "Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",
|
|
572
600
|
args: {
|
|
573
601
|
query: { type: "string", description: "Search string", required: !0 },
|
|
574
602
|
length: { type: "string", description: "Number of results to return", default: 5 }
|
|
575
603
|
},
|
|
576
|
-
fn: async (
|
|
577
|
-
const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(
|
|
604
|
+
fn: async (u) => {
|
|
605
|
+
const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(u.query)}`, {
|
|
578
606
|
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
|
|
579
|
-
}).then((
|
|
580
|
-
let e,
|
|
581
|
-
const
|
|
582
|
-
for (; (e =
|
|
583
|
-
let
|
|
584
|
-
if (
|
|
607
|
+
}).then((r) => r.text());
|
|
608
|
+
let e, n = /<a .*?href="(.+?)".+?<\/a>/g;
|
|
609
|
+
const s = new v();
|
|
610
|
+
for (; (e = n.exec(t)) !== null; ) {
|
|
611
|
+
let r = /uddg=(.+)&?/.exec(decodeURIComponent(e[1]))?.[1];
|
|
612
|
+
if (r && (r = decodeURIComponent(r)), r && s.add(r), s.size >= (u.length || 5)) break;
|
|
585
613
|
}
|
|
586
|
-
return
|
|
614
|
+
return s;
|
|
587
615
|
}
|
|
588
616
|
};
|
|
589
617
|
export {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
618
|
+
pe as Ai,
|
|
619
|
+
F as Anthropic,
|
|
620
|
+
V as CliTool,
|
|
621
|
+
ue as DateTimeTool,
|
|
622
|
+
fe as ExecTool,
|
|
623
|
+
he as FetchTool,
|
|
624
|
+
Y as JSTool,
|
|
625
|
+
Q as LLM,
|
|
626
|
+
X as PythonTool,
|
|
627
|
+
ge as SearchTool
|
|
600
628
|
};
|
|
601
629
|
//# sourceMappingURL=index.mjs.map
|