@ztimson/ai-utils 0.2.6 → 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 +321 -292
- package/dist/index.mjs.map +1 -1
- package/dist/llm.d.ts +3 -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
|
-
let
|
|
72
|
+
let m, h = !0;
|
|
72
73
|
do {
|
|
73
|
-
if (
|
|
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
|
-
for await (const
|
|
83
|
-
if (
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
else if (
|
|
87
|
-
if (
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
} else
|
|
91
|
-
else if (
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
} else if (
|
|
82
|
+
` }), m.content = [];
|
|
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;
|
|
90
|
+
m.content.at(-1).text += f, e.stream({ text: f });
|
|
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") {
|
|
93
|
+
const f = m.content.at(-1);
|
|
94
|
+
f.input != null && (f.input = f.input ? _(f.input, {}) : {});
|
|
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:
|
|
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
|
-
const w = await g.fn(
|
|
106
|
-
return { type: "tool_result", tool_use_id:
|
|
106
|
+
const w = await g.fn(f.input, this.ai);
|
|
107
|
+
return { type: "tool_result", tool_use_id: f.id, content: k(w) };
|
|
107
108
|
} catch (w) {
|
|
108
|
-
return { type: "tool_result", tool_use_id:
|
|
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
|
-
let
|
|
171
|
+
let m, h = !0;
|
|
171
172
|
do {
|
|
172
|
-
if (
|
|
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
|
-
for await (const
|
|
182
|
-
if (
|
|
181
|
+
` }), m.message = { role: "assistant", content: "", tool_calls: [] };
|
|
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 (
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
if (!
|
|
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
|
-
const w = await
|
|
192
|
-
return { role: "tool", tool_name:
|
|
192
|
+
const w = await f.fn(g, this.ai);
|
|
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
|
-
name:
|
|
265
|
-
description:
|
|
265
|
+
name: h.name,
|
|
266
|
+
description: h.description,
|
|
266
267
|
parameters: {
|
|
267
268
|
type: "object",
|
|
268
|
-
properties:
|
|
269
|
-
required:
|
|
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
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
if (!
|
|
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,56 +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
|
-
|
|
362
|
-
const
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
let i = h, l = "";
|
|
376
|
-
for (; i < a.length; ) {
|
|
377
|
-
const n = a[i], r = l + (l ? " " : "") + n;
|
|
378
|
-
if (this.estimateTokens(r.replace(/\s*\n\s*/g, `
|
|
379
|
-
`)) > e && l) break;
|
|
380
|
-
l = r, i++;
|
|
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];
|
|
373
|
+
if (this.estimateTokens(h.replace(/\s*\n\s*/g, `
|
|
374
|
+
`)) > e && p) break;
|
|
375
|
+
p = h, a++;
|
|
381
376
|
}
|
|
382
|
-
const
|
|
377
|
+
const m = p.replace(/\s*\n\s*/g, `
|
|
383
378
|
`).trim();
|
|
384
|
-
|
|
379
|
+
m && o.push(m), d = Math.max(a - n, a === d ? d + 1 : a);
|
|
385
380
|
}
|
|
386
|
-
return
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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)
|
|
391
393
|
})));
|
|
392
394
|
}
|
|
393
395
|
/**
|
|
@@ -407,8 +409,8 @@ class G {
|
|
|
407
409
|
*/
|
|
408
410
|
fuzzyMatch(t, ...e) {
|
|
409
411
|
if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
|
|
410
|
-
const
|
|
411
|
-
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 };
|
|
412
414
|
}
|
|
413
415
|
/**
|
|
414
416
|
* Ask a question with JSON response
|
|
@@ -417,11 +419,11 @@ class G {
|
|
|
417
419
|
* @returns {Promise<{} | {} | RegExpExecArray | null>}
|
|
418
420
|
*/
|
|
419
421
|
async json(t, e) {
|
|
420
|
-
let
|
|
422
|
+
let n = await this.ask(t, {
|
|
421
423
|
system: "Respond using a JSON blob",
|
|
422
424
|
...e
|
|
423
425
|
});
|
|
424
|
-
return
|
|
426
|
+
return n?.[0]?.content ? _(new RegExp("{[sS]*}").exec(n[0].content), {}) : {};
|
|
425
427
|
}
|
|
426
428
|
/**
|
|
427
429
|
* Create a summary of some text
|
|
@@ -430,75 +432,102 @@ class G {
|
|
|
430
432
|
* @param options LLM request options
|
|
431
433
|
* @returns {Promise<string>} Summary
|
|
432
434
|
*/
|
|
433
|
-
summarize(t, e,
|
|
434
|
-
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);
|
|
435
437
|
}
|
|
436
438
|
}
|
|
437
439
|
class C {
|
|
438
440
|
constructor(t) {
|
|
439
|
-
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
|
+
}
|
|
440
448
|
}
|
|
441
449
|
downloads = {};
|
|
442
450
|
whisperModel;
|
|
443
|
-
|
|
444
|
-
* Convert audio to text using Auditory Speech Recognition
|
|
445
|
-
* @param {string} path Path to audio
|
|
446
|
-
* @param model Whisper model
|
|
447
|
-
* @returns {Promise<any>} Extracted text
|
|
448
|
-
*/
|
|
451
|
+
piperBinary;
|
|
449
452
|
asr(t, e = this.whisperModel) {
|
|
450
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");
|
|
451
469
|
let s = () => {
|
|
452
470
|
};
|
|
453
|
-
|
|
454
|
-
this.
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
s = () => h.kill("SIGTERM"), h.on("error", (i) => f(i)), h.stdout.on("data", (i) => m += i.toString()), h.on("close", (i) => {
|
|
458
|
-
i === 0 ? c(m.trim() || null) : f(new Error(`Exit code ${i}`));
|
|
459
|
-
});
|
|
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) }
|
|
460
475
|
});
|
|
461
|
-
|
|
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 });
|
|
462
490
|
}
|
|
463
|
-
/**
|
|
464
|
-
* Downloads the specified Whisper model if it is not already present locally.
|
|
465
|
-
*
|
|
466
|
-
* @param {string} model Whisper model that will be downloaded
|
|
467
|
-
* @return {Promise<string>} Absolute path to model file, resolves once downloaded
|
|
468
|
-
*/
|
|
469
491
|
async downloadAsrModel(t = this.whisperModel) {
|
|
470
492
|
if (!this.ai.options.whisper?.binary) throw new Error("Whisper not configured");
|
|
471
493
|
t.endsWith(".bin") || (t += ".bin");
|
|
472
|
-
const e =
|
|
473
|
-
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]);
|
|
474
507
|
}
|
|
475
508
|
}
|
|
476
|
-
class
|
|
509
|
+
class K {
|
|
477
510
|
constructor(t) {
|
|
478
511
|
this.ai = t;
|
|
479
512
|
}
|
|
480
513
|
/**
|
|
481
514
|
* Convert image to text using Optical Character Recognition
|
|
482
515
|
* @param {string} path Path to image
|
|
483
|
-
* @returns {
|
|
516
|
+
* @returns {AbortablePromise<string | null>} Promise of extracted text with abort method
|
|
484
517
|
*/
|
|
485
518
|
ocr(t) {
|
|
486
519
|
let e;
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
const { data: o } = await e.recognize(t);
|
|
494
|
-
await e.terminate(), s(o.text.trim() || null);
|
|
495
|
-
})
|
|
496
|
-
};
|
|
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() });
|
|
497
526
|
}
|
|
498
527
|
}
|
|
499
|
-
class
|
|
528
|
+
class pe {
|
|
500
529
|
constructor(t) {
|
|
501
|
-
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);
|
|
502
531
|
}
|
|
503
532
|
/** Audio processing AI */
|
|
504
533
|
audio;
|
|
@@ -507,38 +536,38 @@ class le {
|
|
|
507
536
|
/** Vision processing AI */
|
|
508
537
|
vision;
|
|
509
538
|
}
|
|
510
|
-
const
|
|
539
|
+
const V = {
|
|
511
540
|
name: "cli",
|
|
512
541
|
description: "Use the command line interface, returns any output",
|
|
513
542
|
args: { command: { type: "string", description: "Command to run", required: !0 } },
|
|
514
|
-
fn: (
|
|
515
|
-
},
|
|
543
|
+
fn: (u) => H`${u.command}`
|
|
544
|
+
}, ue = {
|
|
516
545
|
name: "get_datetime",
|
|
517
546
|
description: "Get current date and time",
|
|
518
547
|
args: {},
|
|
519
548
|
fn: async () => (/* @__PURE__ */ new Date()).toISOString()
|
|
520
|
-
},
|
|
549
|
+
}, fe = {
|
|
521
550
|
name: "exec",
|
|
522
551
|
description: "Run code/scripts",
|
|
523
552
|
args: {
|
|
524
553
|
language: { type: "string", description: "Execution language", enum: ["cli", "node", "python"], required: !0 },
|
|
525
554
|
code: { type: "string", description: "Code to execute", required: !0 }
|
|
526
555
|
},
|
|
527
|
-
fn: async (
|
|
556
|
+
fn: async (u, t) => {
|
|
528
557
|
try {
|
|
529
|
-
switch (
|
|
558
|
+
switch (u.type) {
|
|
530
559
|
case "bash":
|
|
531
|
-
return await
|
|
560
|
+
return await V.fn({ command: u.code }, t);
|
|
532
561
|
case "node":
|
|
533
|
-
return await
|
|
562
|
+
return await Y.fn({ code: u.code }, t);
|
|
534
563
|
case "python":
|
|
535
|
-
return await
|
|
564
|
+
return await X.fn({ code: u.code }, t);
|
|
536
565
|
}
|
|
537
566
|
} catch (e) {
|
|
538
567
|
return { error: e?.message || e.toString() };
|
|
539
568
|
}
|
|
540
569
|
}
|
|
541
|
-
},
|
|
570
|
+
}, he = {
|
|
542
571
|
name: "fetch",
|
|
543
572
|
description: "Make HTTP request to URL",
|
|
544
573
|
args: {
|
|
@@ -547,54 +576,54 @@ const Q = {
|
|
|
547
576
|
headers: { type: "object", description: "HTTP headers to send", default: {} },
|
|
548
577
|
body: { type: "object", description: "HTTP body to send" }
|
|
549
578
|
},
|
|
550
|
-
fn: (
|
|
551
|
-
},
|
|
579
|
+
fn: (u) => new q({ url: u.url, headers: u.headers }).request({ method: u.method || "GET", body: u.body })
|
|
580
|
+
}, Y = {
|
|
552
581
|
name: "exec_javascript",
|
|
553
582
|
description: "Execute commonjs javascript",
|
|
554
583
|
args: {
|
|
555
584
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
556
585
|
},
|
|
557
|
-
fn: async (
|
|
558
|
-
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));
|
|
559
588
|
return { ...t.output, return: e, stdout: void 0, stderr: void 0 };
|
|
560
589
|
}
|
|
561
|
-
},
|
|
590
|
+
}, X = {
|
|
562
591
|
name: "exec_javascript",
|
|
563
592
|
description: "Execute commonjs javascript",
|
|
564
593
|
args: {
|
|
565
594
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
566
595
|
},
|
|
567
|
-
fn: async (
|
|
568
|
-
},
|
|
596
|
+
fn: async (u) => ({ result: J`python -c "${u.code}"` })
|
|
597
|
+
}, ge = {
|
|
569
598
|
name: "search",
|
|
570
599
|
description: "Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",
|
|
571
600
|
args: {
|
|
572
601
|
query: { type: "string", description: "Search string", required: !0 },
|
|
573
602
|
length: { type: "string", description: "Number of results to return", default: 5 }
|
|
574
603
|
},
|
|
575
|
-
fn: async (
|
|
576
|
-
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)}`, {
|
|
577
606
|
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
|
|
578
|
-
}).then((
|
|
579
|
-
let e,
|
|
580
|
-
const
|
|
581
|
-
for (; (e =
|
|
582
|
-
let
|
|
583
|
-
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;
|
|
584
613
|
}
|
|
585
|
-
return
|
|
614
|
+
return s;
|
|
586
615
|
}
|
|
587
616
|
};
|
|
588
617
|
export {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
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
|
|
599
628
|
};
|
|
600
629
|
//# sourceMappingURL=index.mjs.map
|