@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/README.md +27 -28
- package/dist/index.js +627 -2085
- package/dist/index.js.map +1 -1
- package/package.json +68 -100
- package/dist/chunk-TIOOHHYI.js +0 -4727
- package/dist/chunk-TIOOHHYI.js.map +0 -1
- package/dist/multipart-parser-IQPIHJ5G.js +0 -359
- package/dist/multipart-parser-IQPIHJ5G.js.map +0 -1
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: "
|
|
104
|
-
repo: "
|
|
105
|
-
size: "
|
|
106
|
-
quantization: "
|
|
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: "
|
|
98
|
+
name: "NousResearch/DeepHermes-3-Llama-3-3B-Preview",
|
|
110
99
|
type: "llama"
|
|
111
100
|
}
|
|
112
101
|
},
|
|
113
102
|
medium: {
|
|
114
|
-
name: "
|
|
115
|
-
repo: "
|
|
116
|
-
size: "
|
|
117
|
-
quantization: "
|
|
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: "
|
|
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.
|
|
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.
|
|
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.
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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 ===
|
|
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 ===
|
|
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
|
|
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
|
|
881
|
+
import { promisify } from "node:util";
|
|
2223
882
|
import { logger as logger4 } from "@elizaos/core";
|
|
2224
|
-
var execAsync =
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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 ===
|
|
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 ===
|
|
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
|
|
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
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
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
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
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
|
|
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 =
|
|
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.
|
|
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
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
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
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
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
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
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
|
|
4186
|
-
* This
|
|
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
|
-
|
|
4194
|
-
|
|
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
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
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
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
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
|
-
|
|
4307
|
-
|
|
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
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 {
|
|
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 =
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
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 (
|
|
4797
|
-
await this.
|
|
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
|
|
3059
|
+
throw new Error("Medium model initialization failed");
|
|
4803
3060
|
}
|
|
4804
3061
|
this.activeModelConfig = MODEL_SPECS.medium;
|
|
4805
|
-
|
|
4806
|
-
this.ctx = await
|
|
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
|
|
3069
|
+
throw new Error("Small model initialization failed");
|
|
4812
3070
|
}
|
|
4813
3071
|
this.activeModelConfig = MODEL_SPECS.small;
|
|
4814
|
-
|
|
4815
|
-
this.ctx = await
|
|
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: () =>
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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:
|
|
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:
|
|
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(
|
|
3436
|
+
async init() {
|
|
5012
3437
|
try {
|
|
5013
|
-
logger10.
|
|
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
|
-
[
|
|
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:
|
|
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:
|
|
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
|
-
[
|
|
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:
|
|
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:
|
|
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
|
-
[
|
|
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.
|
|
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
|
-
[
|
|
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
|
-
[
|
|
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
|
-
[
|
|
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
|
-
[
|
|
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
|
-
[
|
|
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(
|
|
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(
|
|
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
|
-
|
|
5233
|
-
|
|
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
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
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
|
}
|