@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.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 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 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 U {
17
17
  }
18
- class X extends R {
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 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(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 q extends R {
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 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,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(O("name", d.function.name));
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 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,13 +712,13 @@ 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
720
  switch (h.type) {
721
- case "bash":
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 = L(null), e = await C({ console: r }, h.code, !0).catch((t) => r.output.error.push(t));
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: Q`python -c "${h.code}"` })
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 = Y.load(r);
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 J();
798
+ const a = new F();
799
799
  for (; (e = t.exec(r)) !== null; ) {
800
800
  let s = /uddg=(.+)&amp?/.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
- X as Anthropic,
809
- te as Audio,
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
- R as LLMProvider,
816
- q as OpenAi,
815
+ U as LLMProvider,
816
+ A as OpenAi,
817
817
  oe as PythonTool,
818
818
  _e as ReadWebpageTool,
819
- re as Vision,
819
+ te as Vision,
820
820
  Se as WebSearchTool
821
821
  };
822
822
  //# sourceMappingURL=index.mjs.map