@elizaos/plugin-local-ai 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,10 +3,7 @@ import fs5 from "fs";
3
3
  import os3 from "os";
4
4
  import path5 from "path";
5
5
  import { Readable as Readable2 } from "stream";
6
- import {
7
- ModelType,
8
- logger as logger8
9
- } from "@elizaos/core";
6
+ import { ModelType, logger as logger8 } from "@elizaos/core";
10
7
  import {
11
8
  LlamaChatSession,
12
9
  getLlama
@@ -253,10 +250,7 @@ var DownloadManager = class _DownloadManager {
253
250
  reject(new Error(`Failed to download: ${response.statusCode}`));
254
251
  return;
255
252
  }
256
- const totalSize = Number.parseInt(
257
- response.headers["content-length"] || "0",
258
- 10
259
- );
253
+ const totalSize = Number.parseInt(response.headers["content-length"] || "0", 10);
260
254
  let downloadedSize = 0;
261
255
  let lastLoggedPercent = 0;
262
256
  const barLength = 30;
@@ -267,13 +261,9 @@ var DownloadManager = class _DownloadManager {
267
261
  downloadedSize += chunk.length;
268
262
  const percent = Math.round(downloadedSize / totalSize * 100);
269
263
  if (percent >= lastLoggedPercent + 5) {
270
- const filledLength = Math.floor(
271
- downloadedSize / totalSize * barLength
272
- );
264
+ const filledLength = Math.floor(downloadedSize / totalSize * barLength);
273
265
  const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
274
- logger2.info(
275
- `Downloading ${fileName}: ${progressBar} ${percent}%`
276
- );
266
+ logger2.info(`Downloading ${fileName}: ${progressBar} ${percent}%`);
277
267
  lastLoggedPercent = percent;
278
268
  }
279
269
  });
@@ -288,24 +278,18 @@ var DownloadManager = class _DownloadManager {
288
278
  fs.mkdirSync(destDir, { recursive: true });
289
279
  }
290
280
  if (!fs.existsSync(tempPath)) {
291
- reject(
292
- new Error(`Temporary file ${tempPath} does not exist`)
293
- );
281
+ reject(new Error(`Temporary file ${tempPath} does not exist`));
294
282
  return;
295
283
  }
296
284
  if (fs.existsSync(destPath)) {
297
285
  try {
298
286
  const backupPath = `${destPath}.bak`;
299
287
  fs.renameSync(destPath, backupPath);
300
- logger2.info(
301
- `Created backup of existing file: ${backupPath}`
302
- );
288
+ logger2.info(`Created backup of existing file: ${backupPath}`);
303
289
  fs.renameSync(tempPath, destPath);
304
290
  if (fs.existsSync(backupPath)) {
305
291
  fs.unlinkSync(backupPath);
306
- logger2.info(
307
- `Removed backup file after successful update: ${backupPath}`
308
- );
292
+ logger2.info(`Removed backup file after successful update: ${backupPath}`);
309
293
  }
310
294
  } catch (moveErr) {
311
295
  logger2.error(
@@ -315,9 +299,7 @@ var DownloadManager = class _DownloadManager {
315
299
  if (fs.existsSync(backupPath)) {
316
300
  try {
317
301
  fs.renameSync(backupPath, destPath);
318
- logger2.info(
319
- `Restored from backup after failed update: ${backupPath}`
320
- );
302
+ logger2.info(`Restored from backup after failed update: ${backupPath}`);
321
303
  } catch (restoreErr) {
322
304
  logger2.error(
323
305
  `Failed to restore from backup: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`
@@ -339,9 +321,7 @@ var DownloadManager = class _DownloadManager {
339
321
  } else {
340
322
  fs.renameSync(tempPath, destPath);
341
323
  }
342
- logger2.success(
343
- `Download of ${fileName} completed successfully`
344
- );
324
+ logger2.success(`Download of ${fileName} completed successfully`);
345
325
  this.activeDownloads.delete(destPath);
346
326
  resolve();
347
327
  } catch (err) {
@@ -363,9 +343,7 @@ var DownloadManager = class _DownloadManager {
363
343
  });
364
344
  });
365
345
  file.on("error", (err) => {
366
- logger2.error(
367
- `File write error: ${err instanceof Error ? err.message : String(err)}`
368
- );
346
+ logger2.error(`File write error: ${err instanceof Error ? err.message : String(err)}`);
369
347
  file.close(() => {
370
348
  if (fs.existsSync(tempPath)) {
371
349
  try {
@@ -383,9 +361,7 @@ var DownloadManager = class _DownloadManager {
383
361
  }
384
362
  );
385
363
  request.on("error", (err) => {
386
- logger2.error(
387
- `Request error: ${err instanceof Error ? err.message : String(err)}`
388
- );
364
+ logger2.error(`Request error: ${err instanceof Error ? err.message : String(err)}`);
389
365
  if (fs.existsSync(tempPath)) {
390
366
  try {
391
367
  fs.unlinkSync(tempPath);
@@ -424,9 +400,7 @@ var DownloadManager = class _DownloadManager {
424
400
  */
425
401
  async downloadFile(url, destPath) {
426
402
  if (this.activeDownloads.has(destPath)) {
427
- logger2.info(
428
- `Download for ${destPath} already in progress, waiting for it to complete...`
429
- );
403
+ logger2.info(`Download for ${destPath} already in progress, waiting for it to complete...`);
430
404
  const existingDownload = this.activeDownloads.get(destPath);
431
405
  if (existingDownload) {
432
406
  return existingDownload;
@@ -665,9 +639,7 @@ var PlatformManager = class _PlatformManager {
665
639
  isAppleSilicon: true
666
640
  };
667
641
  }
668
- const { stdout: gpuInfo } = await execAsync(
669
- "system_profiler SPDisplaysDataType"
670
- );
642
+ const { stdout: gpuInfo } = await execAsync("system_profiler SPDisplaysDataType");
671
643
  return {
672
644
  name: gpuInfo.split("Chipset Model:")[1]?.split("\n")[0]?.trim() || "Unknown GPU",
673
645
  type: "metal",
@@ -689,9 +661,7 @@ var PlatformManager = class _PlatformManager {
689
661
  */
690
662
  async detectWindowsGPU() {
691
663
  try {
692
- const { stdout } = await execAsync(
693
- "wmic path win32_VideoController get name"
694
- );
664
+ const { stdout } = await execAsync("wmic path win32_VideoController get name");
695
665
  const gpuName = stdout.split("\n")[1].trim();
696
666
  if (gpuName.toLowerCase().includes("nvidia")) {
697
667
  const { stdout: nvidiaInfo } = await execAsync(
@@ -885,9 +855,7 @@ var getPlatformManager = () => {
885
855
 
886
856
  // src/utils/tokenizerManager.ts
887
857
  import { logger as logger4 } from "@elizaos/core";
888
- import {
889
- AutoTokenizer
890
- } from "@huggingface/transformers";
858
+ import { AutoTokenizer } from "@huggingface/transformers";
891
859
  var TokenizerManager = class _TokenizerManager {
892
860
  static instance = null;
893
861
  tokenizers;
@@ -937,18 +905,13 @@ var TokenizerManager = class _TokenizerManager {
937
905
  logger4.info("Using cached tokenizer:", { key: tokenizerKey });
938
906
  const cachedTokenizer = this.tokenizers.get(tokenizerKey);
939
907
  if (!cachedTokenizer) {
940
- throw new Error(
941
- `Tokenizer ${tokenizerKey} exists in map but returned undefined`
942
- );
908
+ throw new Error(`Tokenizer ${tokenizerKey} exists in map but returned undefined`);
943
909
  }
944
910
  return cachedTokenizer;
945
911
  }
946
912
  const fs6 = await import("fs");
947
913
  if (!fs6.existsSync(this.modelsDir)) {
948
- logger4.warn(
949
- "Models directory does not exist, creating it:",
950
- this.modelsDir
951
- );
914
+ logger4.warn("Models directory does not exist, creating it:", this.modelsDir);
952
915
  fs6.mkdirSync(this.modelsDir, { recursive: true });
953
916
  }
954
917
  logger4.info(
@@ -956,13 +919,10 @@ var TokenizerManager = class _TokenizerManager {
956
919
  this.modelsDir
957
920
  );
958
921
  try {
959
- const tokenizer = await AutoTokenizer.from_pretrained(
960
- modelConfig.tokenizer.name,
961
- {
962
- cache_dir: this.modelsDir,
963
- local_files_only: false
964
- }
965
- );
922
+ const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {
923
+ cache_dir: this.modelsDir,
924
+ local_files_only: false
925
+ });
966
926
  this.tokenizers.set(tokenizerKey, tokenizer);
967
927
  logger4.success("Tokenizer loaded successfully:", { key: tokenizerKey });
968
928
  return tokenizer;
@@ -974,13 +934,10 @@ var TokenizerManager = class _TokenizerManager {
974
934
  modelsDir: this.modelsDir
975
935
  });
976
936
  logger4.info("Retrying tokenizer loading...");
977
- const tokenizer = await AutoTokenizer.from_pretrained(
978
- modelConfig.tokenizer.name,
979
- {
980
- cache_dir: this.modelsDir,
981
- local_files_only: false
982
- }
983
- );
937
+ const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {
938
+ cache_dir: this.modelsDir,
939
+ local_files_only: false
940
+ });
984
941
  this.tokenizers.set(tokenizerKey, tokenizer);
985
942
  logger4.success("Tokenizer loaded successfully on retry:", {
986
943
  key: tokenizerKey
@@ -1078,8 +1035,15 @@ import fs2 from "fs";
1078
1035
  import path2 from "path";
1079
1036
  import { promisify as promisify2 } from "util";
1080
1037
  import { logger as logger5 } from "@elizaos/core";
1081
- import { nodewhisper } from "nodejs-whisper";
1082
1038
  var execAsync2 = promisify2(exec2);
1039
+ var whisperModule = null;
1040
+ async function getWhisper() {
1041
+ if (!whisperModule) {
1042
+ const module = await import("whisper-node");
1043
+ whisperModule = module.whisper;
1044
+ }
1045
+ return whisperModule;
1046
+ }
1083
1047
  var TranscribeManager = class _TranscribeManager {
1084
1048
  static instance = null;
1085
1049
  cacheDir;
@@ -1204,9 +1168,7 @@ var TranscribeManager = class _TranscribeManager {
1204
1168
  */
1205
1169
  async checkFFmpegAvailability() {
1206
1170
  try {
1207
- const { stdout, stderr } = await execAsync2(
1208
- "which ffmpeg || where ffmpeg"
1209
- );
1171
+ const { stdout, stderr } = await execAsync2("which ffmpeg || where ffmpeg");
1210
1172
  this.ffmpegPath = stdout.trim();
1211
1173
  this.ffmpegAvailable = true;
1212
1174
  logger5.info("FFmpeg found at:", {
@@ -1234,9 +1196,7 @@ var TranscribeManager = class _TranscribeManager {
1234
1196
  const { stdout } = await execAsync2("ffmpeg -codecs");
1235
1197
  const hasRequiredCodecs = stdout.includes("pcm_s16le") && stdout.includes("wav");
1236
1198
  if (!hasRequiredCodecs) {
1237
- throw new Error(
1238
- "FFmpeg installation missing required codecs (pcm_s16le, wav)"
1239
- );
1199
+ throw new Error("FFmpeg installation missing required codecs (pcm_s16le, wav)");
1240
1200
  }
1241
1201
  } catch (error) {
1242
1202
  logger5.error("FFmpeg capabilities verification failed:", {
@@ -1250,20 +1210,17 @@ var TranscribeManager = class _TranscribeManager {
1250
1210
  * Logs instructions on how to install FFmpeg if it is not properly installed.
1251
1211
  */
1252
1212
  logFFmpegInstallInstructions() {
1253
- logger5.warn(
1254
- "FFmpeg is required but not properly installed. Please install FFmpeg:",
1255
- {
1256
- instructions: {
1257
- mac: "brew install ffmpeg",
1258
- ubuntu: "sudo apt-get install ffmpeg",
1259
- windows: "choco install ffmpeg",
1260
- manual: "Download from https://ffmpeg.org/download.html"
1261
- },
1262
- requiredVersion: "4.0 or later",
1263
- requiredCodecs: ["pcm_s16le", "wav"],
1264
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1265
- }
1266
- );
1213
+ logger5.warn("FFmpeg is required but not properly installed. Please install FFmpeg:", {
1214
+ instructions: {
1215
+ mac: "brew install ffmpeg",
1216
+ ubuntu: "sudo apt-get install ffmpeg",
1217
+ windows: "choco install ffmpeg",
1218
+ manual: "Download from https://ffmpeg.org/download.html"
1219
+ },
1220
+ requiredVersion: "4.0 or later",
1221
+ requiredCodecs: ["pcm_s16le", "wav"],
1222
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1223
+ });
1267
1224
  }
1268
1225
  /**
1269
1226
  * Gets the singleton instance of TranscribeManager, creates a new instance if it doesn't exist.
@@ -1341,17 +1298,29 @@ var TranscribeManager = class _TranscribeManager {
1341
1298
  */
1342
1299
  async preprocessAudio(audioBuffer) {
1343
1300
  if (!this.ffmpegAvailable) {
1344
- throw new Error(
1345
- "FFmpeg is not installed. Please install FFmpeg to use audio transcription."
1346
- );
1301
+ throw new Error("FFmpeg is not installed. Please install FFmpeg to use audio transcription.");
1347
1302
  }
1348
1303
  try {
1349
- const tempInputFile = path2.join(
1350
- this.cacheDir,
1351
- `temp_input_${Date.now()}`
1352
- );
1304
+ const isWav = audioBuffer.length > 4 && audioBuffer.toString("ascii", 0, 4) === "RIFF" && audioBuffer.length > 12 && audioBuffer.toString("ascii", 8, 12) === "WAVE";
1305
+ const extension = isWav ? ".wav" : "";
1306
+ const tempInputFile = path2.join(this.cacheDir, `temp_input_${Date.now()}${extension}`);
1353
1307
  const tempWavFile = path2.join(this.cacheDir, `temp_${Date.now()}.wav`);
1354
1308
  fs2.writeFileSync(tempInputFile, audioBuffer);
1309
+ if (isWav) {
1310
+ try {
1311
+ const { stdout } = await execAsync2(
1312
+ `ffprobe -v error -show_entries stream=sample_rate,channels,bits_per_raw_sample -of json "${tempInputFile}"`
1313
+ );
1314
+ const probeResult = JSON.parse(stdout);
1315
+ const stream = probeResult.streams?.[0];
1316
+ if (stream?.sample_rate === "16000" && stream?.channels === 1 && (stream?.bits_per_raw_sample === 16 || stream?.bits_per_raw_sample === void 0)) {
1317
+ fs2.renameSync(tempInputFile, tempWavFile);
1318
+ return tempWavFile;
1319
+ }
1320
+ } catch (probeError) {
1321
+ logger5.debug("FFprobe failed, continuing with conversion:", probeError);
1322
+ }
1323
+ }
1355
1324
  await this.convertToWav(tempInputFile, tempWavFile);
1356
1325
  if (fs2.existsSync(tempInputFile)) {
1357
1326
  fs2.unlinkSync(tempInputFile);
@@ -1386,36 +1355,46 @@ var TranscribeManager = class _TranscribeManager {
1386
1355
  try {
1387
1356
  const wavFile = await this.preprocessAudio(audioBuffer);
1388
1357
  logger5.info("Starting transcription with whisper...");
1389
- const originalStdoutWrite = process.stdout.write;
1390
- const originalStderrWrite = process.stderr.write;
1391
- const noopWrite = () => true;
1392
- process.stdout.write = noopWrite;
1393
- process.stderr.write = noopWrite;
1394
- let output;
1358
+ let segments;
1395
1359
  try {
1396
- output = await nodewhisper(wavFile, {
1397
- modelName: "base.en",
1398
- autoDownloadModelName: "base.en",
1399
- verbose: false,
1360
+ const whisper = await getWhisper();
1361
+ segments = await whisper(wavFile, {
1362
+ modelName: "tiny",
1363
+ modelPath: path2.join(this.cacheDir, "models"),
1364
+ // Specify where to store models
1400
1365
  whisperOptions: {
1401
- outputInText: true,
1402
- language: "en"
1366
+ language: "en",
1367
+ word_timestamps: false
1368
+ // We don't need word-level timestamps
1403
1369
  }
1404
1370
  });
1405
- } finally {
1406
- process.stdout.write = originalStdoutWrite;
1407
- process.stderr.write = originalStderrWrite;
1371
+ } catch (whisperError) {
1372
+ const errorMessage = whisperError instanceof Error ? whisperError.message : String(whisperError);
1373
+ if (errorMessage.includes("not found") || errorMessage.includes("download")) {
1374
+ logger5.error("Whisper model not found. Please run: npx whisper-node download");
1375
+ throw new Error(
1376
+ "Whisper model not found. Please install it with: npx whisper-node download"
1377
+ );
1378
+ }
1379
+ logger5.error("Whisper transcription error:", whisperError);
1380
+ throw whisperError;
1408
1381
  }
1409
1382
  if (fs2.existsSync(wavFile)) {
1410
1383
  fs2.unlinkSync(wavFile);
1411
1384
  logger5.info("Temporary WAV file cleaned up");
1412
1385
  }
1413
- const cleanText = output.split("\n").map((line) => {
1414
- const textMatch = line.match(/](.+)$/);
1415
- return textMatch ? textMatch[1].trim() : line.trim();
1416
- }).filter((line) => line).join(" ");
1386
+ if (!segments || !Array.isArray(segments)) {
1387
+ logger5.warn("Whisper returned no segments (likely silence or very short audio)");
1388
+ return { text: "" };
1389
+ }
1390
+ if (segments.length === 0) {
1391
+ logger5.warn("No speech detected in audio");
1392
+ return { text: "" };
1393
+ }
1394
+ const cleanText = segments.map((segment) => segment.speech?.trim() || "").filter((text) => text).join(" ");
1417
1395
  logger5.success("Transcription complete:", {
1418
1396
  textLength: cleanText.length,
1397
+ segmentCount: segments.length,
1419
1398
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1420
1399
  });
1421
1400
  return { text: cleanText };
@@ -1431,12 +1410,45 @@ var TranscribeManager = class _TranscribeManager {
1431
1410
  };
1432
1411
 
1433
1412
  // src/utils/ttsManager.ts
1413
+ import { logger as logger6 } from "@elizaos/core";
1414
+ import { pipeline } from "@huggingface/transformers";
1434
1415
  import fs3 from "fs";
1435
1416
  import path3 from "path";
1436
- import { Readable } from "stream";
1437
- import { logger as logger6, prependWavHeader } from "@elizaos/core";
1438
- import { pipeline } from "@huggingface/transformers";
1439
1417
  import { fetch as fetch2 } from "undici";
1418
+ import { PassThrough, Readable } from "stream";
1419
+ function getWavHeader(audioLength, sampleRate, channelCount = 1, bitsPerSample = 16) {
1420
+ const wavHeader = Buffer.alloc(44);
1421
+ wavHeader.write("RIFF", 0);
1422
+ wavHeader.writeUInt32LE(36 + audioLength, 4);
1423
+ wavHeader.write("WAVE", 8);
1424
+ wavHeader.write("fmt ", 12);
1425
+ wavHeader.writeUInt32LE(16, 16);
1426
+ wavHeader.writeUInt16LE(1, 20);
1427
+ wavHeader.writeUInt16LE(channelCount, 22);
1428
+ wavHeader.writeUInt32LE(sampleRate, 24);
1429
+ wavHeader.writeUInt32LE(sampleRate * bitsPerSample * channelCount / 8, 28);
1430
+ wavHeader.writeUInt16LE(bitsPerSample * channelCount / 8, 32);
1431
+ wavHeader.writeUInt16LE(bitsPerSample, 34);
1432
+ wavHeader.write("data", 36);
1433
+ wavHeader.writeUInt32LE(audioLength, 40);
1434
+ return wavHeader;
1435
+ }
1436
+ function prependWavHeader(readable, audioLength, sampleRate, channelCount = 1, bitsPerSample = 16) {
1437
+ const wavHeader = getWavHeader(audioLength, sampleRate, channelCount, bitsPerSample);
1438
+ let pushedHeader = false;
1439
+ const passThrough = new PassThrough();
1440
+ readable.on("data", (data) => {
1441
+ if (!pushedHeader) {
1442
+ passThrough.push(wavHeader);
1443
+ pushedHeader = true;
1444
+ }
1445
+ passThrough.push(data);
1446
+ });
1447
+ readable.on("end", () => {
1448
+ passThrough.end();
1449
+ });
1450
+ return passThrough;
1451
+ }
1440
1452
  var TTSManager = class _TTSManager {
1441
1453
  static instance = null;
1442
1454
  cacheDir;
@@ -1463,9 +1475,7 @@ var TTSManager = class _TTSManager {
1463
1475
  }
1464
1476
  async initialize() {
1465
1477
  if (this.initializingPromise) {
1466
- logger6.debug(
1467
- "TTS initialization already in progress, awaiting existing promise."
1468
- );
1478
+ logger6.debug("TTS initialization already in progress, awaiting existing promise.");
1469
1479
  return this.initializingPromise;
1470
1480
  }
1471
1481
  if (this.initialized) {
@@ -1477,21 +1487,15 @@ var TTSManager = class _TTSManager {
1477
1487
  logger6.info("Initializing TTS with Transformers.js backend...");
1478
1488
  const ttsModelSpec = MODEL_SPECS.tts.default;
1479
1489
  if (!ttsModelSpec) {
1480
- throw new Error(
1481
- "Default TTS model specification not found in MODEL_SPECS."
1482
- );
1490
+ throw new Error("Default TTS model specification not found in MODEL_SPECS.");
1483
1491
  }
1484
1492
  const modelName = ttsModelSpec.modelId;
1485
1493
  const speakerEmbeddingUrl = ttsModelSpec.defaultSpeakerEmbeddingUrl;
1486
1494
  logger6.info(`Loading TTS pipeline for model: ${modelName}`);
1487
1495
  this.synthesizer = await pipeline("text-to-audio", modelName);
1488
- logger6.success(
1489
- `TTS pipeline loaded successfully for model: ${modelName}`
1490
- );
1496
+ logger6.success(`TTS pipeline loaded successfully for model: ${modelName}`);
1491
1497
  if (speakerEmbeddingUrl) {
1492
- const embeddingFilename = path3.basename(
1493
- new URL(speakerEmbeddingUrl).pathname
1494
- );
1498
+ const embeddingFilename = path3.basename(new URL(speakerEmbeddingUrl).pathname);
1495
1499
  const embeddingPath = path3.join(this.cacheDir, embeddingFilename);
1496
1500
  if (fs3.existsSync(embeddingPath)) {
1497
1501
  logger6.info("Loading default speaker embedding from cache...");
@@ -1503,14 +1507,10 @@ var TTSManager = class _TTSManager {
1503
1507
  );
1504
1508
  logger6.success("Default speaker embedding loaded from cache.");
1505
1509
  } else {
1506
- logger6.info(
1507
- `Downloading default speaker embedding from: ${speakerEmbeddingUrl}`
1508
- );
1510
+ logger6.info(`Downloading default speaker embedding from: ${speakerEmbeddingUrl}`);
1509
1511
  const response = await fetch2(speakerEmbeddingUrl);
1510
1512
  if (!response.ok) {
1511
- throw new Error(
1512
- `Failed to download speaker embedding: ${response.statusText}`
1513
- );
1513
+ throw new Error(`Failed to download speaker embedding: ${response.statusText}`);
1514
1514
  }
1515
1515
  const buffer = await response.arrayBuffer();
1516
1516
  this.defaultSpeakerEmbedding = new Float32Array(buffer);
@@ -1539,9 +1539,7 @@ var TTSManager = class _TTSManager {
1539
1539
  throw error;
1540
1540
  } finally {
1541
1541
  this.initializingPromise = null;
1542
- logger6.debug(
1543
- "TTS initializingPromise cleared after completion/failure."
1544
- );
1542
+ logger6.debug("TTS initializingPromise cleared after completion/failure.");
1545
1543
  }
1546
1544
  })();
1547
1545
  return this.initializingPromise;
@@ -1650,10 +1648,7 @@ var VisionManager = class _VisionManager {
1650
1648
  this.modelsDir = path4.join(path4.dirname(cacheDir), "models", "vision");
1651
1649
  this.cacheDir = cacheDir;
1652
1650
  this.ensureModelsDirExists();
1653
- this.downloadManager = DownloadManager.getInstance(
1654
- this.cacheDir,
1655
- this.modelsDir
1656
- );
1651
+ this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);
1657
1652
  this.platformConfig = this.getPlatformConfig();
1658
1653
  logger7.debug("VisionManager initialized");
1659
1654
  }
@@ -1717,11 +1712,7 @@ var VisionManager = class _VisionManager {
1717
1712
  * @returns {boolean} - Returns true if cache exists, otherwise returns false.
1718
1713
  */
1719
1714
  checkCacheExists(modelId, type) {
1720
- const modelPath = path4.join(
1721
- this.modelsDir,
1722
- modelId.replace("/", "--"),
1723
- type
1724
- );
1715
+ const modelPath = path4.join(this.modelsDir, modelId.replace("/", "--"), type);
1725
1716
  if (existsSync(modelPath)) {
1726
1717
  logger7.info(`${type} found at: ${modelPath}`);
1727
1718
  return true;
@@ -1759,9 +1750,7 @@ var VisionManager = class _VisionManager {
1759
1750
  * @returns {object} The model configuration object containing device, dtype, and cache_dir.
1760
1751
  */
1761
1752
  getModelConfig(componentName) {
1762
- const component = this.modelComponents.find(
1763
- (c) => c.name === componentName
1764
- );
1753
+ const component = this.modelComponents.find((c) => c.name === componentName);
1765
1754
  return {
1766
1755
  device: this.platformConfig.device,
1767
1756
  dtype: component?.dtype || "fp32",
@@ -1777,9 +1766,7 @@ var VisionManager = class _VisionManager {
1777
1766
  async initialize() {
1778
1767
  try {
1779
1768
  if (this.initialized) {
1780
- logger7.info(
1781
- "Vision model already initialized, skipping initialization"
1782
- );
1769
+ logger7.info("Vision model already initialized, skipping initialization");
1783
1770
  return;
1784
1771
  }
1785
1772
  logger7.info("Starting vision model initialization...");
@@ -1795,32 +1782,25 @@ var VisionManager = class _VisionManager {
1795
1782
  try {
1796
1783
  let lastProgress = -1;
1797
1784
  const modelCached = this.checkCacheExists(modelSpec.modelId, "model");
1798
- const model = await Florence2ForConditionalGeneration.from_pretrained(
1799
- modelSpec.modelId,
1800
- {
1801
- device: "cpu",
1802
- cache_dir: this.modelsDir,
1803
- local_files_only: modelCached,
1804
- revision: "main",
1805
- progress_callback: (progressInfo) => {
1806
- if (modelCached || this.modelDownloaded) return;
1807
- const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
1808
- const currentProgress = Math.round(progress * 100);
1809
- if (currentProgress > lastProgress + 9 || currentProgress === 100) {
1810
- lastProgress = currentProgress;
1811
- const barLength = 30;
1812
- const filledLength = Math.floor(
1813
- currentProgress / 100 * barLength
1814
- );
1815
- const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
1816
- logger7.info(
1817
- `Downloading vision model: ${progressBar} ${currentProgress}%`
1818
- );
1819
- if (currentProgress === 100) this.modelDownloaded = true;
1820
- }
1785
+ const model = await Florence2ForConditionalGeneration.from_pretrained(modelSpec.modelId, {
1786
+ device: "cpu",
1787
+ cache_dir: this.modelsDir,
1788
+ local_files_only: modelCached,
1789
+ revision: "main",
1790
+ progress_callback: (progressInfo) => {
1791
+ if (modelCached || this.modelDownloaded) return;
1792
+ const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
1793
+ const currentProgress = Math.round(progress * 100);
1794
+ if (currentProgress > lastProgress + 9 || currentProgress === 100) {
1795
+ lastProgress = currentProgress;
1796
+ const barLength = 30;
1797
+ const filledLength = Math.floor(currentProgress / 100 * barLength);
1798
+ const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
1799
+ logger7.info(`Downloading vision model: ${progressBar} ${currentProgress}%`);
1800
+ if (currentProgress === 100) this.modelDownloaded = true;
1821
1801
  }
1822
1802
  }
1823
- );
1803
+ });
1824
1804
  this.model = model;
1825
1805
  logger7.success("Florence2 model loaded successfully");
1826
1806
  } catch (error) {
@@ -1833,35 +1813,25 @@ var VisionManager = class _VisionManager {
1833
1813
  }
1834
1814
  logger7.info("Loading vision tokenizer...");
1835
1815
  try {
1836
- const tokenizerCached = this.checkCacheExists(
1837
- modelSpec.modelId,
1838
- "tokenizer"
1839
- );
1816
+ const tokenizerCached = this.checkCacheExists(modelSpec.modelId, "tokenizer");
1840
1817
  let tokenizerProgress = -1;
1841
- this.tokenizer = await AutoTokenizer2.from_pretrained(
1842
- modelSpec.modelId,
1843
- {
1844
- cache_dir: this.modelsDir,
1845
- local_files_only: tokenizerCached,
1846
- progress_callback: (progressInfo) => {
1847
- if (tokenizerCached || this.tokenizerDownloaded) return;
1848
- const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
1849
- const currentProgress = Math.round(progress * 100);
1850
- if (currentProgress !== tokenizerProgress) {
1851
- tokenizerProgress = currentProgress;
1852
- const barLength = 30;
1853
- const filledLength = Math.floor(
1854
- currentProgress / 100 * barLength
1855
- );
1856
- const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
1857
- logger7.info(
1858
- `Downloading vision tokenizer: ${progressBar} ${currentProgress}%`
1859
- );
1860
- if (currentProgress === 100) this.tokenizerDownloaded = true;
1861
- }
1818
+ this.tokenizer = await AutoTokenizer2.from_pretrained(modelSpec.modelId, {
1819
+ cache_dir: this.modelsDir,
1820
+ local_files_only: tokenizerCached,
1821
+ progress_callback: (progressInfo) => {
1822
+ if (tokenizerCached || this.tokenizerDownloaded) return;
1823
+ const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
1824
+ const currentProgress = Math.round(progress * 100);
1825
+ if (currentProgress !== tokenizerProgress) {
1826
+ tokenizerProgress = currentProgress;
1827
+ const barLength = 30;
1828
+ const filledLength = Math.floor(currentProgress / 100 * barLength);
1829
+ const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
1830
+ logger7.info(`Downloading vision tokenizer: ${progressBar} ${currentProgress}%`);
1831
+ if (currentProgress === 100) this.tokenizerDownloaded = true;
1862
1832
  }
1863
1833
  }
1864
- );
1834
+ });
1865
1835
  logger7.success("Vision tokenizer loaded successfully");
1866
1836
  } catch (error) {
1867
1837
  logger7.error("Failed to load tokenizer:", {
@@ -1873,36 +1843,26 @@ var VisionManager = class _VisionManager {
1873
1843
  }
1874
1844
  logger7.info("Loading vision processor...");
1875
1845
  try {
1876
- const processorCached = this.checkCacheExists(
1877
- modelSpec.modelId,
1878
- "processor"
1879
- );
1846
+ const processorCached = this.checkCacheExists(modelSpec.modelId, "processor");
1880
1847
  let processorProgress = -1;
1881
- this.processor = await AutoProcessor.from_pretrained(
1882
- modelSpec.modelId,
1883
- {
1884
- device: "cpu",
1885
- cache_dir: this.modelsDir,
1886
- local_files_only: processorCached,
1887
- progress_callback: (progressInfo) => {
1888
- if (processorCached || this.processorDownloaded) return;
1889
- const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
1890
- const currentProgress = Math.round(progress * 100);
1891
- if (currentProgress !== processorProgress) {
1892
- processorProgress = currentProgress;
1893
- const barLength = 30;
1894
- const filledLength = Math.floor(
1895
- currentProgress / 100 * barLength
1896
- );
1897
- const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
1898
- logger7.info(
1899
- `Downloading vision processor: ${progressBar} ${currentProgress}%`
1900
- );
1901
- if (currentProgress === 100) this.processorDownloaded = true;
1902
- }
1848
+ this.processor = await AutoProcessor.from_pretrained(modelSpec.modelId, {
1849
+ device: "cpu",
1850
+ cache_dir: this.modelsDir,
1851
+ local_files_only: processorCached,
1852
+ progress_callback: (progressInfo) => {
1853
+ if (processorCached || this.processorDownloaded) return;
1854
+ const progress = "progress" in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;
1855
+ const currentProgress = Math.round(progress * 100);
1856
+ if (currentProgress !== processorProgress) {
1857
+ processorProgress = currentProgress;
1858
+ const barLength = 30;
1859
+ const filledLength = Math.floor(currentProgress / 100 * barLength);
1860
+ const progressBar = "\u25B0".repeat(filledLength) + "\u25B1".repeat(barLength - filledLength);
1861
+ logger7.info(`Downloading vision processor: ${progressBar} ${currentProgress}%`);
1862
+ if (currentProgress === 100) this.processorDownloaded = true;
1903
1863
  }
1904
1864
  }
1905
- );
1865
+ });
1906
1866
  logger7.success("Vision processor loaded successfully");
1907
1867
  } catch (error) {
1908
1868
  logger7.error("Failed to load vision processor:", {
@@ -2139,14 +2099,8 @@ var LocalAIManager = class _LocalAIManager {
2139
2099
  */
2140
2100
  _postValidateInit() {
2141
2101
  this._setupModelsDir();
2142
- this.downloadManager = DownloadManager.getInstance(
2143
- this.cacheDir,
2144
- this.modelsDir
2145
- );
2146
- this.tokenizerManager = TokenizerManager.getInstance(
2147
- this.cacheDir,
2148
- this.modelsDir
2149
- );
2102
+ this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);
2103
+ this.tokenizerManager = TokenizerManager.getInstance(this.cacheDir, this.modelsDir);
2150
2104
  this.visionManager = VisionManager.getInstance(this.cacheDir);
2151
2105
  this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);
2152
2106
  this.ttsManager = TTSManager.getInstance(this.cacheDir);
@@ -2159,10 +2113,7 @@ var LocalAIManager = class _LocalAIManager {
2159
2113
  const modelsDirEnv = this.config?.MODELS_DIR?.trim() || process.env.MODELS_DIR?.trim();
2160
2114
  if (modelsDirEnv) {
2161
2115
  this.modelsDir = path5.resolve(modelsDirEnv);
2162
- logger8.info(
2163
- "Using models directory from MODELS_DIR environment variable:",
2164
- this.modelsDir
2165
- );
2116
+ logger8.info("Using models directory from MODELS_DIR environment variable:", this.modelsDir);
2166
2117
  } else {
2167
2118
  this.modelsDir = path5.join(os3.homedir(), ".eliza", "models");
2168
2119
  logger8.info(
@@ -2172,10 +2123,7 @@ var LocalAIManager = class _LocalAIManager {
2172
2123
  }
2173
2124
  if (!fs5.existsSync(this.modelsDir)) {
2174
2125
  fs5.mkdirSync(this.modelsDir, { recursive: true });
2175
- logger8.debug(
2176
- "Ensured models directory exists (created):",
2177
- this.modelsDir
2178
- );
2126
+ logger8.debug("Ensured models directory exists (created):", this.modelsDir);
2179
2127
  } else {
2180
2128
  logger8.debug("Models directory already exists:", this.modelsDir);
2181
2129
  }
@@ -2188,10 +2136,7 @@ var LocalAIManager = class _LocalAIManager {
2188
2136
  const cacheDirEnv = this.config?.CACHE_DIR?.trim() || process.env.CACHE_DIR?.trim();
2189
2137
  if (cacheDirEnv) {
2190
2138
  this.cacheDir = path5.resolve(cacheDirEnv);
2191
- logger8.info(
2192
- "Using cache directory from CACHE_DIR environment variable:",
2193
- this.cacheDir
2194
- );
2139
+ logger8.info("Using cache directory from CACHE_DIR environment variable:", this.cacheDir);
2195
2140
  } else {
2196
2141
  const cacheDir = path5.join(os3.homedir(), ".eliza", "cache");
2197
2142
  if (!fs5.existsSync(cacheDir)) {
@@ -2238,24 +2183,12 @@ var LocalAIManager = class _LocalAIManager {
2238
2183
  logger8.info("Initializing environment configuration...");
2239
2184
  this.config = await validateConfig();
2240
2185
  this._postValidateInit();
2241
- this.modelPath = path5.join(
2242
- this.modelsDir,
2243
- this.config.LOCAL_SMALL_MODEL
2244
- );
2245
- this.mediumModelPath = path5.join(
2246
- this.modelsDir,
2247
- this.config.LOCAL_LARGE_MODEL
2248
- );
2249
- this.embeddingModelPath = path5.join(
2250
- this.modelsDir,
2251
- this.config.LOCAL_EMBEDDING_MODEL
2252
- );
2186
+ this.modelPath = path5.join(this.modelsDir, this.config.LOCAL_SMALL_MODEL);
2187
+ this.mediumModelPath = path5.join(this.modelsDir, this.config.LOCAL_LARGE_MODEL);
2188
+ this.embeddingModelPath = path5.join(this.modelsDir, this.config.LOCAL_EMBEDDING_MODEL);
2253
2189
  logger8.info("Using small model path:", basename(this.modelPath));
2254
2190
  logger8.info("Using medium model path:", basename(this.mediumModelPath));
2255
- logger8.info(
2256
- "Using embedding model path:",
2257
- basename(this.embeddingModelPath)
2258
- );
2191
+ logger8.info("Using embedding model path:", basename(this.embeddingModelPath));
2259
2192
  logger8.info("Environment configuration validated and model paths set");
2260
2193
  this.environmentInitialized = true;
2261
2194
  logger8.success("Environment initialization complete");
@@ -2293,10 +2226,7 @@ var LocalAIManager = class _LocalAIManager {
2293
2226
  modelPathToDownload = modelType === ModelType.TEXT_LARGE ? this.mediumModelPath : this.modelPath;
2294
2227
  }
2295
2228
  try {
2296
- return await this.downloadManager.downloadModel(
2297
- modelSpec,
2298
- modelPathToDownload
2299
- );
2229
+ return await this.downloadManager.downloadModel(modelSpec, modelPathToDownload);
2300
2230
  } catch (error) {
2301
2231
  logger8.error("Model download failed:", {
2302
2232
  error: error instanceof Error ? error.message : String(error),
@@ -2351,10 +2281,7 @@ var LocalAIManager = class _LocalAIManager {
2351
2281
  logger8.info("Initializing embedding model...");
2352
2282
  logger8.info("Models directory:", this.modelsDir);
2353
2283
  if (!fs5.existsSync(this.modelsDir)) {
2354
- logger8.warn(
2355
- "Models directory does not exist, creating it:",
2356
- this.modelsDir
2357
- );
2284
+ logger8.warn("Models directory does not exist, creating it:", this.modelsDir);
2358
2285
  fs5.mkdirSync(this.modelsDir, { recursive: true });
2359
2286
  }
2360
2287
  await this.downloadModel(ModelType.TEXT_EMBEDDING);
@@ -2508,10 +2435,7 @@ var LocalAIManager = class _LocalAIManager {
2508
2435
  runtime: !!params.runtime,
2509
2436
  stopSequences: params.stopSequences
2510
2437
  });
2511
- const tokens = await this.tokenizerManager.encode(
2512
- params.prompt,
2513
- this.activeModelConfig
2514
- );
2438
+ const tokens = await this.tokenizerManager.encode(params.prompt, this.activeModelConfig);
2515
2439
  logger8.info("Input tokens:", { count: tokens.length });
2516
2440
  const systemMessage = "You are a helpful AI assistant. Respond to the current request only.";
2517
2441
  await this.chatSession.prompt(systemMessage, {
@@ -2701,9 +2625,7 @@ var LocalAIManager = class _LocalAIManager {
2701
2625
  try {
2702
2626
  await this.initializeEnvironment();
2703
2627
  if (!this.transcribeManager) {
2704
- this.transcribeManager = TranscribeManager.getInstance(
2705
- this.cacheDir
2706
- );
2628
+ this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);
2707
2629
  }
2708
2630
  const ffmpegReady = await this.transcribeManager.ensureFFmpeg();
2709
2631
  if (!ffmpegReady) {
@@ -2715,9 +2637,7 @@ var LocalAIManager = class _LocalAIManager {
2715
2637
  );
2716
2638
  }
2717
2639
  this.transcriptionInitialized = true;
2718
- logger8.info(
2719
- "Transcription prerequisites (FFmpeg) checked and ready."
2720
- );
2640
+ logger8.info("Transcription prerequisites (FFmpeg) checked and ready.");
2721
2641
  logger8.info("Transcription model initialized successfully");
2722
2642
  } catch (error) {
2723
2643
  logger8.error("Failed to initialize transcription model:", error);
@@ -2800,9 +2720,7 @@ var localAiPlugin = {
2800
2720
  const text = params?.text;
2801
2721
  try {
2802
2722
  if (!text) {
2803
- logger8.debug(
2804
- "Null or empty text input for embedding, returning zero vector"
2805
- );
2723
+ logger8.debug("Null or empty text input for embedding, returning zero vector");
2806
2724
  return new Array(384).fill(0);
2807
2725
  }
2808
2726
  return await localAIManager.generateEmbedding(text);
@@ -2854,13 +2772,8 @@ var localAiPlugin = {
2854
2772
  try {
2855
2773
  jsonObject = JSON.parse(extractedJsonText);
2856
2774
  } catch (parseError) {
2857
- logger8.debug(
2858
- "Initial JSON parse failed, attempting to fix common issues"
2859
- );
2860
- const fixedJson = extractedJsonText.replace(/:\s*"([^"]*)(?:\n)([^"]*)"/g, ': "$1\\n$2"').replace(
2861
- /"([^"]*?)[^a-zA-Z0-9\s\.,;:\-_\(\)"'\[\]{}]([^"]*?)"/g,
2862
- '"$1$2"'
2863
- ).replace(/(\s*)(\w+)(\s*):/g, '$1"$2"$3:').replace(/,(\s*[\]}])/g, "$1");
2775
+ logger8.debug("Initial JSON parse failed, attempting to fix common issues");
2776
+ 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");
2864
2777
  try {
2865
2778
  jsonObject = JSON.parse(fixedJson);
2866
2779
  } catch (finalError) {
@@ -2932,13 +2845,8 @@ var localAiPlugin = {
2932
2845
  try {
2933
2846
  jsonObject = JSON.parse(cleanedJsonText);
2934
2847
  } catch (parseError) {
2935
- logger8.debug(
2936
- "Initial JSON parse failed, attempting to fix common issues"
2937
- );
2938
- const fixedJson = cleanedJsonText.replace(/:\s*"([^"]*)(?:\n)([^"]*)"/g, ': "$1\\n$2"').replace(
2939
- /"([^"]*?)[^a-zA-Z0-9\s\.,;:\-_\(\)"'\[\]{}]([^"]*?)"/g,
2940
- '"$1$2"'
2941
- ).replace(/(\s*)(\w+)(\s*):/g, '$1"$2"$3:').replace(/,(\s*[\]}])/g, "$1");
2848
+ logger8.debug("Initial JSON parse failed, attempting to fix common issues");
2849
+ 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");
2942
2850
  try {
2943
2851
  jsonObject = JSON.parse(fixedJson);
2944
2852
  } catch (finalError) {
@@ -3093,16 +3001,10 @@ var localAiPlugin = {
3093
3001
  fn: async (runtime) => {
3094
3002
  try {
3095
3003
  logger8.info("Starting TEXT_EMBEDDING test");
3096
- const embedding = await runtime.useModel(
3097
- ModelType.TEXT_EMBEDDING,
3098
- {
3099
- text: "This is a test of the text embedding model."
3100
- }
3101
- );
3102
- logger8.info(
3103
- "Embedding generated with dimensions:",
3104
- embedding.length
3105
- );
3004
+ const embedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, {
3005
+ text: "This is a test of the text embedding model."
3006
+ });
3007
+ logger8.info("Embedding generated with dimensions:", embedding.length);
3106
3008
  if (!Array.isArray(embedding)) {
3107
3009
  throw new Error("Embedding is not an array");
3108
3010
  }
@@ -3112,10 +3014,7 @@ var localAiPlugin = {
3112
3014
  if (embedding.some((val) => typeof val !== "number")) {
3113
3015
  throw new Error("Embedding contains non-numeric values");
3114
3016
  }
3115
- const nullEmbedding = await runtime.useModel(
3116
- ModelType.TEXT_EMBEDDING,
3117
- null
3118
- );
3017
+ const nullEmbedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, null);
3119
3018
  if (!Array.isArray(nullEmbedding) || nullEmbedding.some((val) => val !== 0)) {
3120
3019
  throw new Error("Null input did not return zero vector");
3121
3020
  }
@@ -3135,10 +3034,7 @@ var localAiPlugin = {
3135
3034
  try {
3136
3035
  logger8.info("Starting TEXT_TOKENIZER_ENCODE test");
3137
3036
  const text = "Hello tokenizer test!";
3138
- const tokens = await runtime.useModel(
3139
- ModelType.TEXT_TOKENIZER_ENCODE,
3140
- { text }
3141
- );
3037
+ const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, { text });
3142
3038
  logger8.info("Encoded tokens:", { count: tokens.length });
3143
3039
  if (!Array.isArray(tokens)) {
3144
3040
  throw new Error("Tokens output is not an array");
@@ -3149,9 +3045,7 @@ var localAiPlugin = {
3149
3045
  if (tokens.some((token) => !Number.isInteger(token))) {
3150
3046
  throw new Error("Tokens contain non-integer values");
3151
3047
  }
3152
- logger8.success(
3153
- "TEXT_TOKENIZER_ENCODE test completed successfully"
3154
- );
3048
+ logger8.success("TEXT_TOKENIZER_ENCODE test completed successfully");
3155
3049
  } catch (error) {
3156
3050
  logger8.error("TEXT_TOKENIZER_ENCODE test failed:", {
3157
3051
  error: error instanceof Error ? error.message : String(error),
@@ -3167,18 +3061,12 @@ var localAiPlugin = {
3167
3061
  try {
3168
3062
  logger8.info("Starting TEXT_TOKENIZER_DECODE test");
3169
3063
  const originalText = "Hello tokenizer test!";
3170
- const tokens = await runtime.useModel(
3171
- ModelType.TEXT_TOKENIZER_ENCODE,
3172
- {
3173
- text: originalText
3174
- }
3175
- );
3176
- const decodedText = await runtime.useModel(
3177
- ModelType.TEXT_TOKENIZER_DECODE,
3178
- {
3179
- tokens
3180
- }
3181
- );
3064
+ const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, {
3065
+ text: originalText
3066
+ });
3067
+ const decodedText = await runtime.useModel(ModelType.TEXT_TOKENIZER_DECODE, {
3068
+ tokens
3069
+ });
3182
3070
  logger8.info("Round trip tokenization:", {
3183
3071
  original: originalText,
3184
3072
  decoded: decodedText
@@ -3186,9 +3074,7 @@ var localAiPlugin = {
3186
3074
  if (typeof decodedText !== "string") {
3187
3075
  throw new Error("Decoded output is not a string");
3188
3076
  }
3189
- logger8.success(
3190
- "TEXT_TOKENIZER_DECODE test completed successfully"
3191
- );
3077
+ logger8.success("TEXT_TOKENIZER_DECODE test completed successfully");
3192
3078
  } catch (error) {
3193
3079
  logger8.error("TEXT_TOKENIZER_DECODE test failed:", {
3194
3080
  error: error instanceof Error ? error.message : String(error),
@@ -3203,11 +3089,8 @@ var localAiPlugin = {
3203
3089
  fn: async (runtime) => {
3204
3090
  try {
3205
3091
  logger8.info("Starting IMAGE_DESCRIPTION test");
3206
- const imageUrl = "https://raw.githubusercontent.com/microsoft/FLAML/main/website/static/img/flaml.png";
3207
- const result = await runtime.useModel(
3208
- ModelType.IMAGE_DESCRIPTION,
3209
- imageUrl
3210
- );
3092
+ const imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/320px-Cat03.jpg";
3093
+ const result = await runtime.useModel(ModelType.IMAGE_DESCRIPTION, imageUrl);
3211
3094
  logger8.info("Image description result:", result);
3212
3095
  if (!result || typeof result !== "object") {
3213
3096
  throw new Error("Invalid response format");
@@ -3233,37 +3116,37 @@ var localAiPlugin = {
3233
3116
  fn: async (runtime) => {
3234
3117
  try {
3235
3118
  logger8.info("Starting TRANSCRIPTION test");
3236
- const audioData = new Uint8Array([
3237
- 82,
3238
- 73,
3239
- 70,
3240
- 70,
3241
- // "RIFF"
3242
- 36,
3243
- 0,
3244
- 0,
3245
- 0,
3246
- // Chunk size
3247
- 87,
3248
- 65,
3249
- 86,
3250
- 69,
3251
- // "WAVE"
3252
- 102,
3253
- 109,
3254
- 116,
3255
- 32
3256
- // "fmt "
3257
- ]);
3258
- const audioBuffer = Buffer.from(audioData);
3259
- const transcription = await runtime.useModel(
3260
- ModelType.TRANSCRIPTION,
3261
- audioBuffer
3262
- );
3119
+ const channels = 1;
3120
+ const sampleRate = 16e3;
3121
+ const bitsPerSample = 16;
3122
+ const duration = 0.5;
3123
+ const numSamples = Math.floor(sampleRate * duration);
3124
+ const dataSize = numSamples * channels * (bitsPerSample / 8);
3125
+ const buffer = Buffer.alloc(44 + dataSize);
3126
+ buffer.write("RIFF", 0);
3127
+ buffer.writeUInt32LE(36 + dataSize, 4);
3128
+ buffer.write("WAVE", 8);
3129
+ buffer.write("fmt ", 12);
3130
+ buffer.writeUInt32LE(16, 16);
3131
+ buffer.writeUInt16LE(1, 20);
3132
+ buffer.writeUInt16LE(channels, 22);
3133
+ buffer.writeUInt32LE(sampleRate, 24);
3134
+ buffer.writeUInt32LE(sampleRate * channels * (bitsPerSample / 8), 28);
3135
+ buffer.writeUInt16LE(channels * (bitsPerSample / 8), 32);
3136
+ buffer.writeUInt16LE(bitsPerSample, 34);
3137
+ buffer.write("data", 36);
3138
+ buffer.writeUInt32LE(dataSize, 40);
3139
+ const frequency = 440;
3140
+ for (let i = 0; i < numSamples; i++) {
3141
+ const sample = Math.sin(2 * Math.PI * frequency * i / sampleRate) * 0.1 * 32767;
3142
+ buffer.writeInt16LE(Math.floor(sample), 44 + i * 2);
3143
+ }
3144
+ const transcription = await runtime.useModel(ModelType.TRANSCRIPTION, buffer);
3263
3145
  logger8.info("Transcription result:", transcription);
3264
3146
  if (typeof transcription !== "string") {
3265
3147
  throw new Error("Transcription result is not a string");
3266
3148
  }
3149
+ logger8.info("Transcription completed (may be empty for non-speech audio)");
3267
3150
  logger8.success("TRANSCRIPTION test completed successfully");
3268
3151
  } catch (error) {
3269
3152
  logger8.error("TRANSCRIPTION test failed:", {
@@ -3280,10 +3163,7 @@ var localAiPlugin = {
3280
3163
  try {
3281
3164
  logger8.info("Starting TEXT_TO_SPEECH test");
3282
3165
  const testText = "This is a test of the text to speech system.";
3283
- const audioStream = await runtime.useModel(
3284
- ModelType.TEXT_TO_SPEECH,
3285
- testText
3286
- );
3166
+ const audioStream = await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText);
3287
3167
  if (!(audioStream instanceof Readable2)) {
3288
3168
  throw new Error("TTS output is not a readable stream");
3289
3169
  }