@ztimson/ai-utils 0.8.5 → 0.8.6
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 +54 -54
- 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 z, 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 U {
|
|
17
17
|
}
|
|
18
|
-
class
|
|
18
|
+
class Q extends U {
|
|
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(z("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 U {
|
|
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,7 +229,7 @@ ${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(z("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);
|
|
@@ -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,13 +712,13 @@ 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
720
|
switch (h.type) {
|
|
721
|
-
case "
|
|
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);
|
|
@@ -746,7 +746,7 @@ const ne = {
|
|
|
746
746
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
747
747
|
},
|
|
748
748
|
fn: async (h) => {
|
|
749
|
-
const r =
|
|
749
|
+
const r = C(null), e = await J({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
|
|
750
750
|
return { ...r.output, return: e, stdout: void 0, stderr: void 0 };
|
|
751
751
|
}
|
|
752
752
|
}, oe = {
|
|
@@ -755,7 +755,7 @@ const ne = {
|
|
|
755
755
|
args: {
|
|
756
756
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
757
757
|
},
|
|
758
|
-
fn: async (h) => ({ result:
|
|
758
|
+
fn: async (h) => ({ result: j`python -c "${h.code}"` })
|
|
759
759
|
}, _e = {
|
|
760
760
|
name: "read_webpage",
|
|
761
761
|
description: "Extract clean, structured content from a webpage. Use after web_search to read specific URLs",
|
|
@@ -766,7 +766,7 @@ const ne = {
|
|
|
766
766
|
fn: async (h) => {
|
|
767
767
|
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
768
|
throw new Error(`Failed to fetch: ${n.message}`);
|
|
769
|
-
}), e =
|
|
769
|
+
}), e = Z.load(r);
|
|
770
770
|
e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();
|
|
771
771
|
const t = {
|
|
772
772
|
title: e('meta[property="og:title"]').attr("content") || e("title").text() || "",
|
|
@@ -795,7 +795,7 @@ const ne = {
|
|
|
795
795
|
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
|
|
796
796
|
}).then((s) => s.text());
|
|
797
797
|
let e, t = /<a .*?href="(.+?)".+?<\/a>/g;
|
|
798
|
-
const a = new
|
|
798
|
+
const a = new F();
|
|
799
799
|
for (; (e = t.exec(r)) !== null; ) {
|
|
800
800
|
let s = /uddg=(.+)&?/.exec(decodeURIComponent(e[1]))?.[1];
|
|
801
801
|
if (s && (s = decodeURIComponent(s)), s && a.add(s), a.size >= (h.length || 5)) break;
|
|
@@ -805,18 +805,18 @@ const ne = {
|
|
|
805
805
|
};
|
|
806
806
|
export {
|
|
807
807
|
we as Ai,
|
|
808
|
-
|
|
809
|
-
|
|
808
|
+
Q as Anthropic,
|
|
809
|
+
ee as Audio,
|
|
810
810
|
ne as CliTool,
|
|
811
811
|
be as DateTimeTool,
|
|
812
812
|
ke as ExecTool,
|
|
813
813
|
xe as FetchTool,
|
|
814
814
|
se as JSTool,
|
|
815
|
-
|
|
816
|
-
|
|
815
|
+
U as LLMProvider,
|
|
816
|
+
A as OpenAi,
|
|
817
817
|
oe as PythonTool,
|
|
818
818
|
_e as ReadWebpageTool,
|
|
819
|
-
|
|
819
|
+
te as Vision,
|
|
820
820
|
Se as WebSearchTool
|
|
821
821
|
};
|
|
822
822
|
//# sourceMappingURL=index.mjs.map
|