@ztimson/ai-utils 0.8.5 → 0.8.7
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.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +59 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { tmpdir as
|
|
3
|
-
import { objectMap as
|
|
4
|
-
import { Anthropic as
|
|
5
|
-
import { OpenAI as
|
|
6
|
-
import { fileURLToPath as
|
|
7
|
-
import { join as
|
|
8
|
-
import { spawn as b, execSync as
|
|
9
|
-
import { mkdtempSync as
|
|
1
|
+
import * as O from "node:os";
|
|
2
|
+
import { tmpdir as L } from "node:os";
|
|
3
|
+
import { objectMap as R, JSONAttemptParse as _, findByProp as U, JSONSanitize as S, clean as W, Http as N, consoleInterceptor as C, fn as J, ASet as F } from "@ztimson/utils";
|
|
4
|
+
import { Anthropic as H } from "@anthropic-ai/sdk";
|
|
5
|
+
import { OpenAI as D } from "openai";
|
|
6
|
+
import { fileURLToPath as G } from "url";
|
|
7
|
+
import { join as I, dirname as B } from "path";
|
|
8
|
+
import { spawn as b, execSync as K } from "node:child_process";
|
|
9
|
+
import { mkdtempSync as V } from "node:fs";
|
|
10
10
|
import w from "node:fs/promises";
|
|
11
|
-
import * as
|
|
12
|
-
import
|
|
13
|
-
import { createWorker as
|
|
14
|
-
import * as
|
|
15
|
-
import { $
|
|
16
|
-
class
|
|
11
|
+
import * as M from "node:path";
|
|
12
|
+
import P, { join as q } from "node:path";
|
|
13
|
+
import { createWorker as Y } from "tesseract.js";
|
|
14
|
+
import * as Z from "cheerio";
|
|
15
|
+
import { $Sync as j } from "@ztimson/node-utils";
|
|
16
|
+
class z {
|
|
17
17
|
}
|
|
18
|
-
class
|
|
18
|
+
class Q extends z {
|
|
19
19
|
constructor(r, e, t) {
|
|
20
|
-
super(), this.ai = r, this.apiToken = e, this.model = t, this.client = new
|
|
20
|
+
super(), this.ai = r, this.apiToken = e, this.model = t, this.client = new H({ apiKey: e });
|
|
21
21
|
}
|
|
22
22
|
client;
|
|
23
23
|
toStandard(r) {
|
|
@@ -67,7 +67,7 @@ class X extends R {
|
|
|
67
67
|
description: m.description,
|
|
68
68
|
input_schema: {
|
|
69
69
|
type: "object",
|
|
70
|
-
properties: m.args ?
|
|
70
|
+
properties: m.args ? R(m.args, (o, l) => ({ ...l, required: void 0 })) : {},
|
|
71
71
|
required: m.args ? Object.entries(m.args).filter((o) => o[1].required).map((o) => o[0]) : []
|
|
72
72
|
},
|
|
73
73
|
fn: void 0
|
|
@@ -106,7 +106,7 @@ ${JSON.stringify(s, null, 2)}`, o;
|
|
|
106
106
|
if (m.length && !t.signal.aborted) {
|
|
107
107
|
s.push({ role: "assistant", content: u.content });
|
|
108
108
|
const o = await Promise.all(m.map(async (l) => {
|
|
109
|
-
const d = n.find(
|
|
109
|
+
const d = n.find(U("name", l.name));
|
|
110
110
|
if (e.stream && e.stream({ tool: l.name }), !d) return { tool_use_id: l.id, is_error: !0, content: "Tool not found" };
|
|
111
111
|
try {
|
|
112
112
|
const p = await d.fn(l.input, e?.stream, this.ai);
|
|
@@ -124,9 +124,9 @@ ${JSON.stringify(s, null, 2)}`, o;
|
|
|
124
124
|
}), { abort: () => t.abort() });
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
-
class
|
|
127
|
+
class A extends z {
|
|
128
128
|
constructor(r, e, t, a) {
|
|
129
|
-
super(), this.ai = r, this.host = e, this.token = t, this.model = a, this.client = new
|
|
129
|
+
super(), this.ai = r, this.host = e, this.token = t, this.model = a, this.client = new D(W({
|
|
130
130
|
baseURL: e,
|
|
131
131
|
apiKey: t || e ? "ignored" : void 0
|
|
132
132
|
}));
|
|
@@ -191,7 +191,7 @@ class q extends R {
|
|
|
191
191
|
description: o.description,
|
|
192
192
|
parameters: {
|
|
193
193
|
type: "object",
|
|
194
|
-
properties: o.args ?
|
|
194
|
+
properties: o.args ? R(o.args, (l, d) => ({ ...d, required: void 0 })) : {},
|
|
195
195
|
required: o.args ? Object.entries(o.args).filter((l) => l[1].required).map((l) => l[0]) : []
|
|
196
196
|
}
|
|
197
197
|
}
|
|
@@ -229,11 +229,11 @@ ${JSON.stringify(n, null, 2)}`, l;
|
|
|
229
229
|
if (o.length && !t.signal.aborted) {
|
|
230
230
|
n.push(i.choices[0].message);
|
|
231
231
|
const l = await Promise.all(o.map(async (d) => {
|
|
232
|
-
const p = c?.find(
|
|
232
|
+
const p = c?.find(U("name", d.function.name));
|
|
233
233
|
if (e.stream && e.stream({ tool: d.function.name }), !p) return { role: "tool", tool_call_id: d.id, content: '{"error": "Tool not found"}' };
|
|
234
234
|
try {
|
|
235
235
|
const f = _(d.function.arguments, {}), g = await p.fn(f, e.stream, this.ai);
|
|
236
|
-
return { role: "tool", tool_call_id: d.id, content: S(g) };
|
|
236
|
+
return console.log(g), { role: "tool", tool_call_id: d.id, content: S(g) };
|
|
237
237
|
} catch (f) {
|
|
238
238
|
return { role: "tool", tool_call_id: d.id, content: S({ error: f?.message || f?.toString() || "Unknown" }) };
|
|
239
239
|
}
|
|
@@ -245,10 +245,10 @@ ${JSON.stringify(n, null, 2)}`, l;
|
|
|
245
245
|
}), { abort: () => t.abort() });
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
|
-
class
|
|
248
|
+
class X {
|
|
249
249
|
constructor(r) {
|
|
250
250
|
this.ai = r, r.options.llm?.models && Object.entries(r.options.llm.models).forEach(([e, t]) => {
|
|
251
|
-
this.defaultModel || (this.defaultModel = e), t.proto == "anthropic" ? this.models[e] = new
|
|
251
|
+
this.defaultModel || (this.defaultModel = e), t.proto == "anthropic" ? this.models[e] = new Q(this.ai, t.token, e) : t.proto == "ollama" ? this.models[e] = new A(this.ai, t.host, "not-needed", e) : t.proto == "openai" && (this.models[e] = new A(this.ai, t.host || null, t.token, e));
|
|
252
252
|
});
|
|
253
253
|
}
|
|
254
254
|
defaultModel;
|
|
@@ -410,7 +410,7 @@ You have RAG memory and will be given the top_k closest memories regarding the u
|
|
|
410
410
|
}, c = (i) => new Promise((m, o) => {
|
|
411
411
|
if (s) return o(new Error("Aborted"));
|
|
412
412
|
const l = [
|
|
413
|
-
|
|
413
|
+
I(B(G(import.meta.url)), "embedder.js"),
|
|
414
414
|
this.ai.options.path,
|
|
415
415
|
this.ai.options?.embedder || "bge-small-en-v1.5"
|
|
416
416
|
], d = b("node", l, { stdio: ["pipe", "pipe", "ignore"] });
|
|
@@ -487,7 +487,7 @@ ${e}
|
|
|
487
487
|
return this.ask(r, { system: `Generate the shortest summary possible <= ${e} tokens. Output nothing else`, temperature: 0.3, ...t });
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
|
-
class
|
|
490
|
+
class ee {
|
|
491
491
|
constructor(r) {
|
|
492
492
|
this.ai = r, r.options.whisper && (this.whisperModel = r.options.asr || "ggml-base.en.bin", this.downloadAsrModel()), this.pyannote = `
|
|
493
493
|
import sys
|
|
@@ -550,16 +550,16 @@ print(json.dumps(segments))
|
|
|
550
550
|
f.forEach((k) => {
|
|
551
551
|
const x = u.find((y) => k === y.text.trim().toLowerCase().replace(/[^\w]/g, ""));
|
|
552
552
|
if (!x) return;
|
|
553
|
-
const
|
|
554
|
-
if (
|
|
555
|
-
const y = a.get(
|
|
553
|
+
const $ = x.offsets.from / 1e3, v = e.find((y) => $ >= y.start && $ <= y.end);
|
|
554
|
+
if (v) {
|
|
555
|
+
const y = a.get(v.speaker);
|
|
556
556
|
g.set(y, (g.get(y) || 0) + 1);
|
|
557
557
|
}
|
|
558
558
|
});
|
|
559
|
-
let
|
|
559
|
+
let T = 1, E = 0;
|
|
560
560
|
return g.forEach((k, x) => {
|
|
561
|
-
k >
|
|
562
|
-
}), { speaker:
|
|
561
|
+
k > E && (E = k, T = x);
|
|
562
|
+
}), { speaker: T, text: p };
|
|
563
563
|
}).filter((p) => p !== null), m = [];
|
|
564
564
|
i.forEach((p) => {
|
|
565
565
|
const f = m[m.length - 1];
|
|
@@ -582,7 +582,7 @@ print(json.dumps(segments))
|
|
|
582
582
|
const a = new Promise((s, n) => {
|
|
583
583
|
this.downloadAsrModel(e.model).then((c) => {
|
|
584
584
|
if (e.diarization) {
|
|
585
|
-
let u =
|
|
585
|
+
let u = M.join(M.dirname(r), "transcript");
|
|
586
586
|
t = b(
|
|
587
587
|
this.ai.options.whisper,
|
|
588
588
|
["-m", c, "-f", r, "-np", "-ml", "1", "-oj", "-of", u],
|
|
@@ -643,9 +643,9 @@ print(json.dumps(segments))
|
|
|
643
643
|
}
|
|
644
644
|
asr(r, e = {}) {
|
|
645
645
|
if (!this.ai.options.whisper) throw new Error("Whisper not configured");
|
|
646
|
-
const t =
|
|
647
|
-
|
|
648
|
-
const a = () => w.rm(
|
|
646
|
+
const t = q(V(q(L(), "audio-")), "converted.wav");
|
|
647
|
+
K(`ffmpeg -i "${r}" -ar 16000 -ac 1 -f wav "${t}"`, { stdio: "ignore" });
|
|
648
|
+
const a = () => w.rm(P.dirname(t), { recursive: !0, force: !0 }).catch(() => {
|
|
649
649
|
});
|
|
650
650
|
if (!e.diarization) return this.runAsr(t, { model: e.model });
|
|
651
651
|
const s = this.runAsr(t, { model: e.model, diarization: !0 }), n = this.runDiarization(t);
|
|
@@ -664,11 +664,11 @@ print(json.dumps(segments))
|
|
|
664
664
|
async downloadAsrModel(r = this.whisperModel) {
|
|
665
665
|
if (!this.ai.options.whisper) throw new Error("Whisper not configured");
|
|
666
666
|
r.endsWith(".bin") || (r += ".bin");
|
|
667
|
-
const e =
|
|
667
|
+
const e = P.join(this.ai.options.path, r);
|
|
668
668
|
return await w.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[r] ? this.downloads[r] : (this.downloads[r] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${r}`).then((t) => t.arrayBuffer()).then((t) => Buffer.from(t)).then(async (t) => (await w.writeFile(e, t), delete this.downloads[r], e)), this.downloads[r]);
|
|
669
669
|
}
|
|
670
670
|
}
|
|
671
|
-
class
|
|
671
|
+
class te {
|
|
672
672
|
constructor(r) {
|
|
673
673
|
this.ai = r;
|
|
674
674
|
}
|
|
@@ -680,7 +680,7 @@ class re {
|
|
|
680
680
|
ocr(r) {
|
|
681
681
|
let e;
|
|
682
682
|
const t = new Promise(async (a) => {
|
|
683
|
-
e = await
|
|
683
|
+
e = await Y(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
|
|
684
684
|
const { data: s } = await e.recognize(r);
|
|
685
685
|
await e.terminate(), a(s.text.trim() || null);
|
|
686
686
|
});
|
|
@@ -689,7 +689,7 @@ class re {
|
|
|
689
689
|
}
|
|
690
690
|
class we {
|
|
691
691
|
constructor(r) {
|
|
692
|
-
this.options = r, r.path || (r.path =
|
|
692
|
+
this.options = r, r.path || (r.path = O.tmpdir()), process.env.TRANSFORMERS_CACHE = r.path, this.audio = new ee(this), this.language = new X(this), this.vision = new te(this);
|
|
693
693
|
}
|
|
694
694
|
/** Audio processing AI */
|
|
695
695
|
audio;
|
|
@@ -698,11 +698,11 @@ class we {
|
|
|
698
698
|
/** Vision processing AI */
|
|
699
699
|
vision;
|
|
700
700
|
}
|
|
701
|
-
const ne = {
|
|
701
|
+
const re = () => O.platform() == "win32" ? "cmd" : j`echo $SHELL`?.split("/").pop() || "bash", ne = {
|
|
702
702
|
name: "cli",
|
|
703
703
|
description: "Use the command line interface, returns any output",
|
|
704
704
|
args: { command: { type: "string", description: "Command to run", required: !0 } },
|
|
705
|
-
fn: (h) =>
|
|
705
|
+
fn: (h) => j`${h.command}`
|
|
706
706
|
}, be = {
|
|
707
707
|
name: "get_datetime",
|
|
708
708
|
description: "Get current UTC date / time",
|
|
@@ -712,18 +712,20 @@ const ne = {
|
|
|
712
712
|
name: "exec",
|
|
713
713
|
description: "Run code/scripts",
|
|
714
714
|
args: {
|
|
715
|
-
language: { type: "string", description:
|
|
715
|
+
language: { type: "string", description: `Execution language (CLI: ${re()})`, enum: ["cli", "node", "python"], required: !0 },
|
|
716
716
|
code: { type: "string", description: "Code to execute", required: !0 }
|
|
717
717
|
},
|
|
718
718
|
fn: async (h, r, e) => {
|
|
719
719
|
try {
|
|
720
|
-
switch (h.
|
|
721
|
-
case "
|
|
720
|
+
switch (h.language) {
|
|
721
|
+
case "cli":
|
|
722
722
|
return await ne.fn({ command: h.code }, r, e);
|
|
723
723
|
case "node":
|
|
724
724
|
return await se.fn({ code: h.code }, r, e);
|
|
725
725
|
case "python":
|
|
726
726
|
return await oe.fn({ code: h.code }, r, e);
|
|
727
|
+
default:
|
|
728
|
+
throw new Error(`Unsupported language: ${h.language}`);
|
|
727
729
|
}
|
|
728
730
|
} catch (t) {
|
|
729
731
|
return { error: t?.message || t.toString() };
|
|
@@ -746,7 +748,8 @@ const ne = {
|
|
|
746
748
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
747
749
|
},
|
|
748
750
|
fn: async (h) => {
|
|
749
|
-
|
|
751
|
+
console.log("executing js");
|
|
752
|
+
const r = C(null), e = await J({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
|
|
750
753
|
return { ...r.output, return: e, stdout: void 0, stderr: void 0 };
|
|
751
754
|
}
|
|
752
755
|
}, oe = {
|
|
@@ -755,7 +758,7 @@ const ne = {
|
|
|
755
758
|
args: {
|
|
756
759
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
757
760
|
},
|
|
758
|
-
fn: async (h) => ({ result:
|
|
761
|
+
fn: async (h) => ({ result: j`python -c "${h.code}"` })
|
|
759
762
|
}, _e = {
|
|
760
763
|
name: "read_webpage",
|
|
761
764
|
description: "Extract clean, structured content from a webpage. Use after web_search to read specific URLs",
|
|
@@ -766,7 +769,7 @@ const ne = {
|
|
|
766
769
|
fn: async (h) => {
|
|
767
770
|
const r = await fetch(h.url, { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } }).then((n) => n.text()).catch((n) => {
|
|
768
771
|
throw new Error(`Failed to fetch: ${n.message}`);
|
|
769
|
-
}), e =
|
|
772
|
+
}), e = Z.load(r);
|
|
770
773
|
e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();
|
|
771
774
|
const t = {
|
|
772
775
|
title: e('meta[property="og:title"]').attr("content") || e("title").text() || "",
|
|
@@ -795,7 +798,7 @@ const ne = {
|
|
|
795
798
|
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
|
|
796
799
|
}).then((s) => s.text());
|
|
797
800
|
let e, t = /<a .*?href="(.+?)".+?<\/a>/g;
|
|
798
|
-
const a = new
|
|
801
|
+
const a = new F();
|
|
799
802
|
for (; (e = t.exec(r)) !== null; ) {
|
|
800
803
|
let s = /uddg=(.+)&?/.exec(decodeURIComponent(e[1]))?.[1];
|
|
801
804
|
if (s && (s = decodeURIComponent(s)), s && a.add(s), a.size >= (h.length || 5)) break;
|
|
@@ -805,18 +808,18 @@ const ne = {
|
|
|
805
808
|
};
|
|
806
809
|
export {
|
|
807
810
|
we as Ai,
|
|
808
|
-
|
|
809
|
-
|
|
811
|
+
Q as Anthropic,
|
|
812
|
+
ee as Audio,
|
|
810
813
|
ne as CliTool,
|
|
811
814
|
be as DateTimeTool,
|
|
812
815
|
ke as ExecTool,
|
|
813
816
|
xe as FetchTool,
|
|
814
817
|
se as JSTool,
|
|
815
|
-
|
|
816
|
-
|
|
818
|
+
z as LLMProvider,
|
|
819
|
+
A as OpenAi,
|
|
817
820
|
oe as PythonTool,
|
|
818
821
|
_e as ReadWebpageTool,
|
|
819
|
-
|
|
822
|
+
te as Vision,
|
|
820
823
|
Se as WebSearchTool
|
|
821
824
|
};
|
|
822
825
|
//# sourceMappingURL=index.mjs.map
|