@elizaos/plugin-local-ai 1.0.0-alpha.7 → 1.0.0-beta.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/index.js CHANGED
@@ -1,18 +1,9 @@
1
- import {
2
- FormData,
3
- fetch_blob_default,
4
- formDataToBlob
5
- } from "./chunk-TIOOHHYI.js";
6
-
7
1
  // src/index.ts
8
2
  import fs5 from "node:fs";
9
3
  import path5 from "node:path";
10
4
  import { Readable as Readable2 } from "node:stream";
11
5
  import { fileURLToPath } from "node:url";
12
- import {
13
- ModelTypes as ModelTypes3,
14
- logger as logger10
15
- } from "@elizaos/core";
6
+ import { ModelType as ModelType3, logger as logger10 } from "@elizaos/core";
16
7
  import { EmbeddingModel, FlagEmbedding } from "fastembed";
17
8
  import {
18
9
  LlamaChatSession,
@@ -51,9 +42,7 @@ function validateModelConfig(config) {
51
42
  logger.info("Setting USE_LOCAL_AI to true as it's required");
52
43
  }
53
44
  if (config.USE_STUDIOLM_TEXT_MODELS && config.USE_OLLAMA_TEXT_MODELS) {
54
- throw new Error(
55
- "StudioLM and Ollama text models cannot be enabled simultaneously"
56
- );
45
+ throw new Error("StudioLM and Ollama text models cannot be enabled simultaneously");
57
46
  }
58
47
  logger.info("Configuration is valid");
59
48
  }
@@ -100,24 +89,24 @@ ${errorMessages}`);
100
89
  // src/types.ts
101
90
  var MODEL_SPECS = {
102
91
  small: {
103
- name: "DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf",
104
- repo: "unsloth/DeepSeek-R1-Distill-Qwen-1.5B-GGUF",
105
- size: "1.5B",
106
- quantization: "Q8_0",
92
+ name: "DeepHermes-3-Llama-3-3B-Preview-q4.gguf",
93
+ repo: "NousResearch/DeepHermes-3-Llama-3-3B-Preview-GGUF",
94
+ size: "3B",
95
+ quantization: "Q4_0",
107
96
  contextSize: 8192,
108
97
  tokenizer: {
109
- name: "deepseek-ai/deepseek-llm-7b-base",
98
+ name: "NousResearch/DeepHermes-3-Llama-3-3B-Preview",
110
99
  type: "llama"
111
100
  }
112
101
  },
113
102
  medium: {
114
- name: "DeepSeek-R1-Distill-Qwen-7B-Q8_0.gguf",
115
- repo: "bartowski/DeepSeek-R1-Distill-Qwen-7B-GGUF",
116
- size: "7B",
117
- quantization: "Q8_0",
103
+ name: "DeepHermes-3-Llama-3-8B-q4.gguf",
104
+ repo: "NousResearch/DeepHermes-3-Llama-3-8B-Preview-GGUF",
105
+ size: "8B",
106
+ quantization: "Q4_0",
118
107
  contextSize: 8192,
119
108
  tokenizer: {
120
- name: "deepseek-ai/deepseek-llm-7b-base",
109
+ name: "NousResearch/DeepHermes-3-Llama-3-8B-Preview",
121
110
  type: "llama"
122
111
  }
123
112
  },
@@ -165,12 +154,7 @@ var MODEL_SPECS = {
165
154
  quantization: "Q8_0",
166
155
  speakers: ["male_1", "male_2", "female_1", "female_2"],
167
156
  languages: ["en"],
168
- features: [
169
- "MULTI_SPEAKER",
170
- "VOICE_CLONING",
171
- "EMOTION_CONTROL",
172
- "SPEED_CONTROL"
173
- ],
157
+ features: ["MULTI_SPEAKER", "VOICE_CLONING", "EMOTION_CONTROL", "SPEED_CONTROL"],
174
158
  maxInputLength: 4096,
175
159
  sampleRate: 24e3,
176
160
  contextSize: 2048,
@@ -184,14 +168,7 @@ var MODEL_SPECS = {
184
168
  repo: "OuteAI/OuteTTS-0.3-1B-GGUF",
185
169
  size: "1B",
186
170
  quantization: "Q8_0",
187
- speakers: [
188
- "male_1",
189
- "male_2",
190
- "male_3",
191
- "female_1",
192
- "female_2",
193
- "female_3"
194
- ],
171
+ speakers: ["male_1", "male_2", "male_3", "female_1", "female_2", "female_3"],
195
172
  languages: ["en", "es", "fr", "de", "it"],
196
173
  features: [
197
174
  "MULTI_SPEAKER",
@@ -224,20 +201,7 @@ var MODEL_SPECS = {
224
201
  "female_3",
225
202
  "female_4"
226
203
  ],
227
- languages: [
228
- "en",
229
- "es",
230
- "fr",
231
- "de",
232
- "it",
233
- "pt",
234
- "nl",
235
- "pl",
236
- "ru",
237
- "ja",
238
- "ko",
239
- "zh"
240
- ],
204
+ languages: ["en", "es", "fr", "de", "it", "pt", "nl", "pl", "ru", "ja", "ko", "zh"],
241
205
  features: [
242
206
  "MULTI_SPEAKER",
243
207
  "VOICE_CLONING",
@@ -300,20 +264,19 @@ var DownloadManager = class _DownloadManager {
300
264
  * Ensure that the cache directory exists.
301
265
  */
302
266
  ensureCacheDirectory() {
303
- logger2.info("Ensuring cache directory exists:", this.cacheDir);
304
267
  if (!fs.existsSync(this.cacheDir)) {
305
268
  fs.mkdirSync(this.cacheDir, { recursive: true });
306
- logger2.info("Created cache directory");
269
+ logger2.debug("Created cache directory");
307
270
  }
308
271
  }
309
272
  /**
310
273
  * Ensure that the models directory exists. If it does not exist, create it.
311
274
  */
312
275
  ensureModelsDirectory() {
313
- logger2.info("Ensuring models directory exists:", this.modelsDir);
276
+ logger2.debug("Ensuring models directory exists:", this.modelsDir);
314
277
  if (!fs.existsSync(this.modelsDir)) {
315
278
  fs.mkdirSync(this.modelsDir, { recursive: true });
316
- logger2.info("Created models directory");
279
+ logger2.debug("Created models directory");
317
280
  }
318
281
  }
319
282
  /**
@@ -361,10 +324,7 @@ var DownloadManager = class _DownloadManager {
361
324
  reject(new Error(`Failed to download: ${response.statusCode}`));
362
325
  return;
363
326
  }
364
- const totalSize = Number.parseInt(
365
- response.headers["content-length"] || "0",
366
- 10
367
- );
327
+ const totalSize = Number.parseInt(response.headers["content-length"] || "0", 10);
368
328
  let downloadedSize = 0;
369
329
  let lastLoggedPercent = 0;
370
330
  const barLength = 30;
@@ -375,13 +335,9 @@ var DownloadManager = class _DownloadManager {
375
335
  downloadedSize += chunk.length;
376
336
  const percent = Math.round(downloadedSize / totalSize * 100);
377
337
  if (percent >= lastLoggedPercent + 5) {
378
- const filledLength = Math.floor(
379
- downloadedSize / totalSize * barLength
380
- );
338
+ const filledLength = Math.floor(downloadedSize / totalSize * barLength);
381
339
  const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
382
- logger2.info(
383
- `Downloading ${fileName}: ${progressBar} ${percent}%`
384
- );
340
+ logger2.info(`Downloading ${fileName}: ${progressBar} ${percent}%`);
385
341
  lastLoggedPercent = percent;
386
342
  }
387
343
  });
@@ -396,24 +352,18 @@ var DownloadManager = class _DownloadManager {
396
352
  fs.mkdirSync(destDir, { recursive: true });
397
353
  }
398
354
  if (!fs.existsSync(tempPath)) {
399
- reject(
400
- new Error(`Temporary file ${tempPath} does not exist`)
401
- );
355
+ reject(new Error(`Temporary file ${tempPath} does not exist`));
402
356
  return;
403
357
  }
404
358
  if (fs.existsSync(destPath)) {
405
359
  try {
406
360
  const backupPath = `${destPath}.bak`;
407
361
  fs.renameSync(destPath, backupPath);
408
- logger2.info(
409
- `Created backup of existing file: ${backupPath}`
410
- );
362
+ logger2.info(`Created backup of existing file: ${backupPath}`);
411
363
  fs.renameSync(tempPath, destPath);
412
364
  if (fs.existsSync(backupPath)) {
413
365
  fs.unlinkSync(backupPath);
414
- logger2.info(
415
- `Removed backup file after successful update: ${backupPath}`
416
- );
366
+ logger2.info(`Removed backup file after successful update: ${backupPath}`);
417
367
  }
418
368
  } catch (moveErr) {
419
369
  logger2.error(
@@ -423,9 +373,7 @@ var DownloadManager = class _DownloadManager {
423
373
  if (fs.existsSync(backupPath)) {
424
374
  try {
425
375
  fs.renameSync(backupPath, destPath);
426
- logger2.info(
427
- `Restored from backup after failed update: ${backupPath}`
428
- );
376
+ logger2.info(`Restored from backup after failed update: ${backupPath}`);
429
377
  } catch (restoreErr) {
430
378
  logger2.error(
431
379
  `Failed to restore from backup: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`
@@ -447,9 +395,7 @@ var DownloadManager = class _DownloadManager {
447
395
  } else {
448
396
  fs.renameSync(tempPath, destPath);
449
397
  }
450
- logger2.success(
451
- `Download of ${fileName} completed successfully`
452
- );
398
+ logger2.success(`Download of ${fileName} completed successfully`);
453
399
  this.activeDownloads.delete(destPath);
454
400
  resolve();
455
401
  } catch (err) {
@@ -471,9 +417,7 @@ var DownloadManager = class _DownloadManager {
471
417
  });
472
418
  });
473
419
  file.on("error", (err) => {
474
- logger2.error(
475
- `File write error: ${err instanceof Error ? err.message : String(err)}`
476
- );
420
+ logger2.error(`File write error: ${err instanceof Error ? err.message : String(err)}`);
477
421
  file.close(() => {
478
422
  if (fs.existsSync(tempPath)) {
479
423
  try {
@@ -491,9 +435,7 @@ var DownloadManager = class _DownloadManager {
491
435
  }
492
436
  );
493
437
  request.on("error", (err) => {
494
- logger2.error(
495
- `Request error: ${err instanceof Error ? err.message : String(err)}`
496
- );
438
+ logger2.error(`Request error: ${err instanceof Error ? err.message : String(err)}`);
497
439
  if (fs.existsSync(tempPath)) {
498
440
  try {
499
441
  fs.unlinkSync(tempPath);
@@ -532,9 +474,7 @@ var DownloadManager = class _DownloadManager {
532
474
  */
533
475
  async downloadFile(url, destPath) {
534
476
  if (this.activeDownloads.has(destPath)) {
535
- logger2.info(
536
- `Download for ${destPath} already in progress, waiting for it to complete...`
537
- );
477
+ logger2.info(`Download for ${destPath} already in progress, waiting for it to complete...`);
538
478
  const existingDownload = this.activeDownloads.get(destPath);
539
479
  if (existingDownload) {
540
480
  return existingDownload;
@@ -659,1286 +599,7 @@ var DownloadManager = class _DownloadManager {
659
599
  };
660
600
 
661
601
  // src/utils/ollamaManager.ts
662
- import { ModelTypes, logger as logger3 } from "@elizaos/core";
663
-
664
- // ../../node_modules/node-fetch/src/index.js
665
- import http2 from "node:http";
666
- import https2 from "node:https";
667
- import zlib from "node:zlib";
668
- import Stream2, { PassThrough as PassThrough2, pipeline as pump } from "node:stream";
669
- import { Buffer as Buffer3 } from "node:buffer";
670
-
671
- // ../../node_modules/data-uri-to-buffer/dist/index.js
672
- function dataUriToBuffer(uri) {
673
- if (!/^data:/i.test(uri)) {
674
- throw new TypeError('`uri` does not appear to be a Data URI (must begin with "data:")');
675
- }
676
- uri = uri.replace(/\r?\n/g, "");
677
- const firstComma = uri.indexOf(",");
678
- if (firstComma === -1 || firstComma <= 4) {
679
- throw new TypeError("malformed data: URI");
680
- }
681
- const meta = uri.substring(5, firstComma).split(";");
682
- let charset = "";
683
- let base64 = false;
684
- const type = meta[0] || "text/plain";
685
- let typeFull = type;
686
- for (let i = 1; i < meta.length; i++) {
687
- if (meta[i] === "base64") {
688
- base64 = true;
689
- } else if (meta[i]) {
690
- typeFull += `;${meta[i]}`;
691
- if (meta[i].indexOf("charset=") === 0) {
692
- charset = meta[i].substring(8);
693
- }
694
- }
695
- }
696
- if (!meta[0] && !charset.length) {
697
- typeFull += ";charset=US-ASCII";
698
- charset = "US-ASCII";
699
- }
700
- const encoding = base64 ? "base64" : "ascii";
701
- const data = unescape(uri.substring(firstComma + 1));
702
- const buffer = Buffer.from(data, encoding);
703
- buffer.type = type;
704
- buffer.typeFull = typeFull;
705
- buffer.charset = charset;
706
- return buffer;
707
- }
708
- var dist_default = dataUriToBuffer;
709
-
710
- // ../../node_modules/node-fetch/src/body.js
711
- import Stream, { PassThrough } from "node:stream";
712
- import { types, deprecate, promisify } from "node:util";
713
- import { Buffer as Buffer2 } from "node:buffer";
714
-
715
- // ../../node_modules/node-fetch/src/errors/base.js
716
- var FetchBaseError = class extends Error {
717
- constructor(message, type) {
718
- super(message);
719
- Error.captureStackTrace(this, this.constructor);
720
- this.type = type;
721
- }
722
- get name() {
723
- return this.constructor.name;
724
- }
725
- get [Symbol.toStringTag]() {
726
- return this.constructor.name;
727
- }
728
- };
729
-
730
- // ../../node_modules/node-fetch/src/errors/fetch-error.js
731
- var FetchError = class extends FetchBaseError {
732
- /**
733
- * @param {string} message - Error message for human
734
- * @param {string} [type] - Error type for machine
735
- * @param {SystemError} [systemError] - For Node.js system error
736
- */
737
- constructor(message, type, systemError) {
738
- super(message, type);
739
- if (systemError) {
740
- this.code = this.errno = systemError.code;
741
- this.erroredSysCall = systemError.syscall;
742
- }
743
- }
744
- };
745
-
746
- // ../../node_modules/node-fetch/src/utils/is.js
747
- var NAME = Symbol.toStringTag;
748
- var isURLSearchParameters = (object) => {
749
- return typeof object === "object" && typeof object.append === "function" && typeof object.delete === "function" && typeof object.get === "function" && typeof object.getAll === "function" && typeof object.has === "function" && typeof object.set === "function" && typeof object.sort === "function" && object[NAME] === "URLSearchParams";
750
- };
751
- var isBlob = (object) => {
752
- return object && typeof object === "object" && typeof object.arrayBuffer === "function" && typeof object.type === "string" && typeof object.stream === "function" && typeof object.constructor === "function" && /^(Blob|File)$/.test(object[NAME]);
753
- };
754
- var isAbortSignal = (object) => {
755
- return typeof object === "object" && (object[NAME] === "AbortSignal" || object[NAME] === "EventTarget");
756
- };
757
- var isDomainOrSubdomain = (destination, original) => {
758
- const orig = new URL(original).hostname;
759
- const dest = new URL(destination).hostname;
760
- return orig === dest || orig.endsWith(`.${dest}`);
761
- };
762
- var isSameProtocol = (destination, original) => {
763
- const orig = new URL(original).protocol;
764
- const dest = new URL(destination).protocol;
765
- return orig === dest;
766
- };
767
-
768
- // ../../node_modules/node-fetch/src/body.js
769
- var pipeline = promisify(Stream.pipeline);
770
- var INTERNALS = Symbol("Body internals");
771
- var Body = class {
772
- constructor(body, {
773
- size = 0
774
- } = {}) {
775
- let boundary = null;
776
- if (body === null) {
777
- body = null;
778
- } else if (isURLSearchParameters(body)) {
779
- body = Buffer2.from(body.toString());
780
- } else if (isBlob(body)) {
781
- } else if (Buffer2.isBuffer(body)) {
782
- } else if (types.isAnyArrayBuffer(body)) {
783
- body = Buffer2.from(body);
784
- } else if (ArrayBuffer.isView(body)) {
785
- body = Buffer2.from(body.buffer, body.byteOffset, body.byteLength);
786
- } else if (body instanceof Stream) {
787
- } else if (body instanceof FormData) {
788
- body = formDataToBlob(body);
789
- boundary = body.type.split("=")[1];
790
- } else {
791
- body = Buffer2.from(String(body));
792
- }
793
- let stream = body;
794
- if (Buffer2.isBuffer(body)) {
795
- stream = Stream.Readable.from(body);
796
- } else if (isBlob(body)) {
797
- stream = Stream.Readable.from(body.stream());
798
- }
799
- this[INTERNALS] = {
800
- body,
801
- stream,
802
- boundary,
803
- disturbed: false,
804
- error: null
805
- };
806
- this.size = size;
807
- if (body instanceof Stream) {
808
- body.on("error", (error_) => {
809
- const error = error_ instanceof FetchBaseError ? error_ : new FetchError(`Invalid response body while trying to fetch ${this.url}: ${error_.message}`, "system", error_);
810
- this[INTERNALS].error = error;
811
- });
812
- }
813
- }
814
- get body() {
815
- return this[INTERNALS].stream;
816
- }
817
- get bodyUsed() {
818
- return this[INTERNALS].disturbed;
819
- }
820
- /**
821
- * Decode response as ArrayBuffer
822
- *
823
- * @return Promise
824
- */
825
- async arrayBuffer() {
826
- const { buffer, byteOffset, byteLength } = await consumeBody(this);
827
- return buffer.slice(byteOffset, byteOffset + byteLength);
828
- }
829
- async formData() {
830
- const ct = this.headers.get("content-type");
831
- if (ct.startsWith("application/x-www-form-urlencoded")) {
832
- const formData = new FormData();
833
- const parameters = new URLSearchParams(await this.text());
834
- for (const [name, value] of parameters) {
835
- formData.append(name, value);
836
- }
837
- return formData;
838
- }
839
- const { toFormData } = await import("./multipart-parser-IQPIHJ5G.js");
840
- return toFormData(this.body, ct);
841
- }
842
- /**
843
- * Return raw response as Blob
844
- *
845
- * @return Promise
846
- */
847
- async blob() {
848
- const ct = this.headers && this.headers.get("content-type") || this[INTERNALS].body && this[INTERNALS].body.type || "";
849
- const buf = await this.arrayBuffer();
850
- return new fetch_blob_default([buf], {
851
- type: ct
852
- });
853
- }
854
- /**
855
- * Decode response as json
856
- *
857
- * @return Promise
858
- */
859
- async json() {
860
- const text = await this.text();
861
- return JSON.parse(text);
862
- }
863
- /**
864
- * Decode response as text
865
- *
866
- * @return Promise
867
- */
868
- async text() {
869
- const buffer = await consumeBody(this);
870
- return new TextDecoder().decode(buffer);
871
- }
872
- /**
873
- * Decode response as buffer (non-spec api)
874
- *
875
- * @return Promise
876
- */
877
- buffer() {
878
- return consumeBody(this);
879
- }
880
- };
881
- Body.prototype.buffer = deprecate(Body.prototype.buffer, "Please use 'response.arrayBuffer()' instead of 'response.buffer()'", "node-fetch#buffer");
882
- Object.defineProperties(Body.prototype, {
883
- body: { enumerable: true },
884
- bodyUsed: { enumerable: true },
885
- arrayBuffer: { enumerable: true },
886
- blob: { enumerable: true },
887
- json: { enumerable: true },
888
- text: { enumerable: true },
889
- data: { get: deprecate(
890
- () => {
891
- },
892
- "data doesn't exist, use json(), text(), arrayBuffer(), or body instead",
893
- "https://github.com/node-fetch/node-fetch/issues/1000 (response)"
894
- ) }
895
- });
896
- async function consumeBody(data) {
897
- if (data[INTERNALS].disturbed) {
898
- throw new TypeError(`body used already for: ${data.url}`);
899
- }
900
- data[INTERNALS].disturbed = true;
901
- if (data[INTERNALS].error) {
902
- throw data[INTERNALS].error;
903
- }
904
- const { body } = data;
905
- if (body === null) {
906
- return Buffer2.alloc(0);
907
- }
908
- if (!(body instanceof Stream)) {
909
- return Buffer2.alloc(0);
910
- }
911
- const accum = [];
912
- let accumBytes = 0;
913
- try {
914
- for await (const chunk of body) {
915
- if (data.size > 0 && accumBytes + chunk.length > data.size) {
916
- const error = new FetchError(`content size at ${data.url} over limit: ${data.size}`, "max-size");
917
- body.destroy(error);
918
- throw error;
919
- }
920
- accumBytes += chunk.length;
921
- accum.push(chunk);
922
- }
923
- } catch (error) {
924
- const error_ = error instanceof FetchBaseError ? error : new FetchError(`Invalid response body while trying to fetch ${data.url}: ${error.message}`, "system", error);
925
- throw error_;
926
- }
927
- if (body.readableEnded === true || body._readableState.ended === true) {
928
- try {
929
- if (accum.every((c) => typeof c === "string")) {
930
- return Buffer2.from(accum.join(""));
931
- }
932
- return Buffer2.concat(accum, accumBytes);
933
- } catch (error) {
934
- throw new FetchError(`Could not create Buffer from response body for ${data.url}: ${error.message}`, "system", error);
935
- }
936
- } else {
937
- throw new FetchError(`Premature close of server response while trying to fetch ${data.url}`);
938
- }
939
- }
940
- var clone = (instance, highWaterMark) => {
941
- let p1;
942
- let p2;
943
- let { body } = instance[INTERNALS];
944
- if (instance.bodyUsed) {
945
- throw new Error("cannot clone body after it is used");
946
- }
947
- if (body instanceof Stream && typeof body.getBoundary !== "function") {
948
- p1 = new PassThrough({ highWaterMark });
949
- p2 = new PassThrough({ highWaterMark });
950
- body.pipe(p1);
951
- body.pipe(p2);
952
- instance[INTERNALS].stream = p1;
953
- body = p2;
954
- }
955
- return body;
956
- };
957
- var getNonSpecFormDataBoundary = deprecate(
958
- (body) => body.getBoundary(),
959
- "form-data doesn't follow the spec and requires special treatment. Use alternative package",
960
- "https://github.com/node-fetch/node-fetch/issues/1167"
961
- );
962
- var extractContentType = (body, request) => {
963
- if (body === null) {
964
- return null;
965
- }
966
- if (typeof body === "string") {
967
- return "text/plain;charset=UTF-8";
968
- }
969
- if (isURLSearchParameters(body)) {
970
- return "application/x-www-form-urlencoded;charset=UTF-8";
971
- }
972
- if (isBlob(body)) {
973
- return body.type || null;
974
- }
975
- if (Buffer2.isBuffer(body) || types.isAnyArrayBuffer(body) || ArrayBuffer.isView(body)) {
976
- return null;
977
- }
978
- if (body instanceof FormData) {
979
- return `multipart/form-data; boundary=${request[INTERNALS].boundary}`;
980
- }
981
- if (body && typeof body.getBoundary === "function") {
982
- return `multipart/form-data;boundary=${getNonSpecFormDataBoundary(body)}`;
983
- }
984
- if (body instanceof Stream) {
985
- return null;
986
- }
987
- return "text/plain;charset=UTF-8";
988
- };
989
- var getTotalBytes = (request) => {
990
- const { body } = request[INTERNALS];
991
- if (body === null) {
992
- return 0;
993
- }
994
- if (isBlob(body)) {
995
- return body.size;
996
- }
997
- if (Buffer2.isBuffer(body)) {
998
- return body.length;
999
- }
1000
- if (body && typeof body.getLengthSync === "function") {
1001
- return body.hasKnownLength && body.hasKnownLength() ? body.getLengthSync() : null;
1002
- }
1003
- return null;
1004
- };
1005
- var writeToStream = async (dest, { body }) => {
1006
- if (body === null) {
1007
- dest.end();
1008
- } else {
1009
- await pipeline(body, dest);
1010
- }
1011
- };
1012
-
1013
- // ../../node_modules/node-fetch/src/headers.js
1014
- import { types as types2 } from "node:util";
1015
- import http from "node:http";
1016
- var validateHeaderName = typeof http.validateHeaderName === "function" ? http.validateHeaderName : (name) => {
1017
- if (!/^[\^`\-\w!#$%&'*+.|~]+$/.test(name)) {
1018
- const error = new TypeError(`Header name must be a valid HTTP token [${name}]`);
1019
- Object.defineProperty(error, "code", { value: "ERR_INVALID_HTTP_TOKEN" });
1020
- throw error;
1021
- }
1022
- };
1023
- var validateHeaderValue = typeof http.validateHeaderValue === "function" ? http.validateHeaderValue : (name, value) => {
1024
- if (/[^\t\u0020-\u007E\u0080-\u00FF]/.test(value)) {
1025
- const error = new TypeError(`Invalid character in header content ["${name}"]`);
1026
- Object.defineProperty(error, "code", { value: "ERR_INVALID_CHAR" });
1027
- throw error;
1028
- }
1029
- };
1030
- var Headers = class _Headers extends URLSearchParams {
1031
- /**
1032
- * Headers class
1033
- *
1034
- * @constructor
1035
- * @param {HeadersInit} [init] - Response headers
1036
- */
1037
- constructor(init) {
1038
- let result = [];
1039
- if (init instanceof _Headers) {
1040
- const raw = init.raw();
1041
- for (const [name, values] of Object.entries(raw)) {
1042
- result.push(...values.map((value) => [name, value]));
1043
- }
1044
- } else if (init == null) {
1045
- } else if (typeof init === "object" && !types2.isBoxedPrimitive(init)) {
1046
- const method = init[Symbol.iterator];
1047
- if (method == null) {
1048
- result.push(...Object.entries(init));
1049
- } else {
1050
- if (typeof method !== "function") {
1051
- throw new TypeError("Header pairs must be iterable");
1052
- }
1053
- result = [...init].map((pair) => {
1054
- if (typeof pair !== "object" || types2.isBoxedPrimitive(pair)) {
1055
- throw new TypeError("Each header pair must be an iterable object");
1056
- }
1057
- return [...pair];
1058
- }).map((pair) => {
1059
- if (pair.length !== 2) {
1060
- throw new TypeError("Each header pair must be a name/value tuple");
1061
- }
1062
- return [...pair];
1063
- });
1064
- }
1065
- } else {
1066
- throw new TypeError("Failed to construct 'Headers': The provided value is not of type '(sequence<sequence<ByteString>> or record<ByteString, ByteString>)");
1067
- }
1068
- result = result.length > 0 ? result.map(([name, value]) => {
1069
- validateHeaderName(name);
1070
- validateHeaderValue(name, String(value));
1071
- return [String(name).toLowerCase(), String(value)];
1072
- }) : void 0;
1073
- super(result);
1074
- return new Proxy(this, {
1075
- get(target, p, receiver) {
1076
- switch (p) {
1077
- case "append":
1078
- case "set":
1079
- return (name, value) => {
1080
- validateHeaderName(name);
1081
- validateHeaderValue(name, String(value));
1082
- return URLSearchParams.prototype[p].call(
1083
- target,
1084
- String(name).toLowerCase(),
1085
- String(value)
1086
- );
1087
- };
1088
- case "delete":
1089
- case "has":
1090
- case "getAll":
1091
- return (name) => {
1092
- validateHeaderName(name);
1093
- return URLSearchParams.prototype[p].call(
1094
- target,
1095
- String(name).toLowerCase()
1096
- );
1097
- };
1098
- case "keys":
1099
- return () => {
1100
- target.sort();
1101
- return new Set(URLSearchParams.prototype.keys.call(target)).keys();
1102
- };
1103
- default:
1104
- return Reflect.get(target, p, receiver);
1105
- }
1106
- }
1107
- });
1108
- }
1109
- get [Symbol.toStringTag]() {
1110
- return this.constructor.name;
1111
- }
1112
- toString() {
1113
- return Object.prototype.toString.call(this);
1114
- }
1115
- get(name) {
1116
- const values = this.getAll(name);
1117
- if (values.length === 0) {
1118
- return null;
1119
- }
1120
- let value = values.join(", ");
1121
- if (/^content-encoding$/i.test(name)) {
1122
- value = value.toLowerCase();
1123
- }
1124
- return value;
1125
- }
1126
- forEach(callback, thisArg = void 0) {
1127
- for (const name of this.keys()) {
1128
- Reflect.apply(callback, thisArg, [this.get(name), name, this]);
1129
- }
1130
- }
1131
- *values() {
1132
- for (const name of this.keys()) {
1133
- yield this.get(name);
1134
- }
1135
- }
1136
- /**
1137
- * @type {() => IterableIterator<[string, string]>}
1138
- */
1139
- *entries() {
1140
- for (const name of this.keys()) {
1141
- yield [name, this.get(name)];
1142
- }
1143
- }
1144
- [Symbol.iterator]() {
1145
- return this.entries();
1146
- }
1147
- /**
1148
- * Node-fetch non-spec method
1149
- * returning all headers and their values as array
1150
- * @returns {Record<string, string[]>}
1151
- */
1152
- raw() {
1153
- return [...this.keys()].reduce((result, key) => {
1154
- result[key] = this.getAll(key);
1155
- return result;
1156
- }, {});
1157
- }
1158
- /**
1159
- * For better console.log(headers) and also to convert Headers into Node.js Request compatible format
1160
- */
1161
- [Symbol.for("nodejs.util.inspect.custom")]() {
1162
- return [...this.keys()].reduce((result, key) => {
1163
- const values = this.getAll(key);
1164
- if (key === "host") {
1165
- result[key] = values[0];
1166
- } else {
1167
- result[key] = values.length > 1 ? values : values[0];
1168
- }
1169
- return result;
1170
- }, {});
1171
- }
1172
- };
1173
- Object.defineProperties(
1174
- Headers.prototype,
1175
- ["get", "entries", "forEach", "values"].reduce((result, property) => {
1176
- result[property] = { enumerable: true };
1177
- return result;
1178
- }, {})
1179
- );
1180
- function fromRawHeaders(headers = []) {
1181
- return new Headers(
1182
- headers.reduce((result, value, index, array) => {
1183
- if (index % 2 === 0) {
1184
- result.push(array.slice(index, index + 2));
1185
- }
1186
- return result;
1187
- }, []).filter(([name, value]) => {
1188
- try {
1189
- validateHeaderName(name);
1190
- validateHeaderValue(name, String(value));
1191
- return true;
1192
- } catch {
1193
- return false;
1194
- }
1195
- })
1196
- );
1197
- }
1198
-
1199
- // ../../node_modules/node-fetch/src/utils/is-redirect.js
1200
- var redirectStatus = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
1201
- var isRedirect = (code) => {
1202
- return redirectStatus.has(code);
1203
- };
1204
-
1205
- // ../../node_modules/node-fetch/src/response.js
1206
- var INTERNALS2 = Symbol("Response internals");
1207
- var Response = class _Response extends Body {
1208
- constructor(body = null, options = {}) {
1209
- super(body, options);
1210
- const status = options.status != null ? options.status : 200;
1211
- const headers = new Headers(options.headers);
1212
- if (body !== null && !headers.has("Content-Type")) {
1213
- const contentType = extractContentType(body, this);
1214
- if (contentType) {
1215
- headers.append("Content-Type", contentType);
1216
- }
1217
- }
1218
- this[INTERNALS2] = {
1219
- type: "default",
1220
- url: options.url,
1221
- status,
1222
- statusText: options.statusText || "",
1223
- headers,
1224
- counter: options.counter,
1225
- highWaterMark: options.highWaterMark
1226
- };
1227
- }
1228
- get type() {
1229
- return this[INTERNALS2].type;
1230
- }
1231
- get url() {
1232
- return this[INTERNALS2].url || "";
1233
- }
1234
- get status() {
1235
- return this[INTERNALS2].status;
1236
- }
1237
- /**
1238
- * Convenience property representing if the request ended normally
1239
- */
1240
- get ok() {
1241
- return this[INTERNALS2].status >= 200 && this[INTERNALS2].status < 300;
1242
- }
1243
- get redirected() {
1244
- return this[INTERNALS2].counter > 0;
1245
- }
1246
- get statusText() {
1247
- return this[INTERNALS2].statusText;
1248
- }
1249
- get headers() {
1250
- return this[INTERNALS2].headers;
1251
- }
1252
- get highWaterMark() {
1253
- return this[INTERNALS2].highWaterMark;
1254
- }
1255
- /**
1256
- * Clone this response
1257
- *
1258
- * @return Response
1259
- */
1260
- clone() {
1261
- return new _Response(clone(this, this.highWaterMark), {
1262
- type: this.type,
1263
- url: this.url,
1264
- status: this.status,
1265
- statusText: this.statusText,
1266
- headers: this.headers,
1267
- ok: this.ok,
1268
- redirected: this.redirected,
1269
- size: this.size,
1270
- highWaterMark: this.highWaterMark
1271
- });
1272
- }
1273
- /**
1274
- * @param {string} url The URL that the new response is to originate from.
1275
- * @param {number} status An optional status code for the response (e.g., 302.)
1276
- * @returns {Response} A Response object.
1277
- */
1278
- static redirect(url, status = 302) {
1279
- if (!isRedirect(status)) {
1280
- throw new RangeError('Failed to execute "redirect" on "response": Invalid status code');
1281
- }
1282
- return new _Response(null, {
1283
- headers: {
1284
- location: new URL(url).toString()
1285
- },
1286
- status
1287
- });
1288
- }
1289
- static error() {
1290
- const response = new _Response(null, { status: 0, statusText: "" });
1291
- response[INTERNALS2].type = "error";
1292
- return response;
1293
- }
1294
- static json(data = void 0, init = {}) {
1295
- const body = JSON.stringify(data);
1296
- if (body === void 0) {
1297
- throw new TypeError("data is not JSON serializable");
1298
- }
1299
- const headers = new Headers(init && init.headers);
1300
- if (!headers.has("content-type")) {
1301
- headers.set("content-type", "application/json");
1302
- }
1303
- return new _Response(body, {
1304
- ...init,
1305
- headers
1306
- });
1307
- }
1308
- get [Symbol.toStringTag]() {
1309
- return "Response";
1310
- }
1311
- };
1312
- Object.defineProperties(Response.prototype, {
1313
- type: { enumerable: true },
1314
- url: { enumerable: true },
1315
- status: { enumerable: true },
1316
- ok: { enumerable: true },
1317
- redirected: { enumerable: true },
1318
- statusText: { enumerable: true },
1319
- headers: { enumerable: true },
1320
- clone: { enumerable: true }
1321
- });
1322
-
1323
- // ../../node_modules/node-fetch/src/request.js
1324
- import { format as formatUrl } from "node:url";
1325
- import { deprecate as deprecate2 } from "node:util";
1326
-
1327
- // ../../node_modules/node-fetch/src/utils/get-search.js
1328
- var getSearch = (parsedURL) => {
1329
- if (parsedURL.search) {
1330
- return parsedURL.search;
1331
- }
1332
- const lastOffset = parsedURL.href.length - 1;
1333
- const hash = parsedURL.hash || (parsedURL.href[lastOffset] === "#" ? "#" : "");
1334
- return parsedURL.href[lastOffset - hash.length] === "?" ? "?" : "";
1335
- };
1336
-
1337
- // ../../node_modules/node-fetch/src/utils/referrer.js
1338
- import { isIP } from "node:net";
1339
- function stripURLForUseAsAReferrer(url, originOnly = false) {
1340
- if (url == null) {
1341
- return "no-referrer";
1342
- }
1343
- url = new URL(url);
1344
- if (/^(about|blob|data):$/.test(url.protocol)) {
1345
- return "no-referrer";
1346
- }
1347
- url.username = "";
1348
- url.password = "";
1349
- url.hash = "";
1350
- if (originOnly) {
1351
- url.pathname = "";
1352
- url.search = "";
1353
- }
1354
- return url;
1355
- }
1356
- var ReferrerPolicy = /* @__PURE__ */ new Set([
1357
- "",
1358
- "no-referrer",
1359
- "no-referrer-when-downgrade",
1360
- "same-origin",
1361
- "origin",
1362
- "strict-origin",
1363
- "origin-when-cross-origin",
1364
- "strict-origin-when-cross-origin",
1365
- "unsafe-url"
1366
- ]);
1367
- var DEFAULT_REFERRER_POLICY = "strict-origin-when-cross-origin";
1368
- function validateReferrerPolicy(referrerPolicy) {
1369
- if (!ReferrerPolicy.has(referrerPolicy)) {
1370
- throw new TypeError(`Invalid referrerPolicy: ${referrerPolicy}`);
1371
- }
1372
- return referrerPolicy;
1373
- }
1374
- function isOriginPotentiallyTrustworthy(url) {
1375
- if (/^(http|ws)s:$/.test(url.protocol)) {
1376
- return true;
1377
- }
1378
- const hostIp = url.host.replace(/(^\[)|(]$)/g, "");
1379
- const hostIPVersion = isIP(hostIp);
1380
- if (hostIPVersion === 4 && /^127\./.test(hostIp)) {
1381
- return true;
1382
- }
1383
- if (hostIPVersion === 6 && /^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(hostIp)) {
1384
- return true;
1385
- }
1386
- if (url.host === "localhost" || url.host.endsWith(".localhost")) {
1387
- return false;
1388
- }
1389
- if (url.protocol === "file:") {
1390
- return true;
1391
- }
1392
- return false;
1393
- }
1394
- function isUrlPotentiallyTrustworthy(url) {
1395
- if (/^about:(blank|srcdoc)$/.test(url)) {
1396
- return true;
1397
- }
1398
- if (url.protocol === "data:") {
1399
- return true;
1400
- }
1401
- if (/^(blob|filesystem):$/.test(url.protocol)) {
1402
- return true;
1403
- }
1404
- return isOriginPotentiallyTrustworthy(url);
1405
- }
1406
- function determineRequestsReferrer(request, { referrerURLCallback, referrerOriginCallback } = {}) {
1407
- if (request.referrer === "no-referrer" || request.referrerPolicy === "") {
1408
- return null;
1409
- }
1410
- const policy = request.referrerPolicy;
1411
- if (request.referrer === "about:client") {
1412
- return "no-referrer";
1413
- }
1414
- const referrerSource = request.referrer;
1415
- let referrerURL = stripURLForUseAsAReferrer(referrerSource);
1416
- let referrerOrigin = stripURLForUseAsAReferrer(referrerSource, true);
1417
- if (referrerURL.toString().length > 4096) {
1418
- referrerURL = referrerOrigin;
1419
- }
1420
- if (referrerURLCallback) {
1421
- referrerURL = referrerURLCallback(referrerURL);
1422
- }
1423
- if (referrerOriginCallback) {
1424
- referrerOrigin = referrerOriginCallback(referrerOrigin);
1425
- }
1426
- const currentURL = new URL(request.url);
1427
- switch (policy) {
1428
- case "no-referrer":
1429
- return "no-referrer";
1430
- case "origin":
1431
- return referrerOrigin;
1432
- case "unsafe-url":
1433
- return referrerURL;
1434
- case "strict-origin":
1435
- if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
1436
- return "no-referrer";
1437
- }
1438
- return referrerOrigin.toString();
1439
- case "strict-origin-when-cross-origin":
1440
- if (referrerURL.origin === currentURL.origin) {
1441
- return referrerURL;
1442
- }
1443
- if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
1444
- return "no-referrer";
1445
- }
1446
- return referrerOrigin;
1447
- case "same-origin":
1448
- if (referrerURL.origin === currentURL.origin) {
1449
- return referrerURL;
1450
- }
1451
- return "no-referrer";
1452
- case "origin-when-cross-origin":
1453
- if (referrerURL.origin === currentURL.origin) {
1454
- return referrerURL;
1455
- }
1456
- return referrerOrigin;
1457
- case "no-referrer-when-downgrade":
1458
- if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) {
1459
- return "no-referrer";
1460
- }
1461
- return referrerURL;
1462
- default:
1463
- throw new TypeError(`Invalid referrerPolicy: ${policy}`);
1464
- }
1465
- }
1466
- function parseReferrerPolicyFromHeader(headers) {
1467
- const policyTokens = (headers.get("referrer-policy") || "").split(/[,\s]+/);
1468
- let policy = "";
1469
- for (const token of policyTokens) {
1470
- if (token && ReferrerPolicy.has(token)) {
1471
- policy = token;
1472
- }
1473
- }
1474
- return policy;
1475
- }
1476
-
1477
- // ../../node_modules/node-fetch/src/request.js
1478
- var INTERNALS3 = Symbol("Request internals");
1479
- var isRequest = (object) => {
1480
- return typeof object === "object" && typeof object[INTERNALS3] === "object";
1481
- };
1482
- var doBadDataWarn = deprecate2(
1483
- () => {
1484
- },
1485
- ".data is not a valid RequestInit property, use .body instead",
1486
- "https://github.com/node-fetch/node-fetch/issues/1000 (request)"
1487
- );
1488
- var Request = class _Request extends Body {
1489
- constructor(input, init = {}) {
1490
- let parsedURL;
1491
- if (isRequest(input)) {
1492
- parsedURL = new URL(input.url);
1493
- } else {
1494
- parsedURL = new URL(input);
1495
- input = {};
1496
- }
1497
- if (parsedURL.username !== "" || parsedURL.password !== "") {
1498
- throw new TypeError(`${parsedURL} is an url with embedded credentials.`);
1499
- }
1500
- let method = init.method || input.method || "GET";
1501
- if (/^(delete|get|head|options|post|put)$/i.test(method)) {
1502
- method = method.toUpperCase();
1503
- }
1504
- if (!isRequest(init) && "data" in init) {
1505
- doBadDataWarn();
1506
- }
1507
- if ((init.body != null || isRequest(input) && input.body !== null) && (method === "GET" || method === "HEAD")) {
1508
- throw new TypeError("Request with GET/HEAD method cannot have body");
1509
- }
1510
- const inputBody = init.body ? init.body : isRequest(input) && input.body !== null ? clone(input) : null;
1511
- super(inputBody, {
1512
- size: init.size || input.size || 0
1513
- });
1514
- const headers = new Headers(init.headers || input.headers || {});
1515
- if (inputBody !== null && !headers.has("Content-Type")) {
1516
- const contentType = extractContentType(inputBody, this);
1517
- if (contentType) {
1518
- headers.set("Content-Type", contentType);
1519
- }
1520
- }
1521
- let signal = isRequest(input) ? input.signal : null;
1522
- if ("signal" in init) {
1523
- signal = init.signal;
1524
- }
1525
- if (signal != null && !isAbortSignal(signal)) {
1526
- throw new TypeError("Expected signal to be an instanceof AbortSignal or EventTarget");
1527
- }
1528
- let referrer = init.referrer == null ? input.referrer : init.referrer;
1529
- if (referrer === "") {
1530
- referrer = "no-referrer";
1531
- } else if (referrer) {
1532
- const parsedReferrer = new URL(referrer);
1533
- referrer = /^about:(\/\/)?client$/.test(parsedReferrer) ? "client" : parsedReferrer;
1534
- } else {
1535
- referrer = void 0;
1536
- }
1537
- this[INTERNALS3] = {
1538
- method,
1539
- redirect: init.redirect || input.redirect || "follow",
1540
- headers,
1541
- parsedURL,
1542
- signal,
1543
- referrer
1544
- };
1545
- this.follow = init.follow === void 0 ? input.follow === void 0 ? 20 : input.follow : init.follow;
1546
- this.compress = init.compress === void 0 ? input.compress === void 0 ? true : input.compress : init.compress;
1547
- this.counter = init.counter || input.counter || 0;
1548
- this.agent = init.agent || input.agent;
1549
- this.highWaterMark = init.highWaterMark || input.highWaterMark || 16384;
1550
- this.insecureHTTPParser = init.insecureHTTPParser || input.insecureHTTPParser || false;
1551
- this.referrerPolicy = init.referrerPolicy || input.referrerPolicy || "";
1552
- }
1553
- /** @returns {string} */
1554
- get method() {
1555
- return this[INTERNALS3].method;
1556
- }
1557
- /** @returns {string} */
1558
- get url() {
1559
- return formatUrl(this[INTERNALS3].parsedURL);
1560
- }
1561
- /** @returns {Headers} */
1562
- get headers() {
1563
- return this[INTERNALS3].headers;
1564
- }
1565
- get redirect() {
1566
- return this[INTERNALS3].redirect;
1567
- }
1568
- /** @returns {AbortSignal} */
1569
- get signal() {
1570
- return this[INTERNALS3].signal;
1571
- }
1572
- // https://fetch.spec.whatwg.org/#dom-request-referrer
1573
- get referrer() {
1574
- if (this[INTERNALS3].referrer === "no-referrer") {
1575
- return "";
1576
- }
1577
- if (this[INTERNALS3].referrer === "client") {
1578
- return "about:client";
1579
- }
1580
- if (this[INTERNALS3].referrer) {
1581
- return this[INTERNALS3].referrer.toString();
1582
- }
1583
- return void 0;
1584
- }
1585
- get referrerPolicy() {
1586
- return this[INTERNALS3].referrerPolicy;
1587
- }
1588
- set referrerPolicy(referrerPolicy) {
1589
- this[INTERNALS3].referrerPolicy = validateReferrerPolicy(referrerPolicy);
1590
- }
1591
- /**
1592
- * Clone this request
1593
- *
1594
- * @return Request
1595
- */
1596
- clone() {
1597
- return new _Request(this);
1598
- }
1599
- get [Symbol.toStringTag]() {
1600
- return "Request";
1601
- }
1602
- };
1603
- Object.defineProperties(Request.prototype, {
1604
- method: { enumerable: true },
1605
- url: { enumerable: true },
1606
- headers: { enumerable: true },
1607
- redirect: { enumerable: true },
1608
- clone: { enumerable: true },
1609
- signal: { enumerable: true },
1610
- referrer: { enumerable: true },
1611
- referrerPolicy: { enumerable: true }
1612
- });
1613
- var getNodeRequestOptions = (request) => {
1614
- const { parsedURL } = request[INTERNALS3];
1615
- const headers = new Headers(request[INTERNALS3].headers);
1616
- if (!headers.has("Accept")) {
1617
- headers.set("Accept", "*/*");
1618
- }
1619
- let contentLengthValue = null;
1620
- if (request.body === null && /^(post|put)$/i.test(request.method)) {
1621
- contentLengthValue = "0";
1622
- }
1623
- if (request.body !== null) {
1624
- const totalBytes = getTotalBytes(request);
1625
- if (typeof totalBytes === "number" && !Number.isNaN(totalBytes)) {
1626
- contentLengthValue = String(totalBytes);
1627
- }
1628
- }
1629
- if (contentLengthValue) {
1630
- headers.set("Content-Length", contentLengthValue);
1631
- }
1632
- if (request.referrerPolicy === "") {
1633
- request.referrerPolicy = DEFAULT_REFERRER_POLICY;
1634
- }
1635
- if (request.referrer && request.referrer !== "no-referrer") {
1636
- request[INTERNALS3].referrer = determineRequestsReferrer(request);
1637
- } else {
1638
- request[INTERNALS3].referrer = "no-referrer";
1639
- }
1640
- if (request[INTERNALS3].referrer instanceof URL) {
1641
- headers.set("Referer", request.referrer);
1642
- }
1643
- if (!headers.has("User-Agent")) {
1644
- headers.set("User-Agent", "node-fetch");
1645
- }
1646
- if (request.compress && !headers.has("Accept-Encoding")) {
1647
- headers.set("Accept-Encoding", "gzip, deflate, br");
1648
- }
1649
- let { agent } = request;
1650
- if (typeof agent === "function") {
1651
- agent = agent(parsedURL);
1652
- }
1653
- const search = getSearch(parsedURL);
1654
- const options = {
1655
- // Overwrite search to retain trailing ? (issue #776)
1656
- path: parsedURL.pathname + search,
1657
- // The following options are not expressed in the URL
1658
- method: request.method,
1659
- headers: headers[Symbol.for("nodejs.util.inspect.custom")](),
1660
- insecureHTTPParser: request.insecureHTTPParser,
1661
- agent
1662
- };
1663
- return {
1664
- /** @type {URL} */
1665
- parsedURL,
1666
- options
1667
- };
1668
- };
1669
-
1670
- // ../../node_modules/node-fetch/src/errors/abort-error.js
1671
- var AbortError = class extends FetchBaseError {
1672
- constructor(message, type = "aborted") {
1673
- super(message, type);
1674
- }
1675
- };
1676
-
1677
- // ../../node_modules/node-fetch/src/index.js
1678
- var supportedSchemas = /* @__PURE__ */ new Set(["data:", "http:", "https:"]);
1679
- async function fetch2(url, options_) {
1680
- return new Promise((resolve, reject) => {
1681
- const request = new Request(url, options_);
1682
- const { parsedURL, options } = getNodeRequestOptions(request);
1683
- if (!supportedSchemas.has(parsedURL.protocol)) {
1684
- throw new TypeError(`node-fetch cannot load ${url}. URL scheme "${parsedURL.protocol.replace(/:$/, "")}" is not supported.`);
1685
- }
1686
- if (parsedURL.protocol === "data:") {
1687
- const data = dist_default(request.url);
1688
- const response2 = new Response(data, { headers: { "Content-Type": data.typeFull } });
1689
- resolve(response2);
1690
- return;
1691
- }
1692
- const send = (parsedURL.protocol === "https:" ? https2 : http2).request;
1693
- const { signal } = request;
1694
- let response = null;
1695
- const abort = () => {
1696
- const error = new AbortError("The operation was aborted.");
1697
- reject(error);
1698
- if (request.body && request.body instanceof Stream2.Readable) {
1699
- request.body.destroy(error);
1700
- }
1701
- if (!response || !response.body) {
1702
- return;
1703
- }
1704
- response.body.emit("error", error);
1705
- };
1706
- if (signal && signal.aborted) {
1707
- abort();
1708
- return;
1709
- }
1710
- const abortAndFinalize = () => {
1711
- abort();
1712
- finalize();
1713
- };
1714
- const request_ = send(parsedURL.toString(), options);
1715
- if (signal) {
1716
- signal.addEventListener("abort", abortAndFinalize);
1717
- }
1718
- const finalize = () => {
1719
- request_.abort();
1720
- if (signal) {
1721
- signal.removeEventListener("abort", abortAndFinalize);
1722
- }
1723
- };
1724
- request_.on("error", (error) => {
1725
- reject(new FetchError(`request to ${request.url} failed, reason: ${error.message}`, "system", error));
1726
- finalize();
1727
- });
1728
- fixResponseChunkedTransferBadEnding(request_, (error) => {
1729
- if (response && response.body) {
1730
- response.body.destroy(error);
1731
- }
1732
- });
1733
- if (process.version < "v14") {
1734
- request_.on("socket", (s) => {
1735
- let endedWithEventsCount;
1736
- s.prependListener("end", () => {
1737
- endedWithEventsCount = s._eventsCount;
1738
- });
1739
- s.prependListener("close", (hadError) => {
1740
- if (response && endedWithEventsCount < s._eventsCount && !hadError) {
1741
- const error = new Error("Premature close");
1742
- error.code = "ERR_STREAM_PREMATURE_CLOSE";
1743
- response.body.emit("error", error);
1744
- }
1745
- });
1746
- });
1747
- }
1748
- request_.on("response", (response_) => {
1749
- request_.setTimeout(0);
1750
- const headers = fromRawHeaders(response_.rawHeaders);
1751
- if (isRedirect(response_.statusCode)) {
1752
- const location = headers.get("Location");
1753
- let locationURL = null;
1754
- try {
1755
- locationURL = location === null ? null : new URL(location, request.url);
1756
- } catch {
1757
- if (request.redirect !== "manual") {
1758
- reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, "invalid-redirect"));
1759
- finalize();
1760
- return;
1761
- }
1762
- }
1763
- switch (request.redirect) {
1764
- case "error":
1765
- reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, "no-redirect"));
1766
- finalize();
1767
- return;
1768
- case "manual":
1769
- break;
1770
- case "follow": {
1771
- if (locationURL === null) {
1772
- break;
1773
- }
1774
- if (request.counter >= request.follow) {
1775
- reject(new FetchError(`maximum redirect reached at: ${request.url}`, "max-redirect"));
1776
- finalize();
1777
- return;
1778
- }
1779
- const requestOptions = {
1780
- headers: new Headers(request.headers),
1781
- follow: request.follow,
1782
- counter: request.counter + 1,
1783
- agent: request.agent,
1784
- compress: request.compress,
1785
- method: request.method,
1786
- body: clone(request),
1787
- signal: request.signal,
1788
- size: request.size,
1789
- referrer: request.referrer,
1790
- referrerPolicy: request.referrerPolicy
1791
- };
1792
- if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) {
1793
- for (const name of ["authorization", "www-authenticate", "cookie", "cookie2"]) {
1794
- requestOptions.headers.delete(name);
1795
- }
1796
- }
1797
- if (response_.statusCode !== 303 && request.body && options_.body instanceof Stream2.Readable) {
1798
- reject(new FetchError("Cannot follow redirect with body being a readable stream", "unsupported-redirect"));
1799
- finalize();
1800
- return;
1801
- }
1802
- if (response_.statusCode === 303 || (response_.statusCode === 301 || response_.statusCode === 302) && request.method === "POST") {
1803
- requestOptions.method = "GET";
1804
- requestOptions.body = void 0;
1805
- requestOptions.headers.delete("content-length");
1806
- }
1807
- const responseReferrerPolicy = parseReferrerPolicyFromHeader(headers);
1808
- if (responseReferrerPolicy) {
1809
- requestOptions.referrerPolicy = responseReferrerPolicy;
1810
- }
1811
- resolve(fetch2(new Request(locationURL, requestOptions)));
1812
- finalize();
1813
- return;
1814
- }
1815
- default:
1816
- return reject(new TypeError(`Redirect option '${request.redirect}' is not a valid value of RequestRedirect`));
1817
- }
1818
- }
1819
- if (signal) {
1820
- response_.once("end", () => {
1821
- signal.removeEventListener("abort", abortAndFinalize);
1822
- });
1823
- }
1824
- let body = pump(response_, new PassThrough2(), (error) => {
1825
- if (error) {
1826
- reject(error);
1827
- }
1828
- });
1829
- if (process.version < "v12.10") {
1830
- response_.on("aborted", abortAndFinalize);
1831
- }
1832
- const responseOptions = {
1833
- url: request.url,
1834
- status: response_.statusCode,
1835
- statusText: response_.statusMessage,
1836
- headers,
1837
- size: request.size,
1838
- counter: request.counter,
1839
- highWaterMark: request.highWaterMark
1840
- };
1841
- const codings = headers.get("Content-Encoding");
1842
- if (!request.compress || request.method === "HEAD" || codings === null || response_.statusCode === 204 || response_.statusCode === 304) {
1843
- response = new Response(body, responseOptions);
1844
- resolve(response);
1845
- return;
1846
- }
1847
- const zlibOptions = {
1848
- flush: zlib.Z_SYNC_FLUSH,
1849
- finishFlush: zlib.Z_SYNC_FLUSH
1850
- };
1851
- if (codings === "gzip" || codings === "x-gzip") {
1852
- body = pump(body, zlib.createGunzip(zlibOptions), (error) => {
1853
- if (error) {
1854
- reject(error);
1855
- }
1856
- });
1857
- response = new Response(body, responseOptions);
1858
- resolve(response);
1859
- return;
1860
- }
1861
- if (codings === "deflate" || codings === "x-deflate") {
1862
- const raw = pump(response_, new PassThrough2(), (error) => {
1863
- if (error) {
1864
- reject(error);
1865
- }
1866
- });
1867
- raw.once("data", (chunk) => {
1868
- if ((chunk[0] & 15) === 8) {
1869
- body = pump(body, zlib.createInflate(), (error) => {
1870
- if (error) {
1871
- reject(error);
1872
- }
1873
- });
1874
- } else {
1875
- body = pump(body, zlib.createInflateRaw(), (error) => {
1876
- if (error) {
1877
- reject(error);
1878
- }
1879
- });
1880
- }
1881
- response = new Response(body, responseOptions);
1882
- resolve(response);
1883
- });
1884
- raw.once("end", () => {
1885
- if (!response) {
1886
- response = new Response(body, responseOptions);
1887
- resolve(response);
1888
- }
1889
- });
1890
- return;
1891
- }
1892
- if (codings === "br") {
1893
- body = pump(body, zlib.createBrotliDecompress(), (error) => {
1894
- if (error) {
1895
- reject(error);
1896
- }
1897
- });
1898
- response = new Response(body, responseOptions);
1899
- resolve(response);
1900
- return;
1901
- }
1902
- response = new Response(body, responseOptions);
1903
- resolve(response);
1904
- });
1905
- writeToStream(request_, request).catch(reject);
1906
- });
1907
- }
1908
- function fixResponseChunkedTransferBadEnding(request, errorCallback) {
1909
- const LAST_CHUNK = Buffer3.from("0\r\n\r\n");
1910
- let isChunkedTransfer = false;
1911
- let properLastChunkReceived = false;
1912
- let previousChunk;
1913
- request.on("response", (response) => {
1914
- const { headers } = response;
1915
- isChunkedTransfer = headers["transfer-encoding"] === "chunked" && !headers["content-length"];
1916
- });
1917
- request.on("socket", (socket) => {
1918
- const onSocketClose = () => {
1919
- if (isChunkedTransfer && !properLastChunkReceived) {
1920
- const error = new Error("Premature close");
1921
- error.code = "ERR_STREAM_PREMATURE_CLOSE";
1922
- errorCallback(error);
1923
- }
1924
- };
1925
- const onData = (buf) => {
1926
- properLastChunkReceived = Buffer3.compare(buf.slice(-5), LAST_CHUNK) === 0;
1927
- if (!properLastChunkReceived && previousChunk) {
1928
- properLastChunkReceived = Buffer3.compare(previousChunk.slice(-3), LAST_CHUNK.slice(0, 3)) === 0 && Buffer3.compare(buf.slice(-2), LAST_CHUNK.slice(3)) === 0;
1929
- }
1930
- previousChunk = buf;
1931
- };
1932
- socket.prependListener("close", onSocketClose);
1933
- socket.on("data", onData);
1934
- request.on("close", () => {
1935
- socket.removeListener("close", onSocketClose);
1936
- socket.removeListener("data", onData);
1937
- });
1938
- });
1939
- }
1940
-
1941
- // src/utils/ollamaManager.ts
602
+ import { ModelType, logger as logger3 } from "@elizaos/core";
1942
603
  var OllamaManager = class _OllamaManager {
1943
604
  static instance = null;
1944
605
  serverUrl;
@@ -1976,7 +637,7 @@ var OllamaManager = class _OllamaManager {
1976
637
  */
1977
638
  async checkServerStatus() {
1978
639
  try {
1979
- const response = await fetch2(`${this.serverUrl}/api/tags`);
640
+ const response = await fetch(`${this.serverUrl}/api/tags`);
1980
641
  if (!response.ok) {
1981
642
  throw new Error(`Server responded with status: ${response.status}`);
1982
643
  }
@@ -1997,7 +658,7 @@ var OllamaManager = class _OllamaManager {
1997
658
  */
1998
659
  async fetchAvailableModels() {
1999
660
  try {
2000
- const response = await fetch2(`${this.serverUrl}/api/tags`);
661
+ const response = await fetch(`${this.serverUrl}/api/tags`);
2001
662
  if (!response.ok) {
2002
663
  throw new Error(`Failed to fetch models: ${response.status}`);
2003
664
  }
@@ -2035,7 +696,7 @@ var OllamaManager = class _OllamaManager {
2035
696
  }
2036
697
  };
2037
698
  logger3.info(`Testing model ${modelId}...`);
2038
- const response = await fetch2(`${this.serverUrl}/api/generate`, {
699
+ const response = await fetch(`${this.serverUrl}/api/generate`, {
2039
700
  method: "POST",
2040
701
  headers: {
2041
702
  "Content-Type": "application/json"
@@ -2151,17 +812,15 @@ var OllamaManager = class _OllamaManager {
2151
812
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
2152
813
  });
2153
814
  if (!this.initialized && !isInitialized) {
2154
- throw new Error(
2155
- "Ollama not initialized. Please initialize before generating text."
2156
- );
815
+ throw new Error("Ollama not initialized. Please initialize before generating text.");
2157
816
  }
2158
817
  logger3.info("Ollama preparing request:", {
2159
- model: params.modelType === ModelTypes.TEXT_LARGE ? this.configuredModels.medium : this.configuredModels.small,
818
+ model: params.modelType === ModelType.TEXT_LARGE ? this.configuredModels.medium : this.configuredModels.small,
2160
819
  contextLength: params.prompt.length,
2161
820
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
2162
821
  });
2163
822
  const request = {
2164
- model: params.modelType === ModelTypes.TEXT_LARGE ? this.configuredModels.medium : this.configuredModels.small,
823
+ model: params.modelType === ModelType.TEXT_LARGE ? this.configuredModels.medium : this.configuredModels.small,
2165
824
  prompt: params.prompt,
2166
825
  stream: false,
2167
826
  options: {
@@ -2173,7 +832,7 @@ var OllamaManager = class _OllamaManager {
2173
832
  presence_penalty: 0.7
2174
833
  }
2175
834
  };
2176
- const response = await fetch2(`${this.serverUrl}/api/generate`, {
835
+ const response = await fetch(`${this.serverUrl}/api/generate`, {
2177
836
  method: "POST",
2178
837
  headers: {
2179
838
  "Content-Type": "application/json"
@@ -2219,9 +878,9 @@ var OllamaManager = class _OllamaManager {
2219
878
  // src/utils/platform.ts
2220
879
  import { exec } from "node:child_process";
2221
880
  import os from "node:os";
2222
- import { promisify as promisify2 } from "node:util";
881
+ import { promisify } from "node:util";
2223
882
  import { logger as logger4 } from "@elizaos/core";
2224
- var execAsync = promisify2(exec);
883
+ var execAsync = promisify(exec);
2225
884
  var PlatformManager = class _PlatformManager {
2226
885
  static instance;
2227
886
  capabilities = null;
@@ -2331,9 +990,7 @@ var PlatformManager = class _PlatformManager {
2331
990
  isAppleSilicon: true
2332
991
  };
2333
992
  }
2334
- const { stdout: gpuInfo } = await execAsync(
2335
- "system_profiler SPDisplaysDataType"
2336
- );
993
+ const { stdout: gpuInfo } = await execAsync("system_profiler SPDisplaysDataType");
2337
994
  return {
2338
995
  name: gpuInfo.split("Chipset Model:")[1]?.split("\n")[0]?.trim() || "Unknown GPU",
2339
996
  type: "metal",
@@ -2355,9 +1012,7 @@ var PlatformManager = class _PlatformManager {
2355
1012
  */
2356
1013
  async detectWindowsGPU() {
2357
1014
  try {
2358
- const { stdout } = await execAsync(
2359
- "wmic path win32_VideoController get name"
2360
- );
1015
+ const { stdout } = await execAsync("wmic path win32_VideoController get name");
2361
1016
  const gpuName = stdout.split("\n")[1].trim();
2362
1017
  if (gpuName.toLowerCase().includes("nvidia")) {
2363
1018
  const { stdout: nvidiaInfo } = await execAsync(
@@ -2550,7 +1205,7 @@ var getPlatformManager = () => {
2550
1205
  };
2551
1206
 
2552
1207
  // src/utils/studiolmManager.ts
2553
- import { ModelTypes as ModelTypes2, logger as logger5 } from "@elizaos/core";
1208
+ import { ModelType as ModelType2, logger as logger5 } from "@elizaos/core";
2554
1209
  var StudioLMManager = class _StudioLMManager {
2555
1210
  static instance = null;
2556
1211
  serverUrl;
@@ -2589,7 +1244,7 @@ var StudioLMManager = class _StudioLMManager {
2589
1244
  */
2590
1245
  async checkServerStatus() {
2591
1246
  try {
2592
- const response = await fetch2(`${this.serverUrl}/v1/models`);
1247
+ const response = await fetch(`${this.serverUrl}/v1/models`);
2593
1248
  if (!response.ok) {
2594
1249
  throw new Error(`Server responded with status: ${response.status}`);
2595
1250
  }
@@ -2610,7 +1265,7 @@ var StudioLMManager = class _StudioLMManager {
2610
1265
  */
2611
1266
  async fetchAvailableModels() {
2612
1267
  try {
2613
- const response = await fetch2(`${this.serverUrl}/v1/models`);
1268
+ const response = await fetch(`${this.serverUrl}/v1/models`);
2614
1269
  if (!response.ok) {
2615
1270
  throw new Error(`Failed to fetch models: ${response.status}`);
2616
1271
  }
@@ -2651,7 +1306,7 @@ var StudioLMManager = class _StudioLMManager {
2651
1306
  stream: false
2652
1307
  };
2653
1308
  logger5.info(`Testing model ${modelId}...`);
2654
- const response = await fetch2(`${this.serverUrl}/v1/chat/completions`, {
1309
+ const response = await fetch(`${this.serverUrl}/v1/chat/completions`, {
2655
1310
  method: "POST",
2656
1311
  headers: {
2657
1312
  "Content-Type": "application/json"
@@ -2768,9 +1423,7 @@ var StudioLMManager = class _StudioLMManager {
2768
1423
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
2769
1424
  });
2770
1425
  if (!this.initialized && !isInitialized) {
2771
- throw new Error(
2772
- "StudioLM not initialized. Please initialize before generating text."
2773
- );
1426
+ throw new Error("StudioLM not initialized. Please initialize before generating text.");
2774
1427
  }
2775
1428
  const messages = [
2776
1429
  {
@@ -2780,7 +1433,7 @@ var StudioLMManager = class _StudioLMManager {
2780
1433
  { role: "user", content: params.prompt }
2781
1434
  ];
2782
1435
  logger5.info("StudioLM preparing request:", {
2783
- model: params.modelType === ModelTypes2.TEXT_LARGE ? this.configuredModels.medium : this.configuredModels.small,
1436
+ model: params.modelType === ModelType2.TEXT_LARGE ? this.configuredModels.medium : this.configuredModels.small,
2784
1437
  messageCount: messages.length,
2785
1438
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
2786
1439
  });
@@ -2791,13 +1444,13 @@ var StudioLMManager = class _StudioLMManager {
2791
1444
  stopSequences: params.stopSequences
2792
1445
  });
2793
1446
  const request = {
2794
- model: params.modelType === ModelTypes2.TEXT_LARGE ? this.configuredModels.medium : this.configuredModels.small,
1447
+ model: params.modelType === ModelType2.TEXT_LARGE ? this.configuredModels.medium : this.configuredModels.small,
2795
1448
  messages,
2796
1449
  temperature: 0.7,
2797
1450
  max_tokens: 8192,
2798
1451
  stream: false
2799
1452
  };
2800
- const response = await fetch2(`${this.serverUrl}/v1/chat/completions`, {
1453
+ const response = await fetch(`${this.serverUrl}/v1/chat/completions`, {
2801
1454
  method: "POST",
2802
1455
  headers: {
2803
1456
  "Content-Type": "application/json"
@@ -2842,9 +1495,7 @@ var StudioLMManager = class _StudioLMManager {
2842
1495
 
2843
1496
  // src/utils/tokenizerManager.ts
2844
1497
  import { logger as logger6 } from "@elizaos/core";
2845
- import {
2846
- AutoTokenizer
2847
- } from "@huggingface/transformers";
1498
+ import { AutoTokenizer } from "@huggingface/transformers";
2848
1499
  var TokenizerManager = class _TokenizerManager {
2849
1500
  static instance = null;
2850
1501
  tokenizers;
@@ -2894,18 +1545,13 @@ var TokenizerManager = class _TokenizerManager {
2894
1545
  logger6.info("Using cached tokenizer:", { key: tokenizerKey });
2895
1546
  const cachedTokenizer = this.tokenizers.get(tokenizerKey);
2896
1547
  if (!cachedTokenizer) {
2897
- throw new Error(
2898
- `Tokenizer ${tokenizerKey} exists in map but returned undefined`
2899
- );
1548
+ throw new Error(`Tokenizer ${tokenizerKey} exists in map but returned undefined`);
2900
1549
  }
2901
1550
  return cachedTokenizer;
2902
1551
  }
2903
1552
  const fs6 = await import("node:fs");
2904
1553
  if (!fs6.existsSync(this.modelsDir)) {
2905
- logger6.warn(
2906
- "Models directory does not exist, creating it:",
2907
- this.modelsDir
2908
- );
1554
+ logger6.warn("Models directory does not exist, creating it:", this.modelsDir);
2909
1555
  fs6.mkdirSync(this.modelsDir, { recursive: true });
2910
1556
  }
2911
1557
  logger6.info(
@@ -2913,13 +1559,10 @@ var TokenizerManager = class _TokenizerManager {
2913
1559
  this.modelsDir
2914
1560
  );
2915
1561
  try {
2916
- const tokenizer = await AutoTokenizer.from_pretrained(
2917
- modelConfig.tokenizer.name,
2918
- {
2919
- cache_dir: this.modelsDir,
2920
- local_files_only: false
2921
- }
2922
- );
1562
+ const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {
1563
+ cache_dir: this.modelsDir,
1564
+ local_files_only: false
1565
+ });
2923
1566
  this.tokenizers.set(tokenizerKey, tokenizer);
2924
1567
  logger6.success("Tokenizer loaded successfully:", { key: tokenizerKey });
2925
1568
  return tokenizer;
@@ -2931,13 +1574,10 @@ var TokenizerManager = class _TokenizerManager {
2931
1574
  modelsDir: this.modelsDir
2932
1575
  });
2933
1576
  logger6.info("Retrying tokenizer loading...");
2934
- const tokenizer = await AutoTokenizer.from_pretrained(
2935
- modelConfig.tokenizer.name,
2936
- {
2937
- cache_dir: this.modelsDir,
2938
- local_files_only: false
2939
- }
2940
- );
1577
+ const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {
1578
+ cache_dir: this.modelsDir,
1579
+ local_files_only: false
1580
+ });
2941
1581
  this.tokenizers.set(tokenizerKey, tokenizer);
2942
1582
  logger6.success("Tokenizer loaded successfully on retry:", {
2943
1583
  key: tokenizerKey
@@ -3033,10 +1673,10 @@ var TokenizerManager = class _TokenizerManager {
3033
1673
  import { exec as exec2 } from "node:child_process";
3034
1674
  import fs2 from "node:fs";
3035
1675
  import path2 from "node:path";
3036
- import { promisify as promisify3 } from "node:util";
1676
+ import { promisify as promisify2 } from "node:util";
3037
1677
  import { logger as logger7 } from "@elizaos/core";
3038
1678
  import { nodewhisper } from "nodejs-whisper";
3039
- var execAsync2 = promisify3(exec2);
1679
+ var execAsync2 = promisify2(exec2);
3040
1680
  var TranscribeManager = class _TranscribeManager {
3041
1681
  static instance = null;
3042
1682
  cacheDir;
@@ -3051,7 +1691,7 @@ var TranscribeManager = class _TranscribeManager {
3051
1691
  */
3052
1692
  constructor(cacheDir) {
3053
1693
  this.cacheDir = path2.join(cacheDir, "whisper");
3054
- logger7.info("Initializing TranscribeManager", {
1694
+ logger7.debug("Initializing TranscribeManager", {
3055
1695
  cacheDir: this.cacheDir,
3056
1696
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
3057
1697
  });
@@ -3156,9 +1796,7 @@ var TranscribeManager = class _TranscribeManager {
3156
1796
  */
3157
1797
  async checkFFmpegAvailability() {
3158
1798
  try {
3159
- const { stdout, stderr } = await execAsync2(
3160
- "which ffmpeg || where ffmpeg"
3161
- );
1799
+ const { stdout, stderr } = await execAsync2("which ffmpeg || where ffmpeg");
3162
1800
  this.ffmpegPath = stdout.trim();
3163
1801
  this.ffmpegAvailable = true;
3164
1802
  logger7.info("FFmpeg found at:", {
@@ -3186,9 +1824,7 @@ var TranscribeManager = class _TranscribeManager {
3186
1824
  const { stdout } = await execAsync2("ffmpeg -codecs");
3187
1825
  const hasRequiredCodecs = stdout.includes("pcm_s16le") && stdout.includes("wav");
3188
1826
  if (!hasRequiredCodecs) {
3189
- throw new Error(
3190
- "FFmpeg installation missing required codecs (pcm_s16le, wav)"
3191
- );
1827
+ throw new Error("FFmpeg installation missing required codecs (pcm_s16le, wav)");
3192
1828
  }
3193
1829
  } catch (error) {
3194
1830
  logger7.error("FFmpeg capabilities verification failed:", {
@@ -3202,20 +1838,17 @@ var TranscribeManager = class _TranscribeManager {
3202
1838
  * Logs instructions on how to install FFmpeg if it is not properly installed.
3203
1839
  */
3204
1840
  logFFmpegInstallInstructions() {
3205
- logger7.warn(
3206
- "FFmpeg is required but not properly installed. Please install FFmpeg:",
3207
- {
3208
- instructions: {
3209
- mac: "brew install ffmpeg",
3210
- ubuntu: "sudo apt-get install ffmpeg",
3211
- windows: "choco install ffmpeg",
3212
- manual: "Download from https://ffmpeg.org/download.html"
3213
- },
3214
- requiredVersion: "4.0 or later",
3215
- requiredCodecs: ["pcm_s16le", "wav"],
3216
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
3217
- }
3218
- );
1841
+ logger7.warn("FFmpeg is required but not properly installed. Please install FFmpeg:", {
1842
+ instructions: {
1843
+ mac: "brew install ffmpeg",
1844
+ ubuntu: "sudo apt-get install ffmpeg",
1845
+ windows: "choco install ffmpeg",
1846
+ manual: "Download from https://ffmpeg.org/download.html"
1847
+ },
1848
+ requiredVersion: "4.0 or later",
1849
+ requiredCodecs: ["pcm_s16le", "wav"],
1850
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1851
+ });
3219
1852
  }
3220
1853
  /**
3221
1854
  * Gets the singleton instance of TranscribeManager, creates a new instance if it doesn't exist.
@@ -3293,15 +1926,10 @@ var TranscribeManager = class _TranscribeManager {
3293
1926
  */
3294
1927
  async preprocessAudio(audioBuffer) {
3295
1928
  if (!this.ffmpegAvailable) {
3296
- throw new Error(
3297
- "FFmpeg is not installed. Please install FFmpeg to use audio transcription."
3298
- );
1929
+ throw new Error("FFmpeg is not installed. Please install FFmpeg to use audio transcription.");
3299
1930
  }
3300
1931
  try {
3301
- const tempInputFile = path2.join(
3302
- this.cacheDir,
3303
- `temp_input_${Date.now()}`
3304
- );
1932
+ const tempInputFile = path2.join(this.cacheDir, `temp_input_${Date.now()}`);
3305
1933
  const tempWavFile = path2.join(this.cacheDir, `temp_${Date.now()}.wav`);
3306
1934
  fs2.writeFileSync(tempInputFile, audioBuffer);
3307
1935
  await this.convertToWav(tempInputFile, tempWavFile);
@@ -3392,7 +2020,7 @@ import {
3392
2020
  } from "node-llama-cpp";
3393
2021
 
3394
2022
  // src/utils/audioUtils.ts
3395
- import { PassThrough as PassThrough3 } from "node:stream";
2023
+ import { PassThrough } from "node:stream";
3396
2024
  function getWavHeader(audioLength, sampleRate, channelCount = 1, bitsPerSample = 16) {
3397
2025
  const wavHeader = Buffer.alloc(44);
3398
2026
  wavHeader.write("RIFF", 0);
@@ -3411,14 +2039,9 @@ function getWavHeader(audioLength, sampleRate, channelCount = 1, bitsPerSample =
3411
2039
  return wavHeader;
3412
2040
  }
3413
2041
  function prependWavHeader(readable, audioLength, sampleRate, channelCount = 1, bitsPerSample = 16) {
3414
- const wavHeader = getWavHeader(
3415
- audioLength,
3416
- sampleRate,
3417
- channelCount,
3418
- bitsPerSample
3419
- );
2042
+ const wavHeader = getWavHeader(audioLength, sampleRate, channelCount, bitsPerSample);
3420
2043
  let pushedHeader = false;
3421
- const passThrough = new PassThrough3();
2044
+ const passThrough = new PassThrough();
3422
2045
  readable.on("data", (data) => {
3423
2046
  if (!pushedHeader) {
3424
2047
  passThrough.push(wavHeader);
@@ -3450,12 +2073,9 @@ var TTSManager = class _TTSManager {
3450
2073
  constructor(cacheDir) {
3451
2074
  this.cacheDir = path3.join(cacheDir, "tts");
3452
2075
  this.modelsDir = process.env.LLAMALOCAL_PATH?.trim() ? path3.resolve(process.env.LLAMALOCAL_PATH.trim()) : path3.join(process.cwd(), "models");
3453
- this.downloadManager = DownloadManager.getInstance(
3454
- this.cacheDir,
3455
- this.modelsDir
3456
- );
2076
+ this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);
3457
2077
  this.ensureCacheDirectory();
3458
- logger8.info("TTSManager initialized");
2078
+ logger8.debug("TTSManager initialized");
3459
2079
  }
3460
2080
  /**
3461
2081
  * Returns an instance of TTSManager, creating a new one if none exist.
@@ -3475,7 +2095,7 @@ var TTSManager = class _TTSManager {
3475
2095
  ensureCacheDirectory() {
3476
2096
  if (!fs3.existsSync(this.cacheDir)) {
3477
2097
  fs3.mkdirSync(this.cacheDir, { recursive: true });
3478
- logger8.info("Created TTS cache directory:", this.cacheDir);
2098
+ logger8.debug("Created TTS cache directory:", this.cacheDir);
3479
2099
  }
3480
2100
  }
3481
2101
  /**
@@ -3529,10 +2149,7 @@ var TTSManager = class _TTSManager {
3529
2149
  await this.downloadManager.downloadFromUrl(attempt.url, modelPath);
3530
2150
  const completedBar = "\u25B0".repeat(barLength);
3531
2151
  logger8.info(`Downloading TTS model: ${completedBar} 100%`);
3532
- logger8.success(
3533
- "TTS model download successful with:",
3534
- attempt.description
3535
- );
2152
+ logger8.success("TTS model download successful with:", attempt.description);
3536
2153
  break;
3537
2154
  } catch (error) {
3538
2155
  lastError = error;
@@ -3604,9 +2221,7 @@ var TTSManager = class _TTSManager {
3604
2221
  responseTokens.push(token);
3605
2222
  const percent = Math.round(responseTokens.length / maxTokens * 100);
3606
2223
  const barLength = 30;
3607
- const filledLength = Math.floor(
3608
- responseTokens.length / maxTokens * barLength
3609
- );
2224
+ const filledLength = Math.floor(responseTokens.length / maxTokens * barLength);
3610
2225
  const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
3611
2226
  logger8.info(
3612
2227
  `Token generation: ${progressBar} ${percent}% (${responseTokens.length}/${maxTokens})`
@@ -3625,9 +2240,7 @@ var TTSManager = class _TTSManager {
3625
2240
  }
3626
2241
  logger8.info("Converting tokens to audio data...");
3627
2242
  const audioData = this.processAudioResponse({
3628
- tokens: responseTokens.map(
3629
- (t) => Number.parseInt(this.model.detokenize([t]), 10)
3630
- )
2243
+ tokens: responseTokens.map((t) => Number.parseInt(this.model.detokenize([t]), 10))
3631
2244
  });
3632
2245
  logger8.info("Audio data generated:", {
3633
2246
  byteLength: audioData.length,
@@ -3721,12 +2334,9 @@ var VisionManager = class _VisionManager {
3721
2334
  this.modelsDir = path4.join(path4.dirname(cacheDir), "models", "vision");
3722
2335
  this.cacheDir = cacheDir;
3723
2336
  this.ensureModelsDirExists();
3724
- this.downloadManager = DownloadManager.getInstance(
3725
- this.cacheDir,
3726
- this.modelsDir
3727
- );
2337
+ this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);
3728
2338
  this.platformConfig = this.getPlatformConfig();
3729
- logger9.info("VisionManager initialized");
2339
+ logger9.debug("VisionManager initialized");
3730
2340
  }
3731
2341
  /**
3732
2342
  * Retrieves the platform configuration based on the operating system and architecture.
@@ -3756,11 +2366,6 @@ var VisionManager = class _VisionManager {
3756
2366
  };
3757
2367
  }
3758
2368
  }
3759
- logger9.info("Platform configuration detected:", {
3760
- platform,
3761
- arch,
3762
- config
3763
- });
3764
2369
  return config;
3765
2370
  }
3766
2371
  /**
@@ -3768,7 +2373,7 @@ var VisionManager = class _VisionManager {
3768
2373
  */
3769
2374
  ensureModelsDirExists() {
3770
2375
  if (!existsSync(this.modelsDir)) {
3771
- logger9.info(`Creating models directory at: ${this.modelsDir}`);
2376
+ logger9.debug(`Creating models directory at: ${this.modelsDir}`);
3772
2377
  fs4.mkdirSync(this.modelsDir, { recursive: true });
3773
2378
  }
3774
2379
  }
@@ -3793,11 +2398,7 @@ var VisionManager = class _VisionManager {
3793
2398
  * @returns {boolean} - Returns true if cache exists, otherwise returns false.
3794
2399
  */
3795
2400
  checkCacheExists(modelId, type) {
3796
- const modelPath = path4.join(
3797
- this.modelsDir,
3798
- modelId.replace("/", "--"),
3799
- type
3800
- );
2401
+ const modelPath = path4.join(this.modelsDir, modelId.replace("/", "--"), type);
3801
2402
  if (existsSync(modelPath)) {
3802
2403
  logger9.info(`${type} found at: ${modelPath}`);
3803
2404
  return true;
@@ -3835,9 +2436,7 @@ var VisionManager = class _VisionManager {
3835
2436
  * @returns {object} The model configuration object containing device, dtype, and cache_dir.
3836
2437
  */
3837
2438
  getModelConfig(componentName) {
3838
- const component = this.modelComponents.find(
3839
- (c) => c.name === componentName
3840
- );
2439
+ const component = this.modelComponents.find((c) => c.name === componentName);
3841
2440
  return {
3842
2441
  device: this.platformConfig.device,
3843
2442
  dtype: component?.dtype || "fp32",
@@ -3853,9 +2452,7 @@ var VisionManager = class _VisionManager {
3853
2452
  async initialize() {
3854
2453
  try {
3855
2454
  if (this.initialized) {
3856
- logger9.info(
3857
- "Vision model already initialized, skipping initialization"
3858
- );
2455
+ logger9.info("Vision model already initialized, skipping initialization");
3859
2456
  return;
3860
2457
  }
3861
2458
  logger9.info("Starting vision model initialization...");
@@ -3871,32 +2468,25 @@ var VisionManager = class _VisionManager {
3871
2468
  try {
3872
2469
  let lastProgress = -1;
3873
2470
  const modelCached = this.checkCacheExists(modelSpec.modelId, "model");
3874
- const model = await Florence2ForConditionalGeneration.from_pretrained(
3875
- modelSpec.modelId,
3876
- {
3877
- device: "cpu",
3878
- cache_dir: this.modelsDir,
3879
- local_files_only: modelCached,
3880
- revision: "main",
3881
- progress_callback: (progressInfo) => {
3882
- if (modelCached || this.modelDownloaded) return;
3883
- const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
3884
- const currentProgress = Math.round(progress * 100);
3885
- if (currentProgress > lastProgress + 9 || currentProgress === 100) {
3886
- lastProgress = currentProgress;
3887
- const barLength = 30;
3888
- const filledLength = Math.floor(
3889
- currentProgress / 100 * barLength
3890
- );
3891
- const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
3892
- logger9.info(
3893
- `Downloading vision model: ${progressBar} ${currentProgress}%`
3894
- );
3895
- if (currentProgress === 100) this.modelDownloaded = true;
3896
- }
2471
+ const model = await Florence2ForConditionalGeneration.from_pretrained(modelSpec.modelId, {
2472
+ device: "cpu",
2473
+ cache_dir: this.modelsDir,
2474
+ local_files_only: modelCached,
2475
+ revision: "main",
2476
+ progress_callback: (progressInfo) => {
2477
+ if (modelCached || this.modelDownloaded) return;
2478
+ const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
2479
+ const currentProgress = Math.round(progress * 100);
2480
+ if (currentProgress > lastProgress + 9 || currentProgress === 100) {
2481
+ lastProgress = currentProgress;
2482
+ const barLength = 30;
2483
+ const filledLength = Math.floor(currentProgress / 100 * barLength);
2484
+ const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
2485
+ logger9.info(`Downloading vision model: ${progressBar} ${currentProgress}%`);
2486
+ if (currentProgress === 100) this.modelDownloaded = true;
3897
2487
  }
3898
2488
  }
3899
- );
2489
+ });
3900
2490
  this.model = model;
3901
2491
  logger9.success("Florence2 model loaded successfully");
3902
2492
  } catch (error) {
@@ -3909,35 +2499,25 @@ var VisionManager = class _VisionManager {
3909
2499
  }
3910
2500
  logger9.info("Loading vision tokenizer...");
3911
2501
  try {
3912
- const tokenizerCached = this.checkCacheExists(
3913
- modelSpec.modelId,
3914
- "tokenizer"
3915
- );
2502
+ const tokenizerCached = this.checkCacheExists(modelSpec.modelId, "tokenizer");
3916
2503
  let tokenizerProgress = -1;
3917
- this.tokenizer = await AutoTokenizer2.from_pretrained(
3918
- modelSpec.modelId,
3919
- {
3920
- cache_dir: this.modelsDir,
3921
- local_files_only: tokenizerCached,
3922
- progress_callback: (progressInfo) => {
3923
- if (tokenizerCached || this.tokenizerDownloaded) return;
3924
- const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
3925
- const currentProgress = Math.round(progress * 100);
3926
- if (currentProgress !== tokenizerProgress) {
3927
- tokenizerProgress = currentProgress;
3928
- const barLength = 30;
3929
- const filledLength = Math.floor(
3930
- currentProgress / 100 * barLength
3931
- );
3932
- const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
3933
- logger9.info(
3934
- `Downloading vision tokenizer: ${progressBar} ${currentProgress}%`
3935
- );
3936
- if (currentProgress === 100) this.tokenizerDownloaded = true;
3937
- }
2504
+ this.tokenizer = await AutoTokenizer2.from_pretrained(modelSpec.modelId, {
2505
+ cache_dir: this.modelsDir,
2506
+ local_files_only: tokenizerCached,
2507
+ progress_callback: (progressInfo) => {
2508
+ if (tokenizerCached || this.tokenizerDownloaded) return;
2509
+ const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
2510
+ const currentProgress = Math.round(progress * 100);
2511
+ if (currentProgress !== tokenizerProgress) {
2512
+ tokenizerProgress = currentProgress;
2513
+ const barLength = 30;
2514
+ const filledLength = Math.floor(currentProgress / 100 * barLength);
2515
+ const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
2516
+ logger9.info(`Downloading vision tokenizer: ${progressBar} ${currentProgress}%`);
2517
+ if (currentProgress === 100) this.tokenizerDownloaded = true;
3938
2518
  }
3939
2519
  }
3940
- );
2520
+ });
3941
2521
  logger9.success("Vision tokenizer loaded successfully");
3942
2522
  } catch (error) {
3943
2523
  logger9.error("Failed to load tokenizer:", {
@@ -3949,36 +2529,26 @@ var VisionManager = class _VisionManager {
3949
2529
  }
3950
2530
  logger9.info("Loading vision processor...");
3951
2531
  try {
3952
- const processorCached = this.checkCacheExists(
3953
- modelSpec.modelId,
3954
- "processor"
3955
- );
2532
+ const processorCached = this.checkCacheExists(modelSpec.modelId, "processor");
3956
2533
  let processorProgress = -1;
3957
- this.processor = await AutoProcessor.from_pretrained(
3958
- modelSpec.modelId,
3959
- {
3960
- device: "cpu",
3961
- cache_dir: this.modelsDir,
3962
- local_files_only: processorCached,
3963
- progress_callback: (progressInfo) => {
3964
- if (processorCached || this.processorDownloaded) return;
3965
- const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
3966
- const currentProgress = Math.round(progress * 100);
3967
- if (currentProgress !== processorProgress) {
3968
- processorProgress = currentProgress;
3969
- const barLength = 30;
3970
- const filledLength = Math.floor(
3971
- currentProgress / 100 * barLength
3972
- );
3973
- const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
3974
- logger9.info(
3975
- `Downloading vision processor: ${progressBar} ${currentProgress}%`
3976
- );
3977
- if (currentProgress === 100) this.processorDownloaded = true;
3978
- }
2534
+ this.processor = await AutoProcessor.from_pretrained(modelSpec.modelId, {
2535
+ device: "cpu",
2536
+ cache_dir: this.modelsDir,
2537
+ local_files_only: processorCached,
2538
+ progress_callback: (progressInfo) => {
2539
+ if (processorCached || this.processorDownloaded) return;
2540
+ const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
2541
+ const currentProgress = Math.round(progress * 100);
2542
+ if (currentProgress !== processorProgress) {
2543
+ processorProgress = currentProgress;
2544
+ const barLength = 30;
2545
+ const filledLength = Math.floor(currentProgress / 100 * barLength);
2546
+ const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
2547
+ logger9.info(`Downloading vision processor: ${progressBar} ${currentProgress}%`);
2548
+ if (currentProgress === 100) this.processorDownloaded = true;
3979
2549
  }
3980
2550
  }
3981
- );
2551
+ });
3982
2552
  logger9.success("Vision processor loaded successfully");
3983
2553
  } catch (error) {
3984
2554
  logger9.error("Failed to load vision processor:", {
@@ -4178,141 +2748,65 @@ var LocalAIManager = class _LocalAIManager {
4178
2748
  ttsManager;
4179
2749
  studioLMManager;
4180
2750
  ollamaManager;
2751
+ // Initialization state flags
4181
2752
  ollamaInitialized = false;
4182
2753
  studioLMInitialized = false;
2754
+ smallModelInitialized = false;
2755
+ mediumModelInitialized = false;
2756
+ embeddingInitialized = false;
2757
+ visionInitialized = false;
2758
+ transcriptionInitialized = false;
2759
+ ttsInitialized = false;
2760
+ // Initialization promises to prevent duplicate initialization
2761
+ smallModelInitializingPromise = null;
2762
+ mediumModelInitializingPromise = null;
2763
+ embeddingInitializingPromise = null;
2764
+ visionInitializingPromise = null;
2765
+ transcriptionInitializingPromise = null;
2766
+ ttsInitializingPromise = null;
2767
+ ollamaInitializingPromise = null;
2768
+ studioLMInitializingPromise = null;
4183
2769
  modelsDir;
4184
2770
  /**
4185
- * Private constructor function to initialize various managers and services.
4186
- * This function sets up model directories, initializes managers for download, tokenizer, vision, transcribe, and TTS.
4187
- * It also initializes StudioLM and Ollama managers if enabled in the environment.
4188
- * Additionally, this function initializes the environment, checks platform capabilities, sets up embeddings,
4189
- * and initializes various models and services sequentially and in parallel to avoid conflicts.
2771
+ * Private constructor function to initialize base managers and paths.
2772
+ * This now only sets up the basic infrastructure without loading any models.
4190
2773
  */
4191
2774
  constructor() {
4192
2775
  const modelsDir = path5.join(process.cwd(), "models");
4193
- this.activeModelConfig = MODEL_SPECS.small;
4194
- this.modelPath = path5.join(modelsDir, MODEL_SPECS.small.name);
4195
- this.mediumModelPath = path5.join(modelsDir, MODEL_SPECS.medium.name);
4196
- this.cacheDir = path5.join(process.cwd(), "./cache");
4197
- this.modelsDir = modelsDir;
4198
- this.downloadManager = DownloadManager.getInstance(
4199
- this.cacheDir,
4200
- this.modelsDir
4201
- );
4202
- this.tokenizerManager = TokenizerManager.getInstance(
4203
- this.cacheDir,
4204
- this.modelsDir
4205
- );
4206
- this.visionManager = VisionManager.getInstance(this.cacheDir);
4207
- this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);
4208
- this.ttsManager = TTSManager.getInstance(this.cacheDir);
4209
- if (process.env.USE_STUDIOLM_TEXT_MODELS === "true") {
4210
- logger10.info(
4211
- "Creating StudioLM manager instance (enabled in environment)"
4212
- );
4213
- this.studioLMManager = StudioLMManager.getInstance();
2776
+ if (process.env.LLAMALOCAL_PATH?.trim()) {
2777
+ this.modelsDir = path5.resolve(process.env.LLAMALOCAL_PATH.trim());
4214
2778
  } else {
4215
- logger10.info(
4216
- "StudioLM manager instance not created (disabled in environment)"
4217
- );
4218
- }
4219
- if (process.env.USE_OLLAMA_TEXT_MODELS === "true") {
4220
- logger10.info("Creating Ollama manager instance (enabled in environment)");
4221
- this.ollamaManager = OllamaManager.getInstance();
4222
- } else {
4223
- logger10.info(
4224
- "Ollama manager instance not created (disabled in environment)"
4225
- );
4226
- }
4227
- this.initializeEnvironment().catch((error) => {
4228
- logger10.error("Environment initialization failed:", error);
4229
- throw error;
4230
- });
4231
- this.checkPlatformCapabilities().catch((error) => {
4232
- logger10.warn("Platform capabilities check failed:", error);
4233
- });
4234
- this.initializeEmbedding().catch((error) => {
4235
- logger10.warn("Embedding initialization failed:", error);
4236
- });
4237
- logger10.info("Starting model initialization sequence");
4238
- this.initialize(ModelTypes3.TEXT_SMALL).then(() => {
4239
- logger10.info(
4240
- "Small model initialization complete, starting large model initialization"
4241
- );
4242
- return this.initialize(ModelTypes3.TEXT_LARGE);
4243
- }).catch((error) => {
4244
- logger10.warn("Models initialization failed:", {
4245
- stack: error instanceof Error ? error.stack : void 0,
4246
- error: error instanceof Error ? error.message : String(error)
4247
- });
4248
- });
4249
- const servicePromises = [
4250
- // Add vision initialization using a public method
4251
- this.initializeVision().catch((error) => {
4252
- logger10.warn("Vision initialization failed:", error);
4253
- return null;
4254
- }),
4255
- // Add transcription initialization with better error handling
4256
- this.initializeTranscription().catch((error) => {
4257
- logger10.warn("Transcription initialization failed:", {
4258
- error: error instanceof Error ? error.message : String(error),
4259
- stack: error instanceof Error ? error.stack : void 0
4260
- });
4261
- return null;
4262
- }),
4263
- // Add TTS initialization
4264
- this.initializeTTS().catch((error) => {
4265
- logger10.warn("TTS initialization failed:", {
4266
- error: error instanceof Error ? error.message : String(error),
4267
- stack: error instanceof Error ? error.stack : void 0
4268
- });
4269
- return null;
4270
- })
4271
- ];
4272
- if (process.env.USE_STUDIOLM_TEXT_MODELS === "true" && this.studioLMManager) {
4273
- logger10.info(
4274
- "StudioLM initialization enabled by environment configuration"
4275
- );
4276
- servicePromises.push(
4277
- this.initializeStudioLM().then(() => {
4278
- this.studioLMInitialized = true;
4279
- }).catch((error) => {
4280
- logger10.warn("StudioLM initialization failed:", {
4281
- error: error instanceof Error ? error.message : String(error),
4282
- stack: error instanceof Error ? error.stack : void 0
4283
- });
4284
- return null;
4285
- })
4286
- );
4287
- } else {
4288
- logger10.info(
4289
- "StudioLM initialization skipped (disabled in environment configuration or manager not created)"
4290
- );
2779
+ if (!fs5.existsSync(modelsDir)) {
2780
+ fs5.mkdirSync(modelsDir, { recursive: true });
2781
+ logger10.debug("Created models directory");
2782
+ }
2783
+ this.modelsDir = modelsDir;
4291
2784
  }
4292
- if (process.env.USE_OLLAMA_TEXT_MODELS === "true" && this.ollamaManager) {
4293
- logger10.info("Ollama initialization enabled by environment configuration");
4294
- servicePromises.push(
4295
- this.initializeOllama().then(() => {
4296
- this.ollamaInitialized = true;
4297
- }).catch((error) => {
4298
- logger10.warn("Ollama initialization failed:", {
4299
- error: error instanceof Error ? error.message : String(error),
4300
- stack: error instanceof Error ? error.stack : void 0
4301
- });
4302
- return null;
4303
- })
4304
- );
2785
+ this.modelPath = path5.join(this.modelsDir, "DeepHermes-3-Llama-3-3B-Preview-q4.gguf");
2786
+ this.mediumModelPath = path5.join(this.modelsDir, "DeepHermes-3-Llama-3-8B-q4.gguf");
2787
+ const cacheDirEnv = process.env.CACHE_DIR?.trim();
2788
+ if (cacheDirEnv) {
2789
+ this.cacheDir = path5.resolve(cacheDirEnv);
4305
2790
  } else {
4306
- logger10.info(
4307
- "Ollama initialization skipped (disabled in environment configuration or manager not created)"
4308
- );
2791
+ const cacheDir = path5.join(process.cwd(), "cache");
2792
+ if (!fs5.existsSync(cacheDir)) {
2793
+ fs5.mkdirSync(cacheDir, { recursive: true });
2794
+ logger10.debug("Ensuring cache directory exists:", cacheDir);
2795
+ }
2796
+ this.cacheDir = cacheDir;
4309
2797
  }
4310
- Promise.all(servicePromises).catch((error) => {
4311
- logger10.warn("Models initialization failed:", {
4312
- error: error instanceof Error ? error.message : String(error),
4313
- stack: error instanceof Error ? error.stack : void 0
4314
- });
4315
- });
2798
+ this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);
2799
+ this.tokenizerManager = TokenizerManager.getInstance(this.cacheDir, this.modelsDir);
2800
+ this.visionManager = VisionManager.getInstance(this.cacheDir);
2801
+ this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);
2802
+ this.ttsManager = TTSManager.getInstance(this.cacheDir);
2803
+ if (process.env.USE_STUDIOLM_TEXT_MODELS === "true") {
2804
+ this.studioLMManager = StudioLMManager.getInstance();
2805
+ }
2806
+ if (process.env.USE_OLLAMA_TEXT_MODELS === "true") {
2807
+ this.ollamaManager = OllamaManager.getInstance();
2808
+ }
2809
+ this.activeModelConfig = MODEL_SPECS.small;
4316
2810
  }
4317
2811
  /**
4318
2812
  * Retrieves the singleton instance of LocalAIManager. If an instance does not already exist, a new one is created and returned.
@@ -4340,12 +2834,8 @@ var LocalAIManager = class _LocalAIManager {
4340
2834
  const validatedConfig = await validateConfig(config);
4341
2835
  logger10.info("Environment configuration validated");
4342
2836
  process.env.USE_LOCAL_AI = String(validatedConfig.USE_LOCAL_AI);
4343
- process.env.USE_STUDIOLM_TEXT_MODELS = String(
4344
- validatedConfig.USE_STUDIOLM_TEXT_MODELS
4345
- );
4346
- process.env.USE_OLLAMA_TEXT_MODELS = String(
4347
- validatedConfig.USE_OLLAMA_TEXT_MODELS
4348
- );
2837
+ process.env.USE_STUDIOLM_TEXT_MODELS = String(validatedConfig.USE_STUDIOLM_TEXT_MODELS);
2838
+ process.env.USE_OLLAMA_TEXT_MODELS = String(validatedConfig.USE_OLLAMA_TEXT_MODELS);
4349
2839
  logger10.success("Environment initialization complete");
4350
2840
  } catch (error) {
4351
2841
  logger10.error("Environment validation failed:", {
@@ -4369,9 +2859,7 @@ var LocalAIManager = class _LocalAIManager {
4369
2859
  }
4370
2860
  await this.ollamaManager.initialize();
4371
2861
  if (!this.ollamaManager.isInitialized()) {
4372
- throw new Error(
4373
- "Ollama initialization failed - models not properly loaded"
4374
- );
2862
+ throw new Error("Ollama initialization failed - models not properly loaded");
4375
2863
  }
4376
2864
  logger10.success("Ollama initialization complete");
4377
2865
  } catch (error) {
@@ -4396,9 +2884,7 @@ var LocalAIManager = class _LocalAIManager {
4396
2884
  }
4397
2885
  await this.studioLMManager.initialize();
4398
2886
  if (!this.studioLMManager.isInitialized()) {
4399
- throw new Error(
4400
- "StudioLM initialization failed - models not properly loaded"
4401
- );
2887
+ throw new Error("StudioLM initialization failed - models not properly loaded");
4402
2888
  }
4403
2889
  this.studioLMInitialized = true;
4404
2890
  logger10.success("StudioLM initialization complete");
@@ -4411,169 +2897,21 @@ var LocalAIManager = class _LocalAIManager {
4411
2897
  throw error;
4412
2898
  }
4413
2899
  }
4414
- /**
4415
- * Asynchronously initializes the transcription model by performing the following steps:
4416
- * 1. Ensuring FFmpeg availability.
4417
- * 2. Defining sample file path and AWS URL.
4418
- * 3. Downloading the sample file if it doesn't exist in the cache.
4419
- * 4. Verifying the existence of the sample file and loading it.
4420
- * 5. Generating transcription result using the transcribeAudio method.
4421
- *
4422
- * @returns {Promise<void>} A Promise that resolves when the initialization process is complete or rejects with an error.
4423
- */
4424
- async initializeTranscription() {
4425
- try {
4426
- logger10.info("Initializing transcription model...");
4427
- const ffmpegAvailable = await this.transcribeManager.ensureFFmpeg();
4428
- if (!ffmpegAvailable) {
4429
- throw new Error(
4430
- "Cannot initialize transcription without FFmpeg. Please install FFmpeg and try again."
4431
- );
4432
- }
4433
- const samplePath = path5.join(this.cacheDir, "sample1.wav");
4434
- const awsSampleUrl = "https://d2908q01vomqb2.cloudfront.net/artifacts/DBSBlogs/ML-15311/sample1.wav?_=1";
4435
- if (!fs5.existsSync(samplePath)) {
4436
- logger10.info(
4437
- "Sample WAV file not found in cache, downloading from AWS..."
4438
- );
4439
- try {
4440
- await this.downloadManager.downloadFromUrl(awsSampleUrl, samplePath);
4441
- logger10.success("Sample WAV file downloaded successfully");
4442
- } catch (downloadError) {
4443
- logger10.error("Failed to download sample WAV file:", {
4444
- error: downloadError instanceof Error ? downloadError.message : String(downloadError),
4445
- url: awsSampleUrl,
4446
- destination: samplePath,
4447
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4448
- });
4449
- throw downloadError;
4450
- }
4451
- } else {
4452
- logger10.info("Sample WAV file already exists in cache");
4453
- }
4454
- if (!fs5.existsSync(samplePath)) {
4455
- throw new Error(
4456
- `Sample audio file not found at: ${samplePath} after download attempt`
4457
- );
4458
- }
4459
- const testAudioBuffer = fs5.readFileSync(samplePath);
4460
- const result = await this.transcribeAudio(testAudioBuffer);
4461
- logger10.info("Test transcription result:", {
4462
- text: result,
4463
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4464
- });
4465
- logger10.success("Transcription model initialization complete");
4466
- } catch (error) {
4467
- logger10.error("Transcription initialization failed:", {
4468
- error: error instanceof Error ? error.message : String(error),
4469
- stack: error instanceof Error ? error.stack : void 0,
4470
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4471
- });
4472
- throw error;
4473
- }
4474
- }
4475
- /**
4476
- * Asynchronously initializes the vision by downloading a test image from AWS, processing it, and describing the image.
4477
- *
4478
- * @returns A Promise that resolves when the vision is successfully initialized
4479
- */
4480
- async initializeVision() {
4481
- try {
4482
- logger10.info("Initializing vision model...");
4483
- const awsImageUrl = "https://d1.awsstatic.com/product-marketing/Rekognition/Image%20for%20facial%20analysis.3fcc22e8451b4a238540128cb5510b8cbe22da51.jpg";
4484
- const imagePath = path5.join(this.cacheDir, "test_image.jpg");
4485
- if (!fs5.existsSync(imagePath)) {
4486
- logger10.info("Downloading test image from AWS...");
4487
- try {
4488
- await this.downloadManager.downloadFromUrl(awsImageUrl, imagePath);
4489
- logger10.success("Test image downloaded successfully");
4490
- } catch (downloadError) {
4491
- logger10.error("Failed to download test image:", {
4492
- error: downloadError instanceof Error ? downloadError.message : String(downloadError),
4493
- url: awsImageUrl,
4494
- destination: imagePath
4495
- });
4496
- throw downloadError;
4497
- }
4498
- } else {
4499
- logger10.info("Test image already exists in cache");
4500
- }
4501
- if (!fs5.existsSync(imagePath)) {
4502
- throw new Error(
4503
- `Test image not found at: ${imagePath} after download attempt`
4504
- );
4505
- }
4506
- const imageBuffer = fs5.readFileSync(imagePath);
4507
- const result = await this.describeImage(imageBuffer, "image/jpeg");
4508
- logger10.info("Test image description:", result);
4509
- logger10.success("Vision model initialization complete");
4510
- } catch (error) {
4511
- logger10.error("Vision initialization failed:", error);
4512
- throw error;
4513
- }
4514
- }
4515
- /**
4516
- * Asynchronously initializes the Text-to-Speech (TTS) model by testing TTS with sample text,
4517
- * generating speech, and verifying the audio stream readability.
4518
- *
4519
- * @returns {Promise<void>} A Promise that resolves when the TTS model initialization is complete.
4520
- */
4521
- async initializeTTS() {
4522
- try {
4523
- logger10.info("Initializing TTS model...");
4524
- const testText = "ElizaOS is yours";
4525
- logger10.info("Testing TTS with sample text:", { text: testText });
4526
- const audioStream = await this.ttsManager.generateSpeech(testText);
4527
- if (!(audioStream instanceof Readable2)) {
4528
- throw new Error("TTS did not return a valid audio stream");
4529
- }
4530
- let dataReceived = false;
4531
- await new Promise((resolve, reject) => {
4532
- audioStream.on("data", () => {
4533
- if (!dataReceived) {
4534
- dataReceived = true;
4535
- logger10.info("TTS audio stream is producing data");
4536
- }
4537
- });
4538
- audioStream.on("end", () => {
4539
- if (!dataReceived) {
4540
- reject(new Error("No audio data received from TTS stream"));
4541
- } else {
4542
- resolve();
4543
- }
4544
- });
4545
- audioStream.on("error", (err) => {
4546
- reject(err);
4547
- });
4548
- });
4549
- logger10.success("TTS model initialization complete");
4550
- } catch (error) {
4551
- logger10.error("TTS initialization failed:", {
4552
- error: error instanceof Error ? error.message : String(error),
4553
- stack: error instanceof Error ? error.stack : void 0,
4554
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4555
- });
4556
- throw error;
4557
- }
4558
- }
4559
2900
  /**
4560
2901
  * Downloads the model based on the modelPath provided.
4561
2902
  * Determines whether to download a large or small model based on the current modelPath.
4562
2903
  *
4563
2904
  * @returns A Promise that resolves to a boolean indicating whether the model download was successful.
4564
2905
  */
4565
- async downloadModel() {
2906
+ async downloadModel(modelType) {
2907
+ const modelSpec = modelType === ModelType3.TEXT_LARGE ? MODEL_SPECS.medium : MODEL_SPECS.small;
2908
+ const modelPath = modelType === ModelType3.TEXT_LARGE ? this.mediumModelPath : this.modelPath;
4566
2909
  try {
4567
- const isLargeModel = this.modelPath === this.mediumModelPath;
4568
- const modelSpec = isLargeModel ? MODEL_SPECS.medium : MODEL_SPECS.small;
4569
- return await this.downloadManager.downloadModel(
4570
- modelSpec,
4571
- this.modelPath
4572
- );
2910
+ return await this.downloadManager.downloadModel(modelSpec, modelPath);
4573
2911
  } catch (error) {
4574
2912
  logger10.error("Model download failed:", {
4575
2913
  error: error instanceof Error ? error.message : String(error),
4576
- modelPath: this.modelPath
2914
+ modelPath
4577
2915
  });
4578
2916
  throw error;
4579
2917
  }
@@ -4601,66 +2939,14 @@ var LocalAIManager = class _LocalAIManager {
4601
2939
  /**
4602
2940
  * Initializes the LocalAI Manager for a given model type.
4603
2941
  *
4604
- * @param {ModelType} modelType - The type of model to initialize (default: ModelTypes.TEXT_SMALL)
2942
+ * @param {ModelTypeName} modelType - The type of model to initialize (default: ModelType.TEXT_SMALL)
4605
2943
  * @returns {Promise<void>} A promise that resolves when initialization is complete or rejects if an error occurs
4606
2944
  */
4607
- async initialize(modelType = ModelTypes3.TEXT_SMALL) {
4608
- try {
4609
- logger10.info("Initializing LocalAI Manager for model class:", modelType);
4610
- if (modelType === ModelTypes3.TEXT_LARGE) {
4611
- this.modelPath = this.mediumModelPath;
4612
- logger10.info("Using medium model path:", this.modelPath);
4613
- } else {
4614
- this.modelPath = path5.join(this.modelsDir, MODEL_SPECS.small.name);
4615
- logger10.info("Using small model path:", this.modelPath);
4616
- }
4617
- const wasNewlyDownloaded = await this.downloadModel();
4618
- if (wasNewlyDownloaded) {
4619
- if (modelType === ModelTypes3.TEXT_LARGE) {
4620
- logger10.info(
4621
- "Adding delay before loading large model to ensure download is complete..."
4622
- );
4623
- await new Promise((resolve) => setTimeout(resolve, 1e4));
4624
- } else {
4625
- logger10.info(
4626
- "Adding delay before loading small model to ensure download is complete..."
4627
- );
4628
- await new Promise((resolve) => setTimeout(resolve, 1e4));
4629
- }
4630
- }
4631
- if (!fs5.existsSync(this.modelPath)) {
4632
- throw new Error(`Model file not found at path: ${this.modelPath}`);
4633
- }
4634
- this.llama = await getLlama2();
4635
- if (modelType === ModelTypes3.TEXT_LARGE) {
4636
- this.activeModelConfig = MODEL_SPECS.medium;
4637
- logger10.info("Loading large model from:", this.modelPath);
4638
- this.mediumModel = await this.llama.loadModel({
4639
- modelPath: this.modelPath
4640
- });
4641
- this.ctx = await this.mediumModel.createContext({
4642
- contextSize: MODEL_SPECS.medium.contextSize
4643
- });
4644
- } else {
4645
- this.activeModelConfig = MODEL_SPECS.small;
4646
- logger10.info("Loading small model from:", this.modelPath);
4647
- this.smallModel = await this.llama.loadModel({
4648
- modelPath: this.modelPath
4649
- });
4650
- this.ctx = await this.smallModel.createContext({
4651
- contextSize: MODEL_SPECS.small.contextSize
4652
- });
4653
- }
4654
- if (!this.ctx) {
4655
- throw new Error("Failed to create prompt");
4656
- }
4657
- this.sequence = this.ctx.getSequence();
4658
- logger10.success(
4659
- `Model initialization complete for ${modelType === ModelTypes3.TEXT_LARGE ? "large" : "small"} model`
4660
- );
4661
- } catch (error) {
4662
- logger10.error("Initialization failed:", error);
4663
- throw error;
2945
+ async initialize(modelType = ModelType3.TEXT_SMALL) {
2946
+ if (modelType === ModelType3.TEXT_LARGE) {
2947
+ await this.lazyInitMediumModel();
2948
+ } else {
2949
+ await this.lazyInitSmallModel();
4664
2950
  }
4665
2951
  }
4666
2952
  /**
@@ -4673,16 +2959,11 @@ var LocalAIManager = class _LocalAIManager {
4673
2959
  logger10.info("Initializing embedding model...");
4674
2960
  logger10.info("Models directory:", this.modelsDir);
4675
2961
  if (!fs5.existsSync(this.modelsDir)) {
4676
- logger10.warn(
4677
- "Models directory does not exist, creating it:",
4678
- this.modelsDir
4679
- );
2962
+ logger10.warn("Models directory does not exist, creating it:", this.modelsDir);
4680
2963
  fs5.mkdirSync(this.modelsDir, { recursive: true });
4681
2964
  }
4682
2965
  if (!this.embeddingModel) {
4683
- logger10.info(
4684
- "Creating new FlagEmbedding instance with BGESmallENV15 model"
4685
- );
2966
+ logger10.info("Creating new FlagEmbedding instance with BGESmallENV15 model");
4686
2967
  const barLength = 30;
4687
2968
  const emptyBar = "\u25B1".repeat(barLength);
4688
2969
  logger10.info(`Downloading embedding model: ${emptyBar} 0%`);
@@ -4696,13 +2977,6 @@ var LocalAIManager = class _LocalAIManager {
4696
2977
  logger10.info(`Downloading embedding model: ${completedBar} 100%`);
4697
2978
  logger10.success("FlagEmbedding instance created successfully");
4698
2979
  }
4699
- logger10.info("Testing embedding model with sample text...");
4700
- const testEmbed = await this.embeddingModel.queryEmbed("test");
4701
- logger10.info(
4702
- "Test embedding generated successfully, dimensions:",
4703
- testEmbed.length
4704
- );
4705
- logger10.success("Embedding model initialization complete");
4706
2980
  } catch (error) {
4707
2981
  logger10.error("Embedding initialization failed with details:", {
4708
2982
  error: error instanceof Error ? error.message : String(error),
@@ -4738,31 +3012,22 @@ var LocalAIManager = class _LocalAIManager {
4738
3012
  return this.generateText(params);
4739
3013
  }
4740
3014
  if (!this.studioLMManager) {
4741
- logger10.warn(
4742
- "StudioLM manager not initialized, falling back to local models"
4743
- );
3015
+ logger10.warn("StudioLM manager not initialized, falling back to local models");
4744
3016
  return this.generateText(params);
4745
3017
  }
4746
3018
  if (!this.studioLMInitialized) {
4747
3019
  logger10.info("StudioLM not initialized, initializing now...");
4748
3020
  await this.initializeStudioLM();
4749
3021
  }
4750
- return await this.studioLMManager.generateText(
4751
- params,
4752
- this.studioLMInitialized
4753
- );
3022
+ return await this.studioLMManager.generateText(params, this.studioLMInitialized);
4754
3023
  }
4755
3024
  if (modelConfig.source === "ollama") {
4756
3025
  if (process.env.USE_OLLAMA_TEXT_MODELS !== "true") {
4757
- logger10.warn(
4758
- "Ollama requested but disabled in environment, falling back to local models"
4759
- );
3026
+ logger10.warn("Ollama requested but disabled in environment, falling back to local models");
4760
3027
  return this.generateText(params);
4761
3028
  }
4762
3029
  if (!this.ollamaManager) {
4763
- logger10.warn(
4764
- "Ollama manager not initialized, falling back to local models"
4765
- );
3030
+ logger10.warn("Ollama manager not initialized, falling back to local models");
4766
3031
  return this.generateText(params);
4767
3032
  }
4768
3033
  if (!this.ollamaInitialized && !this.ollamaManager.isInitialized()) {
@@ -4770,10 +3035,7 @@ var LocalAIManager = class _LocalAIManager {
4770
3035
  await this.ollamaManager.initialize();
4771
3036
  this.ollamaInitialized = true;
4772
3037
  }
4773
- return await this.ollamaManager.generateText(
4774
- params,
4775
- this.ollamaInitialized
4776
- );
3038
+ return await this.ollamaManager.generateText(params, this.ollamaInitialized);
4777
3039
  }
4778
3040
  return this.generateText(params);
4779
3041
  } catch (error) {
@@ -4787,32 +3049,28 @@ var LocalAIManager = class _LocalAIManager {
4787
3049
  }
4788
3050
  /**
4789
3051
  * Asynchronously generates text based on the provided parameters.
4790
- *
4791
- * @param {GenerateTextParams} params - The parameters for text generation.
4792
- * @returns {Promise<string>} The generated text as a string.
3052
+ * Now uses lazy initialization for models
4793
3053
  */
4794
3054
  async generateText(params) {
4795
3055
  try {
4796
- if (!this.sequence || !this.smallModel || params.modelType === ModelTypes3.TEXT_LARGE && !this.mediumModel) {
4797
- await this.initialize(params.modelType);
4798
- }
4799
- let activeModel;
4800
- if (params.modelType === ModelTypes3.TEXT_LARGE) {
3056
+ if (params.modelType === ModelType3.TEXT_LARGE) {
3057
+ await this.lazyInitMediumModel();
4801
3058
  if (!this.mediumModel) {
4802
- throw new Error("Medium model not initialized");
3059
+ throw new Error("Medium model initialization failed");
4803
3060
  }
4804
3061
  this.activeModelConfig = MODEL_SPECS.medium;
4805
- activeModel = this.mediumModel;
4806
- this.ctx = await activeModel.createContext({
3062
+ const mediumModel = this.mediumModel;
3063
+ this.ctx = await mediumModel.createContext({
4807
3064
  contextSize: MODEL_SPECS.medium.contextSize
4808
3065
  });
4809
3066
  } else {
3067
+ await this.lazyInitSmallModel();
4810
3068
  if (!this.smallModel) {
4811
- throw new Error("Small model not initialized");
3069
+ throw new Error("Small model initialization failed");
4812
3070
  }
4813
3071
  this.activeModelConfig = MODEL_SPECS.small;
4814
- activeModel = this.smallModel;
4815
- this.ctx = await activeModel.createContext({
3072
+ const smallModel = this.smallModel;
3073
+ this.ctx = await smallModel.createContext({
4816
3074
  contextSize: MODEL_SPECS.small.contextSize
4817
3075
  });
4818
3076
  }
@@ -4833,10 +3091,7 @@ var LocalAIManager = class _LocalAIManager {
4833
3091
  runtime: !!params.runtime,
4834
3092
  stopSequences: params.stopSequences
4835
3093
  });
4836
- const tokens = await this.tokenizerManager.encode(
4837
- params.prompt,
4838
- this.activeModelConfig
4839
- );
3094
+ const tokens = await this.tokenizerManager.encode(params.prompt, this.activeModelConfig);
4840
3095
  logger10.info("Input tokens:", { count: tokens.length });
4841
3096
  const systemMessage = "You are a helpful AI assistant. Respond to the current request only.";
4842
3097
  await this.chatSession.prompt(systemMessage, {
@@ -4849,7 +3104,7 @@ var LocalAIManager = class _LocalAIManager {
4849
3104
  temperature: 0.7,
4850
3105
  topP: 0.9,
4851
3106
  repeatPenalty: {
4852
- punishTokensFilter: () => activeModel.tokenize(wordsToPunish.join(" ")),
3107
+ punishTokensFilter: () => this.smallModel.tokenize(wordsToPunish.join(" ")),
4853
3108
  penalty: 1.2,
4854
3109
  frequencyPenalty: 0.7,
4855
3110
  presencePenalty: 0.7
@@ -4872,25 +3127,11 @@ var LocalAIManager = class _LocalAIManager {
4872
3127
  }
4873
3128
  }
4874
3129
  /**
4875
- * Asynchronously generates an embedding for the provided text.
4876
- *
4877
- * @param {string} text - The input text for which to generate the embedding
4878
- * @returns {Promise<number[]>} The generated embedding as an array of numbers
4879
- * @throws {Error} If the input text is null or undefined, or if there is an issue generating the embedding
3130
+ * Generate embeddings - now with lazy initialization
4880
3131
  */
4881
3132
  async generateEmbedding(text) {
4882
3133
  try {
4883
- logger10.info("Generating embedding...");
4884
- if (!text) {
4885
- throw new Error("Input text cannot be null or undefined");
4886
- }
4887
- logger10.debug("Input text length:", text.length);
4888
- if (!this.embeddingModel) {
4889
- logger10.error(
4890
- "Embedding model not initialized, attempting to initialize..."
4891
- );
4892
- await this.initializeEmbedding();
4893
- }
3134
+ await this.lazyInitEmbedding();
4894
3135
  if (!this.embeddingModel) {
4895
3136
  throw new Error("Failed to initialize embedding model");
4896
3137
  }
@@ -4910,16 +3151,11 @@ var LocalAIManager = class _LocalAIManager {
4910
3151
  }
4911
3152
  }
4912
3153
  /**
4913
- * Asynchronously describes the image based on the provided image data and MIME type.
4914
- * Converts the image data buffer to a data URL, then passes the URL to the VisionManager for processing.
4915
- *
4916
- * @param {Buffer} imageData The image data buffer to describe.
4917
- * @param {string} mimeType The MIME type of the image data.
4918
- * @returns {Promise<{ title: string; description: string }>} A Promise that resolves to an object containing the title and description of the described image.
4919
- * @throws {Error} If an error occurs during image description process.
3154
+ * Describe image with lazy vision model initialization
4920
3155
  */
4921
3156
  async describeImage(imageData, mimeType) {
4922
3157
  try {
3158
+ await this.lazyInitVision();
4923
3159
  const base64 = imageData.toString("base64");
4924
3160
  const dataUrl = `data:${mimeType};base64,${base64}`;
4925
3161
  return await this.visionManager.processImage(dataUrl);
@@ -4929,14 +3165,11 @@ var LocalAIManager = class _LocalAIManager {
4929
3165
  }
4930
3166
  }
4931
3167
  /**
4932
- * Transcribe audio data from a Buffer.
4933
- *
4934
- * @param {Buffer} audioBuffer The audio data to transcribe
4935
- * @returns {Promise<string>} The transcribed text
4936
- * @throws {Error} If the audio transcription fails
3168
+ * Transcribe audio with lazy transcription model initialization
4937
3169
  */
4938
3170
  async transcribeAudio(audioBuffer) {
4939
3171
  try {
3172
+ await this.lazyInitTranscription();
4940
3173
  const result = await this.transcribeManager.transcribe(audioBuffer);
4941
3174
  return result.text;
4942
3175
  } catch (error) {
@@ -4948,14 +3181,11 @@ var LocalAIManager = class _LocalAIManager {
4948
3181
  }
4949
3182
  }
4950
3183
  /**
4951
- * Asynchronously generates speech for the given text using the TTS manager.
4952
- *
4953
- * @param {string} text - The text for which speech needs to be generated.
4954
- * @returns {Promise<Readable>} A Promise that resolves to a Readable stream containing the generated speech.
4955
- * @throws {Error} If speech generation fails, an error is thrown with details logged using the logger.
3184
+ * Generate speech with lazy TTS model initialization
4956
3185
  */
4957
3186
  async generateSpeech(text) {
4958
3187
  try {
3188
+ await this.lazyInitTTS();
4959
3189
  return await this.ttsManager.generateSpeech(text);
4960
3190
  } catch (error) {
4961
3191
  logger10.error("Speech generation failed:", {
@@ -4989,7 +3219,7 @@ var LocalAIManager = class _LocalAIManager {
4989
3219
  try {
4990
3220
  const config = {
4991
3221
  source: "local",
4992
- modelType: ModelTypes3.TEXT_SMALL
3222
+ modelType: ModelType3.TEXT_SMALL
4993
3223
  };
4994
3224
  if (process.env.USE_STUDIOLM_TEXT_MODELS === "true" && this.studioLMManager) {
4995
3225
  config.source = "studiolm";
@@ -5000,22 +3230,212 @@ var LocalAIManager = class _LocalAIManager {
5000
3230
  return config;
5001
3231
  } catch (error) {
5002
3232
  logger10.error("Error determining text model source:", error);
5003
- return { source: "local", modelType: ModelTypes3.TEXT_SMALL };
3233
+ return { source: "local", modelType: ModelType3.TEXT_SMALL };
3234
+ }
3235
+ }
3236
+ /**
3237
+ * Generic lazy initialization handler for any model type
3238
+ */
3239
+ async lazyInitialize(modelType, isInitialized, initPromise, initFunction) {
3240
+ if (isInitialized) {
3241
+ return Promise.resolve(null);
3242
+ }
3243
+ if (initPromise) {
3244
+ logger10.info(`Waiting for ${modelType} initialization to complete...`);
3245
+ await initPromise;
3246
+ return Promise.resolve(null);
3247
+ }
3248
+ logger10.info(`Lazy initializing ${modelType}...`);
3249
+ return initFunction();
3250
+ }
3251
+ /**
3252
+ * Lazy initialize the small text model
3253
+ */
3254
+ async lazyInitSmallModel() {
3255
+ if (this.smallModelInitialized) return;
3256
+ if (!this.smallModelInitializingPromise) {
3257
+ this.smallModelInitializingPromise = (async () => {
3258
+ await this.initializeEnvironment();
3259
+ await this.checkPlatformCapabilities();
3260
+ await this.downloadModel(ModelType3.TEXT_SMALL);
3261
+ try {
3262
+ this.llama = await getLlama2();
3263
+ const smallModel = await this.llama.loadModel({
3264
+ gpuLayers: 43,
3265
+ modelPath: this.modelPath,
3266
+ vocabOnly: false
3267
+ });
3268
+ this.smallModel = smallModel;
3269
+ const ctx = await smallModel.createContext({
3270
+ contextSize: MODEL_SPECS.small.contextSize
3271
+ });
3272
+ this.ctx = ctx;
3273
+ this.sequence = void 0;
3274
+ this.smallModelInitialized = true;
3275
+ logger10.info("Small model initialized successfully");
3276
+ } catch (error) {
3277
+ logger10.error("Failed to initialize small model:", error);
3278
+ this.smallModelInitializingPromise = null;
3279
+ throw error;
3280
+ }
3281
+ })();
3282
+ }
3283
+ await this.smallModelInitializingPromise;
3284
+ }
3285
+ /**
3286
+ * Lazy initialize the medium text model
3287
+ */
3288
+ async lazyInitMediumModel() {
3289
+ if (this.mediumModelInitialized) return;
3290
+ if (!this.mediumModelInitializingPromise) {
3291
+ this.mediumModelInitializingPromise = (async () => {
3292
+ if (!this.llama) {
3293
+ await this.lazyInitSmallModel();
3294
+ }
3295
+ await this.downloadModel(ModelType3.TEXT_LARGE);
3296
+ try {
3297
+ const mediumModel = await this.llama.loadModel({
3298
+ gpuLayers: 43,
3299
+ modelPath: this.mediumModelPath,
3300
+ vocabOnly: false
3301
+ });
3302
+ this.mediumModel = mediumModel;
3303
+ this.mediumModelInitialized = true;
3304
+ logger10.info("Medium model initialized successfully");
3305
+ } catch (error) {
3306
+ logger10.error("Failed to initialize medium model:", error);
3307
+ this.mediumModelInitializingPromise = null;
3308
+ throw error;
3309
+ }
3310
+ })();
3311
+ }
3312
+ await this.mediumModelInitializingPromise;
3313
+ }
3314
+ /**
3315
+ * Lazy initialize the embedding model
3316
+ */
3317
+ async lazyInitEmbedding() {
3318
+ if (this.embeddingInitialized) return;
3319
+ if (!this.embeddingInitializingPromise) {
3320
+ this.embeddingInitializingPromise = (async () => {
3321
+ try {
3322
+ await this.initializeEmbedding();
3323
+ this.embeddingInitialized = true;
3324
+ logger10.info("Embedding model initialized successfully");
3325
+ } catch (error) {
3326
+ logger10.error("Failed to initialize embedding model:", error);
3327
+ this.embeddingInitializingPromise = null;
3328
+ throw error;
3329
+ }
3330
+ })();
3331
+ }
3332
+ await this.embeddingInitializingPromise;
3333
+ }
3334
+ /**
3335
+ * Lazy initialize the vision model
3336
+ */
3337
+ async lazyInitVision() {
3338
+ if (this.visionInitialized) return;
3339
+ if (!this.visionInitializingPromise) {
3340
+ this.visionInitializingPromise = (async () => {
3341
+ try {
3342
+ this.visionInitialized = true;
3343
+ logger10.info("Vision model initialized successfully");
3344
+ } catch (error) {
3345
+ logger10.error("Failed to initialize vision model:", error);
3346
+ this.visionInitializingPromise = null;
3347
+ throw error;
3348
+ }
3349
+ })();
3350
+ }
3351
+ await this.visionInitializingPromise;
3352
+ }
3353
+ /**
3354
+ * Lazy initialize the transcription model
3355
+ */
3356
+ async lazyInitTranscription() {
3357
+ if (this.transcriptionInitialized) return;
3358
+ if (!this.transcriptionInitializingPromise) {
3359
+ this.transcriptionInitializingPromise = (async () => {
3360
+ try {
3361
+ this.transcriptionInitialized = true;
3362
+ logger10.info("Transcription model initialized successfully");
3363
+ } catch (error) {
3364
+ logger10.error("Failed to initialize transcription model:", error);
3365
+ this.transcriptionInitializingPromise = null;
3366
+ throw error;
3367
+ }
3368
+ })();
3369
+ }
3370
+ await this.transcriptionInitializingPromise;
3371
+ }
3372
+ /**
3373
+ * Lazy initialize the TTS model
3374
+ */
3375
+ async lazyInitTTS() {
3376
+ if (this.ttsInitialized) return;
3377
+ if (!this.ttsInitializingPromise) {
3378
+ this.ttsInitializingPromise = (async () => {
3379
+ try {
3380
+ this.ttsInitialized = true;
3381
+ logger10.info("TTS model initialized successfully");
3382
+ } catch (error) {
3383
+ logger10.error("Failed to initialize TTS model:", error);
3384
+ this.ttsInitializingPromise = null;
3385
+ throw error;
3386
+ }
3387
+ })();
3388
+ }
3389
+ await this.ttsInitializingPromise;
3390
+ }
3391
+ /**
3392
+ * Lazy initialize the Ollama integration
3393
+ */
3394
+ async lazyInitOllama() {
3395
+ if (this.ollamaInitialized) return;
3396
+ if (!this.ollamaInitializingPromise) {
3397
+ this.ollamaInitializingPromise = (async () => {
3398
+ try {
3399
+ await this.initializeOllama();
3400
+ this.ollamaInitialized = true;
3401
+ logger10.info("Ollama initialized successfully");
3402
+ } catch (error) {
3403
+ logger10.error("Failed to initialize Ollama:", error);
3404
+ this.ollamaInitializingPromise = null;
3405
+ throw error;
3406
+ }
3407
+ })();
3408
+ }
3409
+ await this.ollamaInitializingPromise;
3410
+ }
3411
+ /**
3412
+ * Lazy initialize the StudioLM integration
3413
+ */
3414
+ async lazyInitStudioLM() {
3415
+ if (this.studioLMInitialized) return;
3416
+ if (!this.studioLMInitializingPromise) {
3417
+ this.studioLMInitializingPromise = (async () => {
3418
+ try {
3419
+ await this.initializeStudioLM();
3420
+ this.studioLMInitialized = true;
3421
+ logger10.info("StudioLM initialized successfully");
3422
+ } catch (error) {
3423
+ logger10.error("Failed to initialize StudioLM:", error);
3424
+ this.studioLMInitializingPromise = null;
3425
+ throw error;
3426
+ }
3427
+ })();
5004
3428
  }
3429
+ await this.studioLMInitializingPromise;
5005
3430
  }
5006
3431
  };
5007
3432
  var localAIManager = LocalAIManager.getInstance();
5008
3433
  var localAIPlugin = {
5009
3434
  name: "local-ai",
5010
3435
  description: "Local AI plugin using LLaMA models",
5011
- async init(config) {
3436
+ async init() {
5012
3437
  try {
5013
- logger10.info("Initializing local-ai plugin...");
5014
- const validatedConfig = await validateConfig(config);
5015
- for (const [key, value] of Object.entries(validatedConfig)) {
5016
- process.env[key] = String(value);
5017
- logger10.debug(`Set ${key}=${value}`);
5018
- }
3438
+ logger10.debug("Initializing local-ai plugin...");
5019
3439
  logger10.success("Local AI plugin configuration validated and initialized");
5020
3440
  } catch (error) {
5021
3441
  logger10.error("Plugin initialization failed:", {
@@ -5026,7 +3446,7 @@ var localAIPlugin = {
5026
3446
  }
5027
3447
  },
5028
3448
  models: {
5029
- [ModelTypes3.TEXT_SMALL]: async (runtime, { prompt, stopSequences = [] }) => {
3449
+ [ModelType3.TEXT_SMALL]: async (runtime, { prompt, stopSequences = [] }) => {
5030
3450
  try {
5031
3451
  const modelConfig = localAIManager.getTextModelSource();
5032
3452
  if (modelConfig.source !== "local") {
@@ -5034,21 +3454,21 @@ var localAIPlugin = {
5034
3454
  prompt,
5035
3455
  stopSequences,
5036
3456
  runtime,
5037
- modelType: ModelTypes3.TEXT_SMALL
3457
+ modelType: ModelType3.TEXT_SMALL
5038
3458
  });
5039
3459
  }
5040
3460
  return await localAIManager.generateText({
5041
3461
  prompt,
5042
3462
  stopSequences,
5043
3463
  runtime,
5044
- modelType: ModelTypes3.TEXT_SMALL
3464
+ modelType: ModelType3.TEXT_SMALL
5045
3465
  });
5046
3466
  } catch (error) {
5047
3467
  logger10.error("Error in TEXT_SMALL handler:", error);
5048
3468
  throw error;
5049
3469
  }
5050
3470
  },
5051
- [ModelTypes3.TEXT_LARGE]: async (runtime, { prompt, stopSequences = [] }) => {
3471
+ [ModelType3.TEXT_LARGE]: async (runtime, { prompt, stopSequences = [] }) => {
5052
3472
  try {
5053
3473
  const modelConfig = localAIManager.getTextModelSource();
5054
3474
  if (modelConfig.source !== "local") {
@@ -5056,40 +3476,25 @@ var localAIPlugin = {
5056
3476
  prompt,
5057
3477
  stopSequences,
5058
3478
  runtime,
5059
- modelType: ModelTypes3.TEXT_LARGE
3479
+ modelType: ModelType3.TEXT_LARGE
5060
3480
  });
5061
3481
  }
5062
3482
  return await localAIManager.generateText({
5063
3483
  prompt,
5064
3484
  stopSequences,
5065
3485
  runtime,
5066
- modelType: ModelTypes3.TEXT_LARGE
3486
+ modelType: ModelType3.TEXT_LARGE
5067
3487
  });
5068
3488
  } catch (error) {
5069
3489
  logger10.error("Error in TEXT_LARGE handler:", error);
5070
3490
  throw error;
5071
3491
  }
5072
3492
  },
5073
- [ModelTypes3.TEXT_EMBEDDING]: async (_runtime, text) => {
3493
+ [ModelType3.TEXT_EMBEDDING]: async (_runtime, params) => {
3494
+ const text = params?.text;
5074
3495
  try {
5075
- logger10.info("TEXT_EMBEDDING handler - Initial input:", {
5076
- text,
5077
- // type: typeof text,
5078
- // isString: typeof text === 'string',
5079
- // isObject: typeof text === 'object',
5080
- // hasThinkTag: typeof text === 'string' && text.includes('<think>'),
5081
- length: text?.length,
5082
- rawText: text
5083
- // Log the complete raw text
5084
- });
5085
- if (typeof text === "object" && text !== null) {
5086
- logger10.info("TEXT_EMBEDDING handler - Object structure:", {
5087
- keys: Object.keys(text),
5088
- stringified: JSON.stringify(text, null, 2)
5089
- });
5090
- }
5091
3496
  if (!text) {
5092
- logger10.warn("Null or empty text input for embedding");
3497
+ logger10.debug("Null or empty text input for embedding, returning zero vector");
5093
3498
  return new Array(384).fill(0);
5094
3499
  }
5095
3500
  return await localAIManager.generateEmbedding(text);
@@ -5103,7 +3508,169 @@ var localAIPlugin = {
5103
3508
  return new Array(384).fill(0);
5104
3509
  }
5105
3510
  },
5106
- [ModelTypes3.TEXT_TOKENIZER_ENCODE]: async (_runtime, { text }) => {
3511
+ [ModelType3.OBJECT_SMALL]: async (runtime, params) => {
3512
+ try {
3513
+ logger10.info("OBJECT_SMALL handler - Processing request:", {
3514
+ prompt: params.prompt,
3515
+ hasSchema: !!params.schema,
3516
+ temperature: params.temperature
3517
+ });
3518
+ let jsonPrompt = params.prompt;
3519
+ if (!jsonPrompt.includes("```json") && !jsonPrompt.includes("respond with valid JSON")) {
3520
+ jsonPrompt += "\nPlease respond with valid JSON only, without any explanations, markdown formatting, or additional text.";
3521
+ }
3522
+ const modelConfig = localAIManager.getTextModelSource();
3523
+ let textResponse;
3524
+ if (modelConfig.source !== "local") {
3525
+ textResponse = await localAIManager.generateTextOllamaStudio({
3526
+ prompt: jsonPrompt,
3527
+ stopSequences: params.stopSequences,
3528
+ runtime,
3529
+ modelType: ModelType3.TEXT_SMALL
3530
+ });
3531
+ } else {
3532
+ textResponse = await localAIManager.generateText({
3533
+ prompt: jsonPrompt,
3534
+ stopSequences: params.stopSequences,
3535
+ runtime,
3536
+ modelType: ModelType3.TEXT_SMALL
3537
+ });
3538
+ }
3539
+ try {
3540
+ const extractJSON = (text) => {
3541
+ const jsonBlockRegex = /```(?:json)?\s*([\s\S]*?)\s*```/;
3542
+ const match = text.match(jsonBlockRegex);
3543
+ if (match && match[1]) {
3544
+ return match[1].trim();
3545
+ }
3546
+ const jsonContentRegex = /\s*(\{[\s\S]*\})\s*$/;
3547
+ const contentMatch = text.match(jsonContentRegex);
3548
+ if (contentMatch && contentMatch[1]) {
3549
+ return contentMatch[1].trim();
3550
+ }
3551
+ return text.trim();
3552
+ };
3553
+ const extractedJsonText = extractJSON(textResponse);
3554
+ logger10.debug("Extracted JSON text:", extractedJsonText);
3555
+ let jsonObject;
3556
+ try {
3557
+ jsonObject = JSON.parse(extractedJsonText);
3558
+ } catch (parseError) {
3559
+ logger10.debug("Initial JSON parse failed, attempting to fix common issues");
3560
+ const fixedJson = extractedJsonText.replace(/:\s*"([^"]*)(?:\n)([^"]*)"/g, ': "$1\\n$2"').replace(/"([^"]*?)[^a-zA-Z0-9\s\.,;:\-_\(\)"'\[\]{}]([^"]*?)"/g, '"$1$2"').replace(/(\s*)(\w+)(\s*):/g, '$1"$2"$3:').replace(/,(\s*[\]}])/g, "$1");
3561
+ try {
3562
+ jsonObject = JSON.parse(fixedJson);
3563
+ } catch (finalError) {
3564
+ logger10.error("Failed to parse JSON after fixing:", finalError);
3565
+ throw new Error("Invalid JSON returned from model");
3566
+ }
3567
+ }
3568
+ if (params.schema) {
3569
+ try {
3570
+ for (const key of Object.keys(params.schema)) {
3571
+ if (!(key in jsonObject)) {
3572
+ jsonObject[key] = null;
3573
+ }
3574
+ }
3575
+ } catch (schemaError) {
3576
+ logger10.error("Schema validation failed:", schemaError);
3577
+ }
3578
+ }
3579
+ return jsonObject;
3580
+ } catch (parseError) {
3581
+ logger10.error("Failed to parse JSON:", parseError);
3582
+ logger10.error("Raw response:", textResponse);
3583
+ throw new Error("Invalid JSON returned from model");
3584
+ }
3585
+ } catch (error) {
3586
+ logger10.error("Error in OBJECT_SMALL handler:", error);
3587
+ throw error;
3588
+ }
3589
+ },
3590
+ [ModelType3.OBJECT_LARGE]: async (runtime, params) => {
3591
+ try {
3592
+ logger10.info("OBJECT_LARGE handler - Processing request:", {
3593
+ prompt: params.prompt,
3594
+ hasSchema: !!params.schema,
3595
+ temperature: params.temperature
3596
+ });
3597
+ let jsonPrompt = params.prompt;
3598
+ if (!jsonPrompt.includes("```json") && !jsonPrompt.includes("respond with valid JSON")) {
3599
+ jsonPrompt += "\nPlease respond with valid JSON only, without any explanations, markdown formatting, or additional text.";
3600
+ }
3601
+ const modelConfig = localAIManager.getTextModelSource();
3602
+ let textResponse;
3603
+ if (modelConfig.source !== "local") {
3604
+ textResponse = await localAIManager.generateTextOllamaStudio({
3605
+ prompt: jsonPrompt,
3606
+ stopSequences: params.stopSequences,
3607
+ runtime,
3608
+ modelType: ModelType3.TEXT_LARGE
3609
+ });
3610
+ } else {
3611
+ textResponse = await localAIManager.generateText({
3612
+ prompt: jsonPrompt,
3613
+ stopSequences: params.stopSequences,
3614
+ runtime,
3615
+ modelType: ModelType3.TEXT_LARGE
3616
+ });
3617
+ }
3618
+ try {
3619
+ const extractJSON = (text) => {
3620
+ const jsonBlockRegex = /```(?:json)?\s*([\s\S]*?)\s*```/;
3621
+ const match = text.match(jsonBlockRegex);
3622
+ if (match && match[1]) {
3623
+ return match[1].trim();
3624
+ }
3625
+ const jsonContentRegex = /\s*(\{[\s\S]*\})\s*$/;
3626
+ const contentMatch = text.match(jsonContentRegex);
3627
+ if (contentMatch && contentMatch[1]) {
3628
+ return contentMatch[1].trim();
3629
+ }
3630
+ return text.trim();
3631
+ };
3632
+ const cleanupJSON = (jsonText) => {
3633
+ return jsonText.replace(/\[DEBUG\].*?(\n|$)/g, "\n").replace(/\[LOG\].*?(\n|$)/g, "\n").replace(/console\.log.*?(\n|$)/g, "\n");
3634
+ };
3635
+ const extractedJsonText = extractJSON(textResponse);
3636
+ const cleanedJsonText = cleanupJSON(extractedJsonText);
3637
+ logger10.debug("Extracted JSON text:", cleanedJsonText);
3638
+ let jsonObject;
3639
+ try {
3640
+ jsonObject = JSON.parse(cleanedJsonText);
3641
+ } catch (parseError) {
3642
+ logger10.debug("Initial JSON parse failed, attempting to fix common issues");
3643
+ const fixedJson = cleanedJsonText.replace(/:\s*"([^"]*)(?:\n)([^"]*)"/g, ': "$1\\n$2"').replace(/"([^"]*?)[^a-zA-Z0-9\s\.,;:\-_\(\)"'\[\]{}]([^"]*?)"/g, '"$1$2"').replace(/(\s*)(\w+)(\s*):/g, '$1"$2"$3:').replace(/,(\s*[\]}])/g, "$1");
3644
+ try {
3645
+ jsonObject = JSON.parse(fixedJson);
3646
+ } catch (finalError) {
3647
+ logger10.error("Failed to parse JSON after fixing:", finalError);
3648
+ throw new Error("Invalid JSON returned from model");
3649
+ }
3650
+ }
3651
+ if (params.schema) {
3652
+ try {
3653
+ for (const key of Object.keys(params.schema)) {
3654
+ if (!(key in jsonObject)) {
3655
+ jsonObject[key] = null;
3656
+ }
3657
+ }
3658
+ } catch (schemaError) {
3659
+ logger10.error("Schema validation failed:", schemaError);
3660
+ }
3661
+ }
3662
+ return jsonObject;
3663
+ } catch (parseError) {
3664
+ logger10.error("Failed to parse JSON:", parseError);
3665
+ logger10.error("Raw response:", textResponse);
3666
+ throw new Error("Invalid JSON returned from model");
3667
+ }
3668
+ } catch (error) {
3669
+ logger10.error("Error in OBJECT_LARGE handler:", error);
3670
+ throw error;
3671
+ }
3672
+ },
3673
+ [ModelType3.TEXT_TOKENIZER_ENCODE]: async (_runtime, { text }) => {
5107
3674
  try {
5108
3675
  const manager = localAIManager.getTokenizerManager();
5109
3676
  const config = localAIManager.getActiveModelConfig();
@@ -5113,7 +3680,7 @@ var localAIPlugin = {
5113
3680
  throw error;
5114
3681
  }
5115
3682
  },
5116
- [ModelTypes3.TEXT_TOKENIZER_DECODE]: async (_runtime, { tokens }) => {
3683
+ [ModelType3.TEXT_TOKENIZER_DECODE]: async (_runtime, { tokens }) => {
5117
3684
  try {
5118
3685
  const manager = localAIManager.getTokenizerManager();
5119
3686
  const config = localAIManager.getActiveModelConfig();
@@ -5123,7 +3690,7 @@ var localAIPlugin = {
5123
3690
  throw error;
5124
3691
  }
5125
3692
  },
5126
- [ModelTypes3.IMAGE_DESCRIPTION]: async (_runtime, imageUrl) => {
3693
+ [ModelType3.IMAGE_DESCRIPTION]: async (_runtime, imageUrl) => {
5127
3694
  try {
5128
3695
  logger10.info("Processing image from URL:", imageUrl);
5129
3696
  const response = await fetch(imageUrl);
@@ -5141,7 +3708,7 @@ var localAIPlugin = {
5141
3708
  throw error;
5142
3709
  }
5143
3710
  },
5144
- [ModelTypes3.TRANSCRIPTION]: async (_runtime, audioBuffer) => {
3711
+ [ModelType3.TRANSCRIPTION]: async (_runtime, audioBuffer) => {
5145
3712
  try {
5146
3713
  logger10.info("Processing audio transcription:", {
5147
3714
  bufferSize: audioBuffer.length
@@ -5155,7 +3722,7 @@ var localAIPlugin = {
5155
3722
  throw error;
5156
3723
  }
5157
3724
  },
5158
- [ModelTypes3.TEXT_TO_SPEECH]: async (_runtime, text) => {
3725
+ [ModelType3.TEXT_TO_SPEECH]: async (_runtime, text) => {
5159
3726
  try {
5160
3727
  return await localAIManager.generateSpeech(text);
5161
3728
  } catch (error) {
@@ -5176,7 +3743,7 @@ var localAIPlugin = {
5176
3743
  fn: async (runtime) => {
5177
3744
  try {
5178
3745
  logger10.info("Starting initialization test");
5179
- const result = await runtime.useModel(ModelTypes3.TEXT_SMALL, {
3746
+ const result = await runtime.useModel(ModelType3.TEXT_SMALL, {
5180
3747
  prompt: "Debug Mode: Test initialization. Respond with 'Initialization successful' if you can read this.",
5181
3748
  stopSequences: []
5182
3749
  });
@@ -5202,7 +3769,7 @@ var localAIPlugin = {
5202
3769
  fn: async (runtime) => {
5203
3770
  try {
5204
3771
  logger10.info("Starting TEXT_LARGE model test");
5205
- const result = await runtime.useModel(ModelTypes3.TEXT_LARGE, {
3772
+ const result = await runtime.useModel(ModelType3.TEXT_LARGE, {
5206
3773
  prompt: "Debug Mode: Generate a one-sentence response about artificial intelligence.",
5207
3774
  stopSequences: []
5208
3775
  });
@@ -5228,14 +3795,10 @@ var localAIPlugin = {
5228
3795
  fn: async (runtime) => {
5229
3796
  try {
5230
3797
  logger10.info("Starting TEXT_EMBEDDING test");
5231
- const embedding = await runtime.useModel(
5232
- ModelTypes3.TEXT_EMBEDDING,
5233
- "Test embedding generation"
5234
- );
5235
- logger10.info(
5236
- "Embedding generated with dimensions:",
5237
- embedding.length
5238
- );
3798
+ const embedding = await runtime.useModel(ModelType3.TEXT_EMBEDDING, {
3799
+ text: "This is a test of the text embedding model."
3800
+ });
3801
+ logger10.info("Embedding generated with dimensions:", embedding.length);
5239
3802
  if (!Array.isArray(embedding)) {
5240
3803
  throw new Error("Embedding is not an array");
5241
3804
  }
@@ -5245,10 +3808,7 @@ var localAIPlugin = {
5245
3808
  if (embedding.some((val) => typeof val !== "number")) {
5246
3809
  throw new Error("Embedding contains non-numeric values");
5247
3810
  }
5248
- const nullEmbedding = await runtime.useModel(
5249
- ModelTypes3.TEXT_EMBEDDING,
5250
- null
5251
- );
3811
+ const nullEmbedding = await runtime.useModel(ModelType3.TEXT_EMBEDDING, null);
5252
3812
  if (!Array.isArray(nullEmbedding) || nullEmbedding.some((val) => val !== 0)) {
5253
3813
  throw new Error("Null input did not return zero vector");
5254
3814
  }
@@ -5268,10 +3828,7 @@ var localAIPlugin = {
5268
3828
  try {
5269
3829
  logger10.info("Starting TEXT_TOKENIZER_ENCODE test");
5270
3830
  const text = "Hello tokenizer test!";
5271
- const tokens = await runtime.useModel(
5272
- ModelTypes3.TEXT_TOKENIZER_ENCODE,
5273
- { text }
5274
- );
3831
+ const tokens = await runtime.useModel(ModelType3.TEXT_TOKENIZER_ENCODE, { text });
5275
3832
  logger10.info("Encoded tokens:", { count: tokens.length });
5276
3833
  if (!Array.isArray(tokens)) {
5277
3834
  throw new Error("Tokens output is not an array");
@@ -5282,9 +3839,7 @@ var localAIPlugin = {
5282
3839
  if (tokens.some((token) => !Number.isInteger(token))) {
5283
3840
  throw new Error("Tokens contain non-integer values");
5284
3841
  }
5285
- logger10.success(
5286
- "TEXT_TOKENIZER_ENCODE test completed successfully"
5287
- );
3842
+ logger10.success("TEXT_TOKENIZER_ENCODE test completed successfully");
5288
3843
  } catch (error) {
5289
3844
  logger10.error("TEXT_TOKENIZER_ENCODE test failed:", {
5290
3845
  error: error instanceof Error ? error.message : String(error),
@@ -5300,14 +3855,12 @@ var localAIPlugin = {
5300
3855
  try {
5301
3856
  logger10.info("Starting TEXT_TOKENIZER_DECODE test");
5302
3857
  const originalText = "Hello tokenizer test!";
5303
- const tokens = await runtime.useModel(
5304
- ModelTypes3.TEXT_TOKENIZER_ENCODE,
5305
- { text: originalText }
5306
- );
5307
- const decodedText = await runtime.useModel(
5308
- ModelTypes3.TEXT_TOKENIZER_DECODE,
5309
- { tokens }
5310
- );
3858
+ const tokens = await runtime.useModel(ModelType3.TEXT_TOKENIZER_ENCODE, {
3859
+ text: originalText
3860
+ });
3861
+ const decodedText = await runtime.useModel(ModelType3.TEXT_TOKENIZER_DECODE, {
3862
+ tokens
3863
+ });
5311
3864
  logger10.info("Round trip tokenization:", {
5312
3865
  original: originalText,
5313
3866
  decoded: decodedText
@@ -5315,9 +3868,7 @@ var localAIPlugin = {
5315
3868
  if (typeof decodedText !== "string") {
5316
3869
  throw new Error("Decoded output is not a string");
5317
3870
  }
5318
- logger10.success(
5319
- "TEXT_TOKENIZER_DECODE test completed successfully"
5320
- );
3871
+ logger10.success("TEXT_TOKENIZER_DECODE test completed successfully");
5321
3872
  } catch (error) {
5322
3873
  logger10.error("TEXT_TOKENIZER_DECODE test failed:", {
5323
3874
  error: error instanceof Error ? error.message : String(error),
@@ -5333,10 +3884,7 @@ var localAIPlugin = {
5333
3884
  try {
5334
3885
  logger10.info("Starting IMAGE_DESCRIPTION test");
5335
3886
  const imageUrl = "https://raw.githubusercontent.com/microsoft/FLAML/main/website/static/img/flaml.png";
5336
- const result = await runtime.useModel(
5337
- ModelTypes3.IMAGE_DESCRIPTION,
5338
- imageUrl
5339
- );
3887
+ const result = await runtime.useModel(ModelType3.IMAGE_DESCRIPTION, imageUrl);
5340
3888
  logger10.info("Image description result:", result);
5341
3889
  if (!result || typeof result !== "object") {
5342
3890
  throw new Error("Invalid response format");
@@ -5385,10 +3933,7 @@ var localAIPlugin = {
5385
3933
  // "fmt "
5386
3934
  ]);
5387
3935
  const audioBuffer = Buffer.from(audioData);
5388
- const transcription = await runtime.useModel(
5389
- ModelTypes3.TRANSCRIPTION,
5390
- audioBuffer
5391
- );
3936
+ const transcription = await runtime.useModel(ModelType3.TRANSCRIPTION, audioBuffer);
5392
3937
  logger10.info("Transcription result:", transcription);
5393
3938
  if (typeof transcription !== "string") {
5394
3939
  throw new Error("Transcription result is not a string");
@@ -5409,10 +3954,7 @@ var localAIPlugin = {
5409
3954
  try {
5410
3955
  logger10.info("Starting TEXT_TO_SPEECH test");
5411
3956
  const testText = "This is a test of the text to speech system.";
5412
- const audioStream = await runtime.useModel(
5413
- ModelTypes3.TEXT_TO_SPEECH,
5414
- testText
5415
- );
3957
+ const audioStream = await runtime.useModel(ModelType3.TEXT_TO_SPEECH, testText);
5416
3958
  if (!(audioStream instanceof Readable2)) {
5417
3959
  throw new Error("TTS output is not a readable stream");
5418
3960
  }