@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.mjs CHANGED
@@ -1,23 +1,23 @@
1
- import * as z from "node:os";
2
- import { tmpdir as U } from "node:os";
3
- import { objectMap as A, JSONAttemptParse as _, findByProp as O, JSONSanitize as S, clean as W, Http as N, consoleInterceptor as L, fn as C, ASet as J } from "@ztimson/utils";
4
- import { Anthropic as F } from "@anthropic-ai/sdk";
5
- import { OpenAI as H } from "openai";
6
- import { fileURLToPath as D } from "url";
7
- import { join as G, dirname as I } from "path";
8
- import { spawn as b, execSync as B } from "node:child_process";
9
- import { mkdtempSync as K } from "node:fs";
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 v from "node:path";
12
- import M, { join as P } from "node:path";
13
- import { createWorker as V } from "tesseract.js";
14
- import * as Y from "cheerio";
15
- import { $ as Z, $Sync as Q } from "@ztimson/node-utils";
16
- class R {
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 X extends R {
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 F({ apiKey: e });
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 ? A(m.args, (o, l) => ({ ...l, required: void 0 })) : {},
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(O("name", l.name));
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 q extends R {
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 H(W({
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 ? A(o.args, (l, d) => ({ ...d, required: void 0 })) : {},
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(O("name", d.function.name));
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 ee {
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 X(this.ai, t.token, e) : t.proto == "ollama" ? this.models[e] = new q(this.ai, t.host, "not-needed", e) : t.proto == "openai" && (this.models[e] = new q(this.ai, t.host || null, t.token, e));
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
- G(I(D(import.meta.url)), "embedder.js"),
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 te {
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 E = x.offsets.from / 1e3, $ = e.find((y) => E >= y.start && E <= y.end);
554
- if ($) {
555
- const y = a.get($.speaker);
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 j = 1, T = 0;
559
+ let T = 1, E = 0;
560
560
  return g.forEach((k, x) => {
561
- k > T && (T = k, j = x);
562
- }), { speaker: j, text: p };
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 = v.join(v.dirname(r), "transcript");
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 = P(K(P(U(), "audio-")), "converted.wav");
647
- B(`ffmpeg -i "${r}" -ar 16000 -ac 1 -f wav "${t}"`, { stdio: "ignore" });
648
- const a = () => w.rm(M.dirname(t), { recursive: !0, force: !0 }).catch(() => {
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 = M.join(this.ai.options.path, r);
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 re {
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 V(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
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 = z.tmpdir()), process.env.TRANSFORMERS_CACHE = r.path, this.audio = new te(this), this.language = new ee(this), this.vision = new re(this);
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) => Z`${h.command}`
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: "Execution language", enum: ["cli", "node", "python"], required: !0 },
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.type) {
721
- case "bash":
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
- const r = L(null), e = await C({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
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: Q`python -c "${h.code}"` })
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 = Y.load(r);
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 J();
801
+ const a = new F();
799
802
  for (; (e = t.exec(r)) !== null; ) {
800
803
  let s = /uddg=(.+)&amp?/.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
- X as Anthropic,
809
- te as Audio,
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
- R as LLMProvider,
816
- q as OpenAi,
818
+ z as LLMProvider,
819
+ A as OpenAi,
817
820
  oe as PythonTool,
818
821
  _e as ReadWebpageTool,
819
- re as Vision,
822
+ te as Vision,
820
823
  Se as WebSearchTool
821
824
  };
822
825
  //# sourceMappingURL=index.mjs.map