@elizaos/plugin-local-ai 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2395,6 +2395,10 @@ var LocalAIManager = class _LocalAIManager {
2395
2395
  */
2396
2396
  async generateText(params) {
2397
2397
  try {
2398
+ if (this.ctx) {
2399
+ this.ctx.dispose();
2400
+ this.ctx = void 0;
2401
+ }
2398
2402
  await this.initializeEnvironment();
2399
2403
  logger8.info("Generating text with model:", params.modelType);
2400
2404
  if (params.modelType === ModelType.TEXT_LARGE) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/environment.ts","../src/types.ts","../src/utils/downloadManager.ts","../src/utils/platform.ts","../src/utils/tokenizerManager.ts","../src/utils/transcribeManager.ts","../src/utils/ttsManager.ts","../src/utils/visionManager.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\nimport type {\n GenerateTextParams,\n ModelTypeName,\n TextEmbeddingParams,\n ObjectGenerationParams,\n} from '@elizaos/core';\nimport { type IAgentRuntime, ModelType, type Plugin, logger } from '@elizaos/core';\nimport {\n type Llama,\n LlamaChatSession,\n type LlamaContext,\n type LlamaContextSequence,\n LlamaEmbeddingContext,\n type LlamaModel,\n getLlama,\n} from 'node-llama-cpp';\nimport { validateConfig, type Config } from './environment';\nimport { MODEL_SPECS, type ModelSpec, type EmbeddingModelSpec } from './types';\nimport { DownloadManager } from './utils/downloadManager';\nimport { getPlatformManager } from './utils/platform';\nimport { TokenizerManager } from './utils/tokenizerManager';\nimport { TranscribeManager } from './utils/transcribeManager';\nimport { TTSManager } from './utils/ttsManager';\nimport { VisionManager } from './utils/visionManager';\nimport { basename } from 'path';\n\n// Words to punish in LLM responses\n/**\n * Array containing words that should trigger a punishment when used in a message.\n * This array includes words like \"please\", \"feel\", \"free\", punctuation marks, and various topic-related words.\n * @type {string[]}\n */\nconst wordsToPunish = [\n ' please',\n ' feel',\n ' free',\n '!',\n '–',\n '—',\n '?',\n '.',\n ',',\n '; ',\n ' cosmos',\n ' tapestry',\n ' tapestries',\n ' glitch',\n ' matrix',\n ' cyberspace',\n ' troll',\n ' questions',\n ' topics',\n ' discuss',\n ' basically',\n ' simulation',\n ' simulate',\n ' universe',\n ' like',\n ' debug',\n ' debugging',\n ' wild',\n ' existential',\n ' juicy',\n ' circuits',\n ' help',\n ' ask',\n ' happy',\n ' just',\n ' cosmic',\n ' cool',\n ' joke',\n ' punchline',\n ' fancy',\n ' glad',\n ' assist',\n ' algorithm',\n ' Indeed',\n ' Furthermore',\n ' However',\n ' Notably',\n ' Therefore',\n];\n\n/**\n * Class representing a LocalAIManager.\n * @property {LocalAIManager | null} instance - The static instance of LocalAIManager.\n * @property {Llama | undefined} llama - The llama object.\n * @property {LlamaModel | undefined} smallModel - The small LlamaModel object.\n * @property {LlamaModel | undefined} mediumModel - The medium LlamaModel object.\n * @property {LlamaContext | undefined} ctx - The LlamaContext object.\n * @property {LlamaContextSequence | undefined} sequence - The LlamaContextSequence object.\n * @property {LlamaChatSession | undefined} chatSession - The LlamaChatSession object.\n * @property {string} modelPath - The path to the model.\n */\nclass LocalAIManager {\n private static instance: LocalAIManager | null = null;\n private llama: Llama | undefined;\n private smallModel: LlamaModel | undefined;\n private mediumModel: LlamaModel | undefined;\n private embeddingModel: LlamaModel | undefined;\n private embeddingContext: LlamaEmbeddingContext | undefined;\n private ctx: LlamaContext | undefined;\n private sequence: LlamaContextSequence | undefined;\n private chatSession: LlamaChatSession | undefined;\n private modelPath!: string;\n private mediumModelPath!: string;\n private embeddingModelPath!: string;\n private cacheDir!: string;\n private tokenizerManager!: TokenizerManager;\n private downloadManager!: DownloadManager;\n private visionManager!: VisionManager;\n private activeModelConfig: ModelSpec;\n private embeddingModelConfig: EmbeddingModelSpec;\n private transcribeManager!: TranscribeManager;\n private ttsManager!: TTSManager;\n private config: Config | null = null; // Store validated config\n\n // Initialization state flag\n private smallModelInitialized = false;\n private mediumModelInitialized = false;\n private embeddingInitialized = false;\n private visionInitialized = false;\n private transcriptionInitialized = false;\n private ttsInitialized = false;\n private environmentInitialized = false; // Add flag for environment initialization\n\n // Initialization promises to prevent duplicate initialization\n private smallModelInitializingPromise: Promise<void> | null = null;\n private mediumModelInitializingPromise: Promise<void> | null = null;\n private embeddingInitializingPromise: Promise<void> | null = null;\n private visionInitializingPromise: Promise<void> | null = null;\n private transcriptionInitializingPromise: Promise<void> | null = null;\n private ttsInitializingPromise: Promise<void> | null = null;\n private environmentInitializingPromise: Promise<void> | null = null; // Add promise for environment\n\n private modelsDir!: string;\n\n /**\n * Private constructor function to initialize base managers and paths.\n * Model paths are set after environment initialization.\n */\n private constructor() {\n this.config = validateConfig();\n\n this._setupCacheDir();\n\n // Initialize active model config (default)\n this.activeModelConfig = MODEL_SPECS.small;\n // Initialize embedding model config (spec details)\n this.embeddingModelConfig = MODEL_SPECS.embedding;\n }\n\n /**\n * Post-validation initialization steps that require config to be set.\n * Called after config validation in initializeEnvironment.\n */\n private _postValidateInit(): void {\n this._setupModelsDir();\n\n // Initialize managers that depend on modelsDir\n this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);\n this.tokenizerManager = TokenizerManager.getInstance(this.cacheDir, this.modelsDir);\n this.visionManager = VisionManager.getInstance(this.cacheDir);\n this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);\n this.ttsManager = TTSManager.getInstance(this.cacheDir);\n }\n\n /**\n * Sets up the models directory, reading from config or environment variables,\n * and ensures the directory exists.\n */\n private _setupModelsDir(): void {\n // Set up models directory consistently, similar to cacheDir\n const modelsDirEnv = this.config?.MODELS_DIR?.trim() || process.env.MODELS_DIR?.trim();\n if (modelsDirEnv) {\n this.modelsDir = path.resolve(modelsDirEnv);\n logger.info('Using models directory from MODELS_DIR environment variable:', this.modelsDir);\n } else {\n this.modelsDir = path.join(os.homedir(), '.eliza', 'models');\n logger.info(\n 'MODELS_DIR environment variable not set, using default models directory:',\n this.modelsDir\n );\n }\n\n // Ensure models directory exists\n if (!fs.existsSync(this.modelsDir)) {\n fs.mkdirSync(this.modelsDir, { recursive: true });\n logger.debug('Ensured models directory exists (created):', this.modelsDir);\n } else {\n logger.debug('Models directory already exists:', this.modelsDir);\n }\n }\n\n /**\n * Sets up the cache directory, reading from config or environment variables,\n * and ensures the directory exists.\n */\n private _setupCacheDir(): void {\n // Set up cache directory\n const cacheDirEnv = this.config?.CACHE_DIR?.trim() || process.env.CACHE_DIR?.trim();\n if (cacheDirEnv) {\n this.cacheDir = path.resolve(cacheDirEnv);\n logger.info('Using cache directory from CACHE_DIR environment variable:', this.cacheDir);\n } else {\n const cacheDir = path.join(os.homedir(), '.eliza', 'cache');\n // Ensure cache directory exists\n if (!fs.existsSync(cacheDir)) {\n fs.mkdirSync(cacheDir, { recursive: true });\n logger.debug('Ensuring cache directory exists (created):', cacheDir);\n }\n this.cacheDir = cacheDir;\n logger.info(\n 'CACHE_DIR environment variable not set, using default cache directory:',\n this.cacheDir\n );\n }\n // Ensure cache directory exists if specified via env var but not yet created\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n logger.debug('Ensured cache directory exists (created):', this.cacheDir);\n } else {\n logger.debug('Cache directory already exists:', this.cacheDir);\n }\n }\n\n /**\n * Retrieves the singleton instance of LocalAIManager. If an instance does not already exist, a new one is created and returned.\n * @returns {LocalAIManager} The singleton instance of LocalAIManager\n */\n public static getInstance(): LocalAIManager {\n if (!LocalAIManager.instance) {\n LocalAIManager.instance = new LocalAIManager();\n }\n return LocalAIManager.instance;\n }\n\n /**\n * Initializes the environment by validating the configuration and setting model paths.\n * Now public to be callable from plugin init and model handlers.\n *\n * @returns {Promise<void>} A Promise that resolves once the environment has been successfully initialized.\n */\n public async initializeEnvironment(): Promise<void> {\n // Prevent duplicate initialization\n if (this.environmentInitialized) return;\n if (this.environmentInitializingPromise) {\n await this.environmentInitializingPromise;\n return;\n }\n\n this.environmentInitializingPromise = (async () => {\n try {\n logger.info('Initializing environment configuration...');\n\n // Re-validate config to ensure it's up to date\n this.config = await validateConfig();\n\n // Initialize components that depend on validated config\n this._postValidateInit();\n\n // Set model paths based on validated config\n this.modelPath = path.join(this.modelsDir, this.config.LOCAL_SMALL_MODEL);\n this.mediumModelPath = path.join(this.modelsDir, this.config.LOCAL_LARGE_MODEL);\n this.embeddingModelPath = path.join(this.modelsDir, this.config.LOCAL_EMBEDDING_MODEL); // Set embedding path\n\n logger.info('Using small model path:', basename(this.modelPath));\n logger.info('Using medium model path:', basename(this.mediumModelPath));\n logger.info('Using embedding model path:', basename(this.embeddingModelPath));\n\n logger.info('Environment configuration validated and model paths set');\n\n this.environmentInitialized = true;\n logger.success('Environment initialization complete');\n } catch (error) {\n logger.error('Environment validation failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n this.environmentInitializingPromise = null; // Allow retry on failure\n throw error;\n }\n })();\n\n await this.environmentInitializingPromise;\n }\n\n /**\n * Downloads the model based on the modelPath provided.\n * Determines the model spec and path based on the model type.\n *\n * @param {ModelTypeName} modelType - The type of model to download\n * @param {ModelSpec} [customModelSpec] - Optional custom model spec to use instead of the default\n * @returns A Promise that resolves to a boolean indicating whether the model download was successful.\n */\n private async downloadModel(\n modelType: ModelTypeName,\n customModelSpec?: ModelSpec\n ): Promise<boolean> {\n let modelSpec: ModelSpec;\n let modelPathToDownload: string;\n\n // Ensure environment is initialized to have correct paths\n await this.initializeEnvironment();\n\n if (customModelSpec) {\n modelSpec = customModelSpec;\n // Use appropriate path based on model type, now read from instance properties\n modelPathToDownload =\n modelType === ModelType.TEXT_EMBEDDING\n ? this.embeddingModelPath\n : modelType === ModelType.TEXT_LARGE\n ? this.mediumModelPath\n : this.modelPath;\n } else if (modelType === ModelType.TEXT_EMBEDDING) {\n modelSpec = MODEL_SPECS.embedding;\n modelPathToDownload = this.embeddingModelPath; // Use configured path\n } else {\n modelSpec = modelType === ModelType.TEXT_LARGE ? MODEL_SPECS.medium : MODEL_SPECS.small;\n modelPathToDownload =\n modelType === ModelType.TEXT_LARGE ? this.mediumModelPath : this.modelPath; // Use configured path\n }\n\n try {\n // Pass the determined path to the download manager\n return await this.downloadManager.downloadModel(modelSpec, modelPathToDownload);\n } catch (error) {\n logger.error('Model download failed:', {\n error: error instanceof Error ? error.message : String(error),\n modelType,\n modelPath: modelPathToDownload,\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously checks the platform capabilities.\n *\n * @returns {Promise<void>} A promise that resolves once the platform capabilities have been checked.\n */\n public async checkPlatformCapabilities(): Promise<void> {\n try {\n const platformManager = getPlatformManager();\n await platformManager.initialize();\n const capabilities = platformManager.getCapabilities();\n\n logger.info('Platform capabilities detected:', {\n platform: capabilities.platform,\n gpu: capabilities.gpu?.type || 'none',\n recommendedModel: capabilities.recommendedModelSize,\n supportedBackends: capabilities.supportedBackends,\n });\n } catch (error) {\n logger.warn('Platform detection failed:', error);\n }\n }\n\n /**\n * Initializes the LocalAI Manager for a given model type.\n *\n * @param {ModelTypeName} modelType - The type of model to initialize (default: ModelType.TEXT_SMALL)\n * @returns {Promise<void>} A promise that resolves when initialization is complete or rejects if an error occurs\n */\n async initialize(modelType: ModelTypeName = ModelType.TEXT_SMALL): Promise<void> {\n await this.initializeEnvironment(); // Ensure environment is initialized first\n if (modelType === ModelType.TEXT_LARGE) {\n await this.lazyInitMediumModel();\n } else {\n await this.lazyInitSmallModel();\n }\n }\n\n /**\n * Asynchronously initializes the embedding model.\n *\n * @returns {Promise<void>} A promise that resolves once the initialization is complete.\n */\n public async initializeEmbedding(): Promise<void> {\n try {\n await this.initializeEnvironment(); // Ensure environment/paths are ready\n logger.info('Initializing embedding model...');\n logger.info('Models directory:', this.modelsDir);\n\n // Ensure models directory exists\n if (!fs.existsSync(this.modelsDir)) {\n logger.warn('Models directory does not exist, creating it:', this.modelsDir);\n fs.mkdirSync(this.modelsDir, { recursive: true });\n }\n\n // Download the embedding model using the common downloadModel function\n // This will now use the correct embeddingModelPath\n await this.downloadModel(ModelType.TEXT_EMBEDDING);\n\n // Initialize the llama instance if not already done\n if (!this.llama) {\n this.llama = await getLlama();\n }\n\n // Load the embedding model\n if (!this.embeddingModel) {\n logger.info('Loading embedding model:', this.embeddingModelPath); // Use the correct path\n\n this.embeddingModel = await this.llama.loadModel({\n modelPath: this.embeddingModelPath, // Use the correct path\n gpuLayers: 0, // Embedding models are typically small enough to run on CPU\n vocabOnly: false,\n });\n\n // Create context for embeddings\n this.embeddingContext = await this.embeddingModel.createEmbeddingContext({\n contextSize: this.embeddingModelConfig.contextSize,\n batchSize: 512,\n });\n\n logger.success('Embedding model initialized successfully');\n }\n } catch (error) {\n logger.error('Embedding initialization failed with details:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelsDir: this.modelsDir,\n embeddingModelPath: this.embeddingModelPath, // Log the path being used\n });\n throw error;\n }\n }\n\n /**\n * Generate embeddings using the proper LlamaContext.getEmbedding method.\n */\n async generateEmbedding(text: string): Promise<number[]> {\n try {\n // Lazy initialize embedding model\n await this.lazyInitEmbedding();\n\n if (!this.embeddingModel || !this.embeddingContext) {\n throw new Error('Failed to initialize embedding model');\n }\n\n logger.info('Generating embedding for text', { textLength: text.length });\n\n // Use the native getEmbedding method\n const embeddingResult = await this.embeddingContext.getEmbeddingFor(text);\n\n // Convert readonly array to mutable array\n const mutableEmbedding = [...embeddingResult.vector];\n\n // Normalize the embedding if needed (may already be normalized)\n const normalizedEmbedding = this.normalizeEmbedding(mutableEmbedding);\n\n logger.info('Embedding generation complete', {\n dimensions: normalizedEmbedding.length,\n });\n return normalizedEmbedding;\n } catch (error) {\n logger.error('Embedding generation failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n textLength: text?.length ?? 'text is null',\n });\n\n // Return zero vector with correct dimensions as fallback\n const zeroDimensions = this.config?.LOCAL_EMBEDDING_DIMENSIONS // Use validated config\n ? this.config.LOCAL_EMBEDDING_DIMENSIONS\n : this.embeddingModelConfig.dimensions;\n\n return new Array(zeroDimensions).fill(0);\n }\n }\n\n /**\n * Normalizes an embedding vector using L2 normalization\n *\n * @param {number[]} embedding - The embedding vector to normalize\n * @returns {number[]} - The normalized embedding vector\n */\n private normalizeEmbedding(embedding: number[]): number[] {\n // Calculate the L2 norm (Euclidean norm)\n const squareSum = embedding.reduce((sum, val) => sum + val * val, 0);\n const norm = Math.sqrt(squareSum);\n\n // Avoid division by zero\n if (norm === 0) {\n return embedding;\n }\n\n // Normalize each component\n return embedding.map((val) => val / norm);\n }\n\n /**\n * Lazy initialize the embedding model\n */\n private async lazyInitEmbedding(): Promise<void> {\n if (this.embeddingInitialized) return;\n\n if (!this.embeddingInitializingPromise) {\n this.embeddingInitializingPromise = (async () => {\n try {\n // Ensure environment is initialized first to get correct paths\n await this.initializeEnvironment();\n\n // Download model if needed (uses the correct path now)\n await this.downloadModel(ModelType.TEXT_EMBEDDING);\n\n // Initialize the llama instance if not already done\n if (!this.llama) {\n this.llama = await getLlama();\n }\n\n // Load the embedding model (uses the correct path)\n this.embeddingModel = await this.llama.loadModel({\n modelPath: this.embeddingModelPath,\n gpuLayers: 0, // Embedding models are typically small enough to run on CPU\n vocabOnly: false,\n });\n\n // Create context for embeddings\n this.embeddingContext = await this.embeddingModel.createEmbeddingContext({\n contextSize: this.embeddingModelConfig.contextSize,\n batchSize: 512,\n });\n\n this.embeddingInitialized = true;\n logger.info('Embedding model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize embedding model:', error);\n this.embeddingInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.embeddingInitializingPromise;\n }\n\n /**\n * Asynchronously generates text based on the provided parameters.\n * Now uses lazy initialization for models\n */\n async generateText(params: GenerateTextParams): Promise<string> {\n try {\n await this.initializeEnvironment(); // Ensure environment is initialized\n logger.info('Generating text with model:', params.modelType);\n // Lazy initialize the appropriate model\n if (params.modelType === ModelType.TEXT_LARGE) {\n await this.lazyInitMediumModel();\n\n if (!this.mediumModel) {\n throw new Error('Medium model initialization failed');\n }\n\n this.activeModelConfig = MODEL_SPECS.medium;\n const mediumModel = this.mediumModel;\n\n // Create fresh context\n this.ctx = await mediumModel.createContext({\n contextSize: MODEL_SPECS.medium.contextSize,\n });\n } else {\n await this.lazyInitSmallModel();\n\n if (!this.smallModel) {\n throw new Error('Small model initialization failed');\n }\n\n this.activeModelConfig = MODEL_SPECS.small;\n const smallModel = this.smallModel;\n\n // Create fresh context\n this.ctx = await smallModel.createContext({\n contextSize: MODEL_SPECS.small.contextSize,\n });\n }\n\n if (!this.ctx) {\n throw new Error('Failed to create prompt');\n }\n\n // QUICK TEST FIX: Always get fresh sequence\n this.sequence = this.ctx.getSequence();\n\n // QUICK TEST FIX: Create new session each time without maintaining state\n // Only use valid options for LlamaChatSession\n this.chatSession = new LlamaChatSession({\n contextSequence: this.sequence,\n });\n\n if (!this.chatSession) {\n throw new Error('Failed to create chat session');\n }\n logger.info('Created new chat session for model:', params.modelType);\n // Log incoming prompt for debugging\n logger.info('Incoming prompt structure:', {\n contextLength: params.prompt.length,\n hasAction: params.prompt.includes('action'),\n runtime: !!params.runtime,\n stopSequences: params.stopSequences,\n });\n\n const tokens = await this.tokenizerManager.encode(params.prompt, this.activeModelConfig);\n logger.info('Input tokens:', { count: tokens.length });\n\n // QUICK TEST FIX: Add system message to reset prompt\n const systemMessage = 'You are a helpful AI assistant. Respond to the current request only.';\n await this.chatSession.prompt(systemMessage, {\n maxTokens: 1, // Minimal tokens for system message\n temperature: 0.0,\n });\n\n let response = await this.chatSession.prompt(params.prompt, {\n maxTokens: 8192,\n temperature: 0.7,\n topP: 0.9,\n repeatPenalty: {\n punishTokensFilter: () =>\n this.smallModel ? this.smallModel.tokenize(wordsToPunish.join(' ')) : [],\n penalty: 1.2,\n frequencyPenalty: 0.7,\n presencePenalty: 0.7,\n },\n });\n\n // Log raw response for debugging\n logger.info('Raw response structure:', {\n responseLength: response.length,\n hasAction: response.includes('action'),\n hasThinkTag: response.includes('<think>'),\n });\n\n // Clean think tags if present\n if (response.includes('<think>')) {\n logger.info('Cleaning think tags from response');\n response = response.replace(/<think>[\\s\\S]*?<\\/think>\\n?/g, '');\n logger.info('Think tags removed from response');\n }\n\n // Return the raw response and let the framework handle JSON parsing and action validation\n return response;\n } catch (error) {\n logger.error('Text generation failed:', error);\n throw error;\n }\n }\n\n /**\n * Describe image with lazy vision model initialization\n */\n public async describeImage(\n imageData: Buffer,\n mimeType: string\n ): Promise<{ title: string; description: string }> {\n try {\n // Lazy initialize vision model\n await this.lazyInitVision();\n\n // Convert buffer to data URL\n const base64 = imageData.toString('base64');\n const dataUrl = `data:${mimeType};base64,${base64}`;\n return await this.visionManager.processImage(dataUrl);\n } catch (error) {\n logger.error('Image description failed:', error);\n throw error;\n }\n }\n\n /**\n * Transcribe audio with lazy transcription model initialization\n */\n public async transcribeAudio(audioBuffer: Buffer): Promise<string> {\n try {\n // Lazy initialize transcription model\n await this.lazyInitTranscription();\n\n const result = await this.transcribeManager.transcribe(audioBuffer);\n return result.text;\n } catch (error) {\n logger.error('Audio transcription failed:', {\n error: error instanceof Error ? error.message : String(error),\n bufferSize: audioBuffer.length,\n });\n throw error;\n }\n }\n\n /**\n * Generate speech with lazy TTS model initialization\n */\n public async generateSpeech(text: string): Promise<Readable> {\n try {\n // Lazy initialize TTS model\n await this.lazyInitTTS();\n\n return await this.ttsManager.generateSpeech(text);\n } catch (error) {\n logger.error('Speech generation failed:', {\n error: error instanceof Error ? error.message : String(error),\n textLength: text.length,\n });\n throw error;\n }\n }\n\n /**\n * Returns the TokenizerManager associated with this object.\n *\n * @returns {TokenizerManager} The TokenizerManager object.\n */\n public getTokenizerManager(): TokenizerManager {\n return this.tokenizerManager;\n }\n\n /**\n * Returns the active model configuration.\n * @returns {ModelSpec} The active model configuration.\n */\n public getActiveModelConfig(): ModelSpec {\n return this.activeModelConfig;\n }\n\n /**\n * Lazy initialize the small text model\n */\n private async lazyInitSmallModel(): Promise<void> {\n if (this.smallModelInitialized) return;\n\n if (!this.smallModelInitializingPromise) {\n this.smallModelInitializingPromise = (async () => {\n await this.initializeEnvironment(); // Ensure environment is initialized first\n await this.checkPlatformCapabilities();\n\n // Download model if needed\n // Pass the correct model path determined during environment init\n await this.downloadModel(ModelType.TEXT_SMALL);\n\n // Initialize Llama and small model\n try {\n // Use getLlama helper instead of directly creating\n this.llama = await getLlama();\n\n const smallModel = await this.llama.loadModel({\n gpuLayers: 43,\n modelPath: this.modelPath, // Use the potentially overridden path\n vocabOnly: false,\n });\n\n this.smallModel = smallModel;\n\n const ctx = await smallModel.createContext({\n contextSize: MODEL_SPECS.small.contextSize,\n });\n\n this.ctx = ctx;\n this.sequence = undefined; // Reset sequence to create a new one\n this.smallModelInitialized = true;\n logger.info('Small model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize small model:', error);\n this.smallModelInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.smallModelInitializingPromise;\n }\n\n /**\n * Lazy initialize the medium text model\n */\n private async lazyInitMediumModel(): Promise<void> {\n if (this.mediumModelInitialized) return;\n\n if (!this.mediumModelInitializingPromise) {\n this.mediumModelInitializingPromise = (async () => {\n await this.initializeEnvironment(); // Ensure environment is initialized first\n // Make sure llama is initialized first (implicitly done by small model init if needed)\n if (!this.llama) {\n // Attempt to initialize small model first to get llama instance\n // This might download the small model even if only medium is requested,\n // but ensures llama is ready.\n await this.lazyInitSmallModel();\n }\n\n // Download model if needed\n // Pass the correct model path determined during environment init\n await this.downloadModel(ModelType.TEXT_LARGE);\n\n // Initialize medium model\n try {\n const mediumModel = await this.llama!.loadModel({\n gpuLayers: 43,\n modelPath: this.mediumModelPath, // Use the potentially overridden path\n vocabOnly: false,\n });\n\n this.mediumModel = mediumModel;\n this.mediumModelInitialized = true;\n logger.info('Medium model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize medium model:', error);\n this.mediumModelInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.mediumModelInitializingPromise;\n }\n\n /**\n * Lazy initialize the vision model\n */\n private async lazyInitVision(): Promise<void> {\n if (this.visionInitialized) return;\n\n if (!this.visionInitializingPromise) {\n this.visionInitializingPromise = (async () => {\n try {\n // Initialize vision model directly\n // Use existing initialization code from the file\n // ...\n this.visionInitialized = true;\n logger.info('Vision model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize vision model:', error);\n this.visionInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.visionInitializingPromise;\n }\n\n /**\n * Lazy initialize the transcription model\n */\n private async lazyInitTranscription(): Promise<void> {\n if (this.transcriptionInitialized) return;\n\n if (!this.transcriptionInitializingPromise) {\n this.transcriptionInitializingPromise = (async () => {\n try {\n // Ensure environment is initialized first\n await this.initializeEnvironment();\n\n // Initialize TranscribeManager if not already done\n if (!this.transcribeManager) {\n this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);\n }\n\n // Ensure FFmpeg is available\n const ffmpegReady = await this.transcribeManager.ensureFFmpeg();\n if (!ffmpegReady) {\n // FFmpeg is not available, log instructions and throw\n // The TranscribeManager's ensureFFmpeg or initializeFFmpeg would have already logged instructions.\n logger.error(\n 'FFmpeg is not available or not configured correctly. Cannot proceed with transcription.'\n );\n // No need to call logFFmpegInstallInstructions here as ensureFFmpeg/initializeFFmpeg already does.\n throw new Error(\n 'FFmpeg is required for transcription but is not available. Please see server logs for installation instructions.'\n );\n }\n\n // Proceed with transcription model initialization if FFmpeg is ready\n // (Assuming TranscribeManager handles its own specific model init if any,\n // or that nodewhisper handles it internally)\n this.transcriptionInitialized = true;\n logger.info('Transcription prerequisites (FFmpeg) checked and ready.');\n logger.info('Transcription model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize transcription model:', error);\n this.transcriptionInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.transcriptionInitializingPromise;\n }\n\n /**\n * Lazy initialize the TTS model\n */\n private async lazyInitTTS(): Promise<void> {\n if (this.ttsInitialized) return;\n\n if (!this.ttsInitializingPromise) {\n this.ttsInitializingPromise = (async () => {\n try {\n // Initialize TTS model directly\n // Use existing initialization code from the file\n // Get the TTSManager instance (ensure environment is initialized for cacheDir)\n await this.initializeEnvironment();\n this.ttsManager = TTSManager.getInstance(this.cacheDir);\n // Note: The internal pipeline initialization within TTSManager happens\n // when generateSpeech calls its own initialize method.\n this.ttsInitialized = true;\n logger.info('TTS model initialized successfully');\n } catch (error) {\n logger.error('Failed to lazy initialize TTS components:', error);\n this.ttsInitializingPromise = null; // Allow retry\n throw error;\n }\n })();\n }\n\n await this.ttsInitializingPromise;\n }\n}\n\n// Create manager instance\nconst localAIManager = LocalAIManager.getInstance();\n\n/**\n * Plugin that provides functionality for local AI using LLaMA models.\n * @type {Plugin}\n */\nexport const localAiPlugin: Plugin = {\n name: 'local-ai',\n description: 'Local AI plugin using LLaMA models',\n\n async init(_config: any, runtime: IAgentRuntime) {\n logger.info('🚀 Initializing Local AI plugin...');\n \n try {\n // Initialize environment and validate configuration\n await localAIManager.initializeEnvironment();\n const config = validateConfig();\n \n // Check for critical configuration\n if (!config.LOCAL_SMALL_MODEL || !config.LOCAL_LARGE_MODEL || !config.LOCAL_EMBEDDING_MODEL) {\n logger.warn('⚠️ Local AI plugin: Model configuration is incomplete');\n logger.warn('Please ensure the following environment variables are set:');\n logger.warn('- LOCAL_SMALL_MODEL: Path to small language model file');\n logger.warn('- LOCAL_LARGE_MODEL: Path to large language model file');\n logger.warn('- LOCAL_EMBEDDING_MODEL: Path to embedding model file');\n logger.warn('Example: LOCAL_SMALL_MODEL=llama-3.2-1b-instruct-q8_0.gguf');\n }\n \n // Check if models directory is accessible\n const modelsDir = config.MODELS_DIR || path.join(os.homedir(), '.eliza', 'models');\n if (!fs.existsSync(modelsDir)) {\n logger.warn(`⚠️ Models directory does not exist: ${modelsDir}`);\n logger.warn('The directory will be created, but you need to download model files');\n logger.warn('Visit https://huggingface.co/models to download compatible GGUF models');\n }\n \n // Perform a basic initialization test\n logger.info('🔍 Testing Local AI initialization...');\n \n try {\n // Check platform capabilities\n await localAIManager.checkPlatformCapabilities();\n \n // Test if we can get the llama instance\n const llamaInstance = await getLlama();\n if (llamaInstance) {\n logger.success('✅ Local AI: llama.cpp library loaded successfully');\n } else {\n throw new Error('Failed to load llama.cpp library');\n }\n \n // Check if at least one model file exists\n const smallModelPath = path.join(modelsDir, config.LOCAL_SMALL_MODEL);\n const largeModelPath = path.join(modelsDir, config.LOCAL_LARGE_MODEL);\n const embeddingModelPath = path.join(modelsDir, config.LOCAL_EMBEDDING_MODEL);\n \n const modelsExist = {\n small: fs.existsSync(smallModelPath),\n large: fs.existsSync(largeModelPath),\n embedding: fs.existsSync(embeddingModelPath)\n };\n \n if (!modelsExist.small && !modelsExist.large && !modelsExist.embedding) {\n logger.warn('⚠️ No model files found in models directory');\n logger.warn('Models will be downloaded on first use, which may take time');\n logger.warn('To pre-download models, run the plugin and it will fetch them automatically');\n } else {\n logger.info('📦 Found model files:', {\n small: modelsExist.small ? '✓' : '✗',\n large: modelsExist.large ? '✓' : '✗',\n embedding: modelsExist.embedding ? '✓' : '✗'\n });\n }\n \n logger.success('✅ Local AI plugin initialized successfully');\n logger.info('💡 Models will be loaded on-demand when first used');\n \n } catch (testError) {\n logger.error('❌ Local AI initialization test failed:', testError);\n logger.warn('The plugin may not function correctly');\n logger.warn('Please check:');\n logger.warn('1. Your system has sufficient memory (8GB+ recommended)');\n logger.warn('2. C++ build tools are installed (for node-llama-cpp)');\n logger.warn('3. Your CPU supports the required instruction sets');\n // Don't throw here - allow the plugin to load even if the test fails\n }\n \n } catch (error) {\n logger.error('❌ Failed to initialize Local AI plugin:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n \n // Provide helpful guidance based on common errors\n if (error instanceof Error) {\n if (error.message.includes('Cannot find module')) {\n logger.error('📚 Missing dependencies detected');\n logger.error('Please run: npm install or bun install');\n } else if (error.message.includes('node-llama-cpp')) {\n logger.error('🔧 node-llama-cpp build issue detected');\n logger.error('Please ensure C++ build tools are installed:');\n logger.error('- Windows: Install Visual Studio Build Tools');\n logger.error('- macOS: Install Xcode Command Line Tools');\n logger.error('- Linux: Install build-essential package');\n }\n }\n \n // Don't throw - allow the system to continue without this plugin\n logger.warn('⚠️ Local AI plugin will not be available');\n }\n },\n models: {\n [ModelType.TEXT_SMALL]: async (\n runtime: IAgentRuntime,\n { prompt, stopSequences = [] }: GenerateTextParams\n ) => {\n try {\n // Ensure environment is initialized before generating text (now public)\n await localAIManager.initializeEnvironment();\n return await localAIManager.generateText({\n prompt,\n stopSequences,\n runtime,\n modelType: ModelType.TEXT_SMALL,\n });\n } catch (error) {\n logger.error('Error in TEXT_SMALL handler:', error);\n throw error;\n }\n },\n\n [ModelType.TEXT_LARGE]: async (\n runtime: IAgentRuntime,\n { prompt, stopSequences = [] }: GenerateTextParams\n ) => {\n try {\n // Ensure environment is initialized before generating text (now public)\n await localAIManager.initializeEnvironment();\n return await localAIManager.generateText({\n prompt,\n stopSequences,\n runtime,\n modelType: ModelType.TEXT_LARGE,\n });\n } catch (error) {\n logger.error('Error in TEXT_LARGE handler:', error);\n throw error;\n }\n },\n\n [ModelType.TEXT_EMBEDDING]: async (_runtime: IAgentRuntime, params: TextEmbeddingParams) => {\n const text = params?.text;\n try {\n // Handle null/undefined/empty text\n if (!text) {\n logger.debug('Null or empty text input for embedding, returning zero vector');\n return new Array(384).fill(0);\n }\n\n // Pass the raw text directly to the framework without any manipulation\n return await localAIManager.generateEmbedding(text);\n } catch (error) {\n logger.error('Error in TEXT_EMBEDDING handler:', {\n error: error instanceof Error ? error.message : String(error),\n fullText: text,\n textType: typeof text,\n textStructure: text !== null ? JSON.stringify(text, null, 2) : 'null',\n });\n return new Array(384).fill(0);\n }\n },\n\n [ModelType.OBJECT_SMALL]: async (runtime: IAgentRuntime, params: ObjectGenerationParams) => {\n try {\n // Ensure environment is initialized (now public)\n await localAIManager.initializeEnvironment();\n logger.info('OBJECT_SMALL handler - Processing request:', {\n prompt: params.prompt,\n hasSchema: !!params.schema,\n temperature: params.temperature,\n });\n\n // Enhance the prompt to request JSON output\n let jsonPrompt = params.prompt;\n if (!jsonPrompt.includes('```json') && !jsonPrompt.includes('respond with valid JSON')) {\n jsonPrompt +=\n '\\nPlease respond with valid JSON only, without any explanations, markdown formatting, or additional text.';\n }\n\n // Directly generate text using the local small model\n const textResponse = await localAIManager.generateText({\n prompt: jsonPrompt,\n stopSequences: params.stopSequences,\n runtime,\n modelType: ModelType.TEXT_SMALL,\n });\n\n // Extract and parse JSON from the text response\n try {\n // Function to extract JSON content from text\n const extractJSON = (text: string): string => {\n // Try to find content between JSON codeblocks or markdown blocks\n const jsonBlockRegex = /```(?:json)?\\s*([\\s\\S]*?)\\s*```/;\n const match = text.match(jsonBlockRegex);\n\n if (match && match[1]) {\n return match[1].trim();\n }\n\n // If no code blocks, try to find JSON-like content\n // This regex looks for content that starts with { and ends with }\n const jsonContentRegex = /\\s*(\\{[\\s\\S]*\\})\\s*$/;\n const contentMatch = text.match(jsonContentRegex);\n\n if (contentMatch && contentMatch[1]) {\n return contentMatch[1].trim();\n }\n\n // If no JSON-like content found, return the original text\n return text.trim();\n };\n\n const extractedJsonText = extractJSON(textResponse);\n logger.debug('Extracted JSON text:', extractedJsonText);\n\n let jsonObject;\n try {\n jsonObject = JSON.parse(extractedJsonText);\n } catch (parseError) {\n // Try fixing common JSON issues\n logger.debug('Initial JSON parse failed, attempting to fix common issues');\n\n // Replace any unescaped newlines in string values\n const fixedJson = extractedJsonText\n .replace(/:\\s*\"([^\"]*)(?:\\n)([^\"]*)\"/g, ': \"$1\\\\n$2\"')\n // Remove any non-JSON text that might have gotten mixed into string values\n .replace(/\"([^\"]*?)[^a-zA-Z0-9\\s\\.,;:\\-_\\(\\)\"'\\[\\]{}]([^\"]*?)\"/g, '\"$1$2\"')\n // Fix missing quotes around property names\n .replace(/(\\s*)(\\w+)(\\s*):/g, '$1\"$2\"$3:')\n // Fix trailing commas in arrays and objects\n .replace(/,(\\s*[\\]}])/g, '$1');\n\n try {\n jsonObject = JSON.parse(fixedJson);\n } catch (finalError) {\n logger.error('Failed to parse JSON after fixing:', finalError);\n throw new Error('Invalid JSON returned from model');\n }\n }\n\n // Validate against schema if provided\n if (params.schema) {\n try {\n // Simplistic schema validation - check if all required properties exist\n for (const key of Object.keys(params.schema)) {\n if (!(key in jsonObject)) {\n jsonObject[key] = null; // Add missing properties with null value\n }\n }\n } catch (schemaError) {\n logger.error('Schema validation failed:', schemaError);\n }\n }\n\n return jsonObject;\n } catch (parseError) {\n logger.error('Failed to parse JSON:', parseError);\n logger.error('Raw response:', textResponse);\n throw new Error('Invalid JSON returned from model');\n }\n } catch (error) {\n logger.error('Error in OBJECT_SMALL handler:', error);\n throw error;\n }\n },\n\n [ModelType.OBJECT_LARGE]: async (runtime: IAgentRuntime, params: ObjectGenerationParams) => {\n try {\n // Ensure environment is initialized (now public)\n await localAIManager.initializeEnvironment();\n logger.info('OBJECT_LARGE handler - Processing request:', {\n prompt: params.prompt,\n hasSchema: !!params.schema,\n temperature: params.temperature,\n });\n\n // Enhance the prompt to request JSON output\n let jsonPrompt = params.prompt;\n if (!jsonPrompt.includes('```json') && !jsonPrompt.includes('respond with valid JSON')) {\n jsonPrompt +=\n '\\nPlease respond with valid JSON only, without any explanations, markdown formatting, or additional text.';\n }\n\n // Directly generate text using the local large model\n const textResponse = await localAIManager.generateText({\n prompt: jsonPrompt,\n stopSequences: params.stopSequences,\n runtime,\n modelType: ModelType.TEXT_LARGE,\n });\n\n // Extract and parse JSON from the text response\n try {\n // Function to extract JSON content from text\n const extractJSON = (text: string): string => {\n // Try to find content between JSON codeblocks or markdown blocks\n const jsonBlockRegex = /```(?:json)?\\s*([\\s\\S]*?)\\s*```/;\n const match = text.match(jsonBlockRegex);\n\n if (match && match[1]) {\n return match[1].trim();\n }\n\n // If no code blocks, try to find JSON-like content\n // This regex looks for content that starts with { and ends with }\n const jsonContentRegex = /\\s*(\\{[\\s\\S]*\\})\\s*$/;\n const contentMatch = text.match(jsonContentRegex);\n\n if (contentMatch && contentMatch[1]) {\n return contentMatch[1].trim();\n }\n\n // If no JSON-like content found, return the original text\n return text.trim();\n };\n\n // Clean up the extracted JSON to handle common formatting issues\n const cleanupJSON = (jsonText: string): string => {\n // Remove common logging/debugging patterns that might get mixed into the JSON\n return (\n jsonText\n // Remove any lines that look like log statements\n .replace(/\\[DEBUG\\].*?(\\n|$)/g, '\\n')\n .replace(/\\[LOG\\].*?(\\n|$)/g, '\\n')\n .replace(/console\\.log.*?(\\n|$)/g, '\\n')\n );\n };\n\n const extractedJsonText = extractJSON(textResponse);\n const cleanedJsonText = cleanupJSON(extractedJsonText);\n logger.debug('Extracted JSON text:', cleanedJsonText);\n\n let jsonObject;\n try {\n jsonObject = JSON.parse(cleanedJsonText);\n } catch (parseError) {\n // Try fixing common JSON issues\n logger.debug('Initial JSON parse failed, attempting to fix common issues');\n\n // Replace any unescaped newlines in string values\n const fixedJson = cleanedJsonText\n .replace(/:\\s*\"([^\"]*)(?:\\n)([^\"]*)\"/g, ': \"$1\\\\n$2\"')\n // Remove any non-JSON text that might have gotten mixed into string values\n .replace(/\"([^\"]*?)[^a-zA-Z0-9\\s\\.,;:\\-_\\(\\)\"'\\[\\]{}]([^\"]*?)\"/g, '\"$1$2\"')\n // Fix missing quotes around property names\n .replace(/(\\s*)(\\w+)(\\s*):/g, '$1\"$2\"$3:')\n // Fix trailing commas in arrays and objects\n .replace(/,(\\s*[\\]}])/g, '$1');\n\n try {\n jsonObject = JSON.parse(fixedJson);\n } catch (finalError) {\n logger.error('Failed to parse JSON after fixing:', finalError);\n throw new Error('Invalid JSON returned from model');\n }\n }\n\n // Validate against schema if provided\n if (params.schema) {\n try {\n // Simplistic schema validation - check if all required properties exist\n for (const key of Object.keys(params.schema)) {\n if (!(key in jsonObject)) {\n jsonObject[key] = null; // Add missing properties with null value\n }\n }\n } catch (schemaError) {\n logger.error('Schema validation failed:', schemaError);\n }\n }\n\n return jsonObject;\n } catch (parseError) {\n logger.error('Failed to parse JSON:', parseError);\n logger.error('Raw response:', textResponse);\n throw new Error('Invalid JSON returned from model');\n }\n } catch (error) {\n logger.error('Error in OBJECT_LARGE handler:', error);\n throw error;\n }\n },\n\n [ModelType.TEXT_TOKENIZER_ENCODE]: async (\n _runtime: IAgentRuntime,\n { text }: { text: string }\n ) => {\n try {\n const manager = localAIManager.getTokenizerManager();\n const config = localAIManager.getActiveModelConfig();\n return await manager.encode(text, config);\n } catch (error) {\n logger.error('Error in TEXT_TOKENIZER_ENCODE handler:', error);\n throw error;\n }\n },\n\n [ModelType.TEXT_TOKENIZER_DECODE]: async (\n _runtime: IAgentRuntime,\n { tokens }: { tokens: number[] }\n ) => {\n try {\n const manager = localAIManager.getTokenizerManager();\n const config = localAIManager.getActiveModelConfig();\n return await manager.decode(tokens, config);\n } catch (error) {\n logger.error('Error in TEXT_TOKENIZER_DECODE handler:', error);\n throw error;\n }\n },\n\n [ModelType.IMAGE_DESCRIPTION]: async (_runtime: IAgentRuntime, imageUrl: string) => {\n try {\n logger.info('Processing image from URL:', imageUrl);\n\n // Fetch the image from URL\n const response = await fetch(imageUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch image: ${response.statusText}`);\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const mimeType = response.headers.get('content-type') || 'image/jpeg';\n\n return await localAIManager.describeImage(buffer, mimeType);\n } catch (error) {\n logger.error('Error in IMAGE_DESCRIPTION handler:', {\n error: error instanceof Error ? error.message : String(error),\n imageUrl,\n });\n throw error;\n }\n },\n\n [ModelType.TRANSCRIPTION]: async (_runtime: IAgentRuntime, audioBuffer: Buffer) => {\n try {\n logger.info('Processing audio transcription:', {\n bufferSize: audioBuffer.length,\n });\n\n return await localAIManager.transcribeAudio(audioBuffer);\n } catch (error) {\n logger.error('Error in TRANSCRIPTION handler:', {\n error: error instanceof Error ? error.message : String(error),\n bufferSize: audioBuffer.length,\n });\n throw error;\n }\n },\n\n [ModelType.TEXT_TO_SPEECH]: async (_runtime: IAgentRuntime, text: string) => {\n try {\n return await localAIManager.generateSpeech(text);\n } catch (error) {\n logger.error('Error in TEXT_TO_SPEECH handler:', {\n error: error instanceof Error ? error.message : String(error),\n textLength: text.length,\n });\n throw error;\n }\n },\n },\n tests: [\n {\n name: 'local_ai_plugin_tests',\n tests: [\n {\n name: 'local_ai_test_initialization',\n fn: async (runtime) => {\n try {\n logger.info('Starting initialization test');\n\n // Test TEXT_SMALL model initialization\n const result = await runtime.useModel(ModelType.TEXT_SMALL, {\n prompt:\n \"Debug Mode: Test initialization. Respond with 'Initialization successful' if you can read this.\",\n stopSequences: [],\n });\n\n logger.info('Model response:', result);\n\n if (!result || typeof result !== 'string') {\n throw new Error('Invalid response from model');\n }\n\n if (!result.includes('successful')) {\n throw new Error('Model response does not indicate success');\n }\n\n logger.success('Initialization test completed successfully');\n } catch (error) {\n logger.error('Initialization test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_text_large',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_LARGE model test');\n\n const result = await runtime.useModel(ModelType.TEXT_LARGE, {\n prompt:\n 'Debug Mode: Generate a one-sentence response about artificial intelligence.',\n stopSequences: [],\n });\n\n logger.info('Large model response:', result);\n\n if (!result || typeof result !== 'string') {\n throw new Error('Invalid response from large model');\n }\n\n if (result.length < 10) {\n throw new Error('Response too short, possible model failure');\n }\n\n logger.success('TEXT_LARGE test completed successfully');\n } catch (error) {\n logger.error('TEXT_LARGE test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_text_embedding',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_EMBEDDING test');\n\n // Test with normal text\n const embedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, {\n text: 'This is a test of the text embedding model.',\n });\n\n logger.info('Embedding generated with dimensions:', embedding.length);\n\n if (!Array.isArray(embedding)) {\n throw new Error('Embedding is not an array');\n }\n\n if (embedding.length === 0) {\n throw new Error('Embedding array is empty');\n }\n\n if (embedding.some((val) => typeof val !== 'number')) {\n throw new Error('Embedding contains non-numeric values');\n }\n\n // Test with null input (should return zero vector)\n const nullEmbedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, null);\n if (!Array.isArray(nullEmbedding) || nullEmbedding.some((val) => val !== 0)) {\n throw new Error('Null input did not return zero vector');\n }\n\n logger.success('TEXT_EMBEDDING test completed successfully');\n } catch (error) {\n logger.error('TEXT_EMBEDDING test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_tokenizer_encode',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_TOKENIZER_ENCODE test');\n const text = 'Hello tokenizer test!';\n\n const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, { text });\n logger.info('Encoded tokens:', { count: tokens.length });\n\n if (!Array.isArray(tokens)) {\n throw new Error('Tokens output is not an array');\n }\n\n if (tokens.length === 0) {\n throw new Error('No tokens generated');\n }\n\n if (tokens.some((token) => !Number.isInteger(token))) {\n throw new Error('Tokens contain non-integer values');\n }\n\n logger.success('TEXT_TOKENIZER_ENCODE test completed successfully');\n } catch (error) {\n logger.error('TEXT_TOKENIZER_ENCODE test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_tokenizer_decode',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_TOKENIZER_DECODE test');\n\n // First encode some text\n const originalText = 'Hello tokenizer test!';\n const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, {\n text: originalText,\n });\n\n // Then decode it back\n const decodedText = await runtime.useModel(ModelType.TEXT_TOKENIZER_DECODE, {\n tokens,\n });\n logger.info('Round trip tokenization:', {\n original: originalText,\n decoded: decodedText,\n });\n\n if (typeof decodedText !== 'string') {\n throw new Error('Decoded output is not a string');\n }\n\n logger.success('TEXT_TOKENIZER_DECODE test completed successfully');\n } catch (error) {\n logger.error('TEXT_TOKENIZER_DECODE test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_image_description',\n fn: async (runtime) => {\n try {\n logger.info('Starting IMAGE_DESCRIPTION test');\n\n // Use a more stable test image URL\n const imageUrl =\n 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/320px-Cat03.jpg';\n const result = await runtime.useModel(ModelType.IMAGE_DESCRIPTION, imageUrl);\n\n logger.info('Image description result:', result);\n\n if (!result || typeof result !== 'object') {\n throw new Error('Invalid response format');\n }\n\n if (!result.title || !result.description) {\n throw new Error('Missing title or description in response');\n }\n\n if (typeof result.title !== 'string' || typeof result.description !== 'string') {\n throw new Error('Title or description is not a string');\n }\n\n logger.success('IMAGE_DESCRIPTION test completed successfully');\n } catch (error) {\n logger.error('IMAGE_DESCRIPTION test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_transcription',\n fn: async (runtime) => {\n try {\n logger.info('Starting TRANSCRIPTION test');\n\n // Create a proper WAV file header and minimal audio data\n // WAV file format: RIFF header + fmt chunk + data chunk\n const channels = 1;\n const sampleRate = 16000;\n const bitsPerSample = 16;\n const duration = 0.5; // 500ms for better transcription\n const numSamples = Math.floor(sampleRate * duration);\n const dataSize = numSamples * channels * (bitsPerSample / 8);\n\n // Create the WAV header\n const buffer = Buffer.alloc(44 + dataSize);\n\n // RIFF header\n buffer.write('RIFF', 0);\n buffer.writeUInt32LE(36 + dataSize, 4); // File size - 8\n buffer.write('WAVE', 8);\n\n // fmt chunk\n buffer.write('fmt ', 12);\n buffer.writeUInt32LE(16, 16); // fmt chunk size\n buffer.writeUInt16LE(1, 20); // Audio format (1 = PCM)\n buffer.writeUInt16LE(channels, 22); // Number of channels\n buffer.writeUInt32LE(sampleRate, 24); // Sample rate\n buffer.writeUInt32LE(sampleRate * channels * (bitsPerSample / 8), 28); // Byte rate\n buffer.writeUInt16LE(channels * (bitsPerSample / 8), 32); // Block align\n buffer.writeUInt16LE(bitsPerSample, 34); // Bits per sample\n\n // data chunk\n buffer.write('data', 36);\n buffer.writeUInt32LE(dataSize, 40); // Data size\n\n // Generate a simple sine wave tone (440Hz) instead of silence\n const frequency = 440; // A4 note\n for (let i = 0; i < numSamples; i++) {\n const sample = Math.sin((2 * Math.PI * frequency * i) / sampleRate) * 0.1 * 32767;\n buffer.writeInt16LE(Math.floor(sample), 44 + i * 2);\n }\n\n const transcription = await runtime.useModel(ModelType.TRANSCRIPTION, buffer);\n logger.info('Transcription result:', transcription);\n\n if (typeof transcription !== 'string') {\n throw new Error('Transcription result is not a string');\n }\n\n // Accept empty string as valid result (for non-speech audio)\n logger.info('Transcription completed (may be empty for non-speech audio)');\n\n logger.success('TRANSCRIPTION test completed successfully');\n } catch (error) {\n logger.error('TRANSCRIPTION test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_text_to_speech',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_TO_SPEECH test');\n\n const testText = 'This is a test of the text to speech system.';\n const audioStream = await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText);\n\n if (!(audioStream instanceof Readable)) {\n throw new Error('TTS output is not a readable stream');\n }\n\n // Test stream readability\n let dataReceived = false;\n audioStream.on('data', () => {\n dataReceived = true;\n });\n\n await new Promise((resolve, reject) => {\n audioStream.on('end', () => {\n if (!dataReceived) {\n reject(new Error('No audio data received from stream'));\n } else {\n resolve(true);\n }\n });\n audioStream.on('error', reject);\n });\n\n logger.success('TEXT_TO_SPEECH test completed successfully');\n } catch (error) {\n logger.error('TEXT_TO_SPEECH test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\n\nexport default localAiPlugin;\n","import { logger } from '@elizaos/core';\nimport { z } from 'zod';\n\n// Default model filenames\nconst DEFAULT_SMALL_MODEL = 'DeepHermes-3-Llama-3-3B-Preview-q4.gguf';\nconst DEFAULT_LARGE_MODEL = 'DeepHermes-3-Llama-3-8B-q4.gguf';\nconst DEFAULT_EMBEDDING_MODEL = 'bge-small-en-v1.5.Q4_K_M.gguf';\n\n// Configuration schema focused only on local AI settings\n/**\n * Configuration schema for local AI settings.\n * Allows overriding default model filenames via environment variables.\n */\nexport const configSchema = z.object({\n LOCAL_SMALL_MODEL: z.string().optional().default(DEFAULT_SMALL_MODEL),\n LOCAL_LARGE_MODEL: z.string().optional().default(DEFAULT_LARGE_MODEL),\n LOCAL_EMBEDDING_MODEL: z.string().optional().default(DEFAULT_EMBEDDING_MODEL),\n MODELS_DIR: z.string().optional(), // Path for the models directory\n CACHE_DIR: z.string().optional(), // Path for the cache directory\n LOCAL_EMBEDDING_DIMENSIONS: z\n .string()\n .optional()\n .default('384') // Default to 384 if not provided\n .transform((val) => parseInt(val, 10)), // Transform to number\n});\n\n/**\n * Export type representing the inferred type of the 'configSchema'.\n */\nexport type Config = z.infer<typeof configSchema>;\n\n/**\n * Validates and parses the configuration, reading from environment variables.\n * Since only local AI is supported, this primarily ensures the structure\n * and applies defaults or environment variable overrides for model filenames.\n * @returns {Config} The validated configuration object.\n */\nexport function validateConfig(): Config {\n try {\n // Prepare the config for parsing, reading from process.env\n const configToParse = {\n // Read model filenames from environment variables or use undefined (so zod defaults apply)\n LOCAL_SMALL_MODEL: process.env.LOCAL_SMALL_MODEL,\n LOCAL_LARGE_MODEL: process.env.LOCAL_LARGE_MODEL,\n LOCAL_EMBEDDING_MODEL: process.env.LOCAL_EMBEDDING_MODEL,\n MODELS_DIR: process.env.MODELS_DIR, // Read models directory path from env\n CACHE_DIR: process.env.CACHE_DIR, // Read cache directory path from env\n LOCAL_EMBEDDING_DIMENSIONS: process.env.LOCAL_EMBEDDING_DIMENSIONS, // Read embedding dimensions\n };\n\n logger.debug('Validating configuration for local AI plugin from env:', {\n LOCAL_SMALL_MODEL: configToParse.LOCAL_SMALL_MODEL,\n LOCAL_LARGE_MODEL: configToParse.LOCAL_LARGE_MODEL,\n LOCAL_EMBEDDING_MODEL: configToParse.LOCAL_EMBEDDING_MODEL,\n MODELS_DIR: configToParse.MODELS_DIR,\n CACHE_DIR: configToParse.CACHE_DIR,\n LOCAL_EMBEDDING_DIMENSIONS: configToParse.LOCAL_EMBEDDING_DIMENSIONS,\n });\n\n const validatedConfig = configSchema.parse(configToParse);\n\n logger.info('Using local AI configuration:', validatedConfig);\n\n return validatedConfig;\n } catch (error) {\n if (error instanceof z.ZodError) {\n const errorMessages = error.errors\n .map((err) => `${err.path.join('.')}: ${err.message}`)\n .join('\\n');\n logger.error('Zod validation failed:', errorMessages);\n throw new Error(`Configuration validation failed:\\n${errorMessages}`);\n }\n logger.error('Configuration validation failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n}\n","// Model specifications and configurations\n/**\n * Interface representing a Tokenizer configuration.\n * @property {string} name - The name of the tokenizer.\n * @property {string} type - The type of the tokenizer.\n */\nexport interface TokenizerConfig {\n name: string;\n type: string;\n}\n\n/**\n * Interface representing the specification of a model.\n * @typedef {Object} ModelSpec\n * @property {string} name - The name of the model.\n * @property {string} repo - The repository of the model.\n * @property {string} size - The size of the model.\n * @property {string} quantization - The quantization of the model.\n * @property {number} contextSize - The context size of the model.\n * @property {TokenizerConfig} tokenizer - The configuration for the tokenizer used by the model.\n */\nexport interface ModelSpec {\n name: string;\n repo: string;\n size: string;\n quantization: string;\n contextSize: number;\n tokenizer: TokenizerConfig;\n}\n\n/**\n * Interface representing the specification of an embedding model.\n * @typedef {Object} EmbeddingModelSpec\n * @property {string} name - The name of the embedding model.\n * @property {string} repo - The repository of the embedding model.\n * @property {string} size - The size of the embedding model.\n * @property {string} quantization - The quantization of the embedding model.\n * @property {number} contextSize - The context size of the embedding model.\n * @property {number} dimensions - The embedding dimensions.\n * @property {TokenizerConfig} tokenizer - The configuration for the tokenizer used by the model.\n */\nexport interface EmbeddingModelSpec extends ModelSpec {\n dimensions: number;\n}\n\n/**\n * Interface representing a specification for a vision model.\n * @typedef {object} VisionModelSpec\n * @property {string} name - The name of the vision model.\n * @property {string} repo - The repository of the vision model.\n * @property {string} size - The size of the vision model.\n * @property {string} modelId - The ID of the vision model.\n * @property {number} contextSize - The context size of the vision model.\n * @property {number} maxTokens - The maximum tokens of the vision model.\n * @property {Array.<string>} tasks - The tasks performed by the vision model.\n */\nexport interface VisionModelSpec {\n name: string;\n repo: string;\n size: string;\n modelId: string;\n contextSize: number;\n maxTokens: number;\n tasks: string[];\n}\n\n/**\n * Interface representing the specification for a TTS model.\n * @typedef { Object } TTSModelSpec\n * @property { string } name - The name of the model.\n * @property { string } repo - The repository where the model is stored.\n * @property { string } size - The size of the model.\n * @property { string } quantization - The quantization method used for the model.\n * @property {string[]} speakers - An array of speakers the model can mimic.\n * @property {string[]} languages - An array of languages the model can speak in.\n * @property {string[]} features - An array of features supported by the model.\n * @property { number } maxInputLength - The maximum input length accepted by the model.\n * @property { number } sampleRate - The sample rate used by the model.\n * @property { number } contextSize - The context size used by the model.\n * @property { TokenizerConfig } tokenizer - The configuration for the tokenizer used by the model.\n */\nexport interface TTSModelSpec {\n name: string;\n repo: string;\n size: string;\n quantization: string;\n speakers: string[];\n languages: string[];\n features: string[];\n maxInputLength: number;\n sampleRate: number;\n contextSize: number;\n tokenizer: TokenizerConfig;\n}\n\n/**\n * Interface representing a specification for a TTS model runnable with Transformers.js.\n * @typedef { object } TransformersJsTTSModelSpec\n * @property { string } modelId - The Hugging Face model identifier (e.g., 'Xenova/speecht5_tts').\n * @property { number } defaultSampleRate - The typical sample rate for this model (e.g., 16000 for SpeechT5).\n * @property { string } [defaultSpeakerEmbeddingUrl] - Optional URL to a default speaker embedding .bin file.\n */\nexport interface TransformersJsTTSModelSpec {\n modelId: string;\n defaultSampleRate: number;\n defaultSpeakerEmbeddingUrl?: string;\n}\n\n// Model specifications mapping\n/**\n * Interface for specifying different models for a project.\n * @interface ModelSpecs\n * @property {ModelSpec} small - Specifications for a small model\n * @property {ModelSpec} medium - Specifications for a medium model\n * @property {EmbeddingModelSpec} embedding - Specifications for an embedding model\n * @property {VisionModelSpec} vision - Specifications for a vision model\n * @property {VisionModelSpec} visionvl - Specifications for a vision model with vision loss\n * @property {Object} tts - Specifications for text-to-speech models (using Transformers.js)\n * @property {TransformersJsTTSModelSpec} tts.default - Specifications for the default text-to-speech model\n */\nexport interface ModelSpecs {\n small: ModelSpec;\n medium: ModelSpec;\n embedding: EmbeddingModelSpec;\n vision: VisionModelSpec;\n visionvl: VisionModelSpec;\n tts: {\n default: TransformersJsTTSModelSpec;\n };\n}\n\n// Export MODEL_SPECS constant type\n/**\n * Model specifications containing information about various models such as name, repository, size, quantization, context size, tokenizer details, tasks, speakers, languages, features, max input length, sample rate, and other relevant information.\n */\nexport const MODEL_SPECS: ModelSpecs = {\n small: {\n name: 'DeepHermes-3-Llama-3-3B-Preview-q4.gguf',\n repo: 'NousResearch/DeepHermes-3-Llama-3-3B-Preview-GGUF',\n size: '3B',\n quantization: 'Q4_0',\n contextSize: 8192,\n tokenizer: {\n name: 'NousResearch/DeepHermes-3-Llama-3-3B-Preview',\n type: 'llama',\n },\n },\n medium: {\n name: 'DeepHermes-3-Llama-3-8B-q4.gguf',\n repo: 'NousResearch/DeepHermes-3-Llama-3-8B-Preview-GGUF',\n size: '8B',\n quantization: 'Q4_0',\n contextSize: 8192,\n tokenizer: {\n name: 'NousResearch/DeepHermes-3-Llama-3-8B-Preview',\n type: 'llama',\n },\n },\n embedding: {\n name: 'bge-small-en-v1.5.Q4_K_M.gguf',\n repo: 'ChristianAzinn/bge-small-en-v1.5-gguf',\n size: '133 MB',\n quantization: 'Q4_K_M',\n contextSize: 512,\n dimensions: 384,\n tokenizer: {\n name: 'ChristianAzinn/bge-small-en-v1.5-gguf',\n type: 'llama',\n },\n },\n vision: {\n name: 'Florence-2-base-ft',\n repo: 'onnx-community/Florence-2-base-ft',\n size: '0.23B',\n modelId: 'onnx-community/Florence-2-base-ft',\n contextSize: 1024,\n maxTokens: 256,\n tasks: [\n 'CAPTION',\n 'DETAILED_CAPTION',\n 'MORE_DETAILED_CAPTION',\n 'CAPTION_TO_PHRASE_GROUNDING',\n 'OD',\n 'DENSE_REGION_CAPTION',\n 'REGION_PROPOSAL',\n 'OCR',\n 'OCR_WITH_REGION',\n ],\n },\n visionvl: {\n name: 'Qwen2.5-VL-3B-Instruct',\n repo: 'Qwen/Qwen2.5-VL-3B-Instruct',\n size: '3B',\n modelId: 'Qwen/Qwen2.5-VL-3B-Instruct',\n contextSize: 32768,\n maxTokens: 1024,\n tasks: [\n 'CAPTION',\n 'DETAILED_CAPTION',\n 'IMAGE_UNDERSTANDING',\n 'VISUAL_QUESTION_ANSWERING',\n 'OCR',\n 'VISUAL_LOCALIZATION',\n 'REGION_ANALYSIS',\n ],\n },\n tts: {\n default: {\n modelId: 'Xenova/speecht5_tts',\n defaultSampleRate: 16000, // SpeechT5 default\n // Use the standard embedding URL\n defaultSpeakerEmbeddingUrl:\n 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/speaker_embeddings.bin',\n },\n },\n};\n","import fs from 'node:fs';\nimport https from 'node:https';\nimport path from 'node:path';\nimport { logger } from '@elizaos/core';\nimport type { ModelSpec } from '../types';\n\n/**\n * Class representing a Download Manager.\n */\nexport class DownloadManager {\n private static instance: DownloadManager | null = null;\n private cacheDir: string;\n private modelsDir: string;\n // Track active downloads to prevent duplicates\n private activeDownloads: Map<string, Promise<void>> = new Map();\n\n /**\n * Creates a new instance of CacheManager.\n *\n * @param {string} cacheDir - The directory path for caching data.\n * @param {string} modelsDir - The directory path for model files.\n */\n private constructor(cacheDir: string, modelsDir: string) {\n this.cacheDir = cacheDir;\n this.modelsDir = modelsDir;\n this.ensureCacheDirectory();\n this.ensureModelsDirectory();\n }\n\n /**\n * Returns the singleton instance of the DownloadManager class.\n * If an instance does not already exist, it creates a new one using the provided cache directory and models directory.\n *\n * @param {string} cacheDir - The directory where downloaded files are stored.\n * @param {string} modelsDir - The directory where model files are stored.\n * @returns {DownloadManager} The singleton instance of the DownloadManager class.\n */\n public static getInstance(cacheDir: string, modelsDir: string): DownloadManager {\n if (!DownloadManager.instance) {\n DownloadManager.instance = new DownloadManager(cacheDir, modelsDir);\n }\n return DownloadManager.instance;\n }\n\n /**\n * Ensure that the cache directory exists.\n */\n private ensureCacheDirectory(): void {\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n logger.debug('Created cache directory');\n }\n }\n\n /**\n * Ensure that the models directory exists. If it does not exist, create it.\n */\n private ensureModelsDirectory(): void {\n logger.debug('Ensuring models directory exists:', this.modelsDir);\n if (!fs.existsSync(this.modelsDir)) {\n fs.mkdirSync(this.modelsDir, { recursive: true });\n logger.debug('Created models directory');\n }\n }\n\n /**\n * Downloads a file from a given URL to a specified destination path asynchronously.\n *\n * @param {string} url - The URL from which to download the file.\n * @param {string} destPath - The destination path where the downloaded file will be saved.\n * @returns {Promise<void>} A Promise that resolves when the file download is completed successfully or rejects if an error occurs.\n */\n private async downloadFileInternal(url: string, destPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n logger.info(`Starting download to: ${destPath}`);\n\n // Create a temporary file path in the same directory as destPath\n const tempPath = `${destPath}.tmp`;\n\n // Check if temp file already exists and remove it to avoid conflicts\n if (fs.existsSync(tempPath)) {\n try {\n logger.warn(`Removing existing temporary file: ${tempPath}`);\n fs.unlinkSync(tempPath);\n } catch (err) {\n logger.error(\n `Failed to remove existing temporary file: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n\n const request = https.get(\n url,\n {\n headers: {\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',\n },\n timeout: 300000, // Increase timeout to 5 minutes\n },\n (response) => {\n if (response.statusCode === 301 || response.statusCode === 302) {\n const redirectUrl = response.headers.location;\n if (!redirectUrl) {\n reject(new Error('Redirect location not found'));\n return;\n }\n // logger.info(`Following redirect to: ${redirectUrl}`);\n // Remove the current download from tracking before starting a new one\n this.activeDownloads.delete(destPath);\n this.downloadFile(redirectUrl, destPath).then(resolve).catch(reject);\n return;\n }\n\n if (response.statusCode !== 200) {\n reject(new Error(`Failed to download: ${response.statusCode}`));\n return;\n }\n\n const totalSize = Number.parseInt(response.headers['content-length'] || '0', 10);\n let downloadedSize = 0;\n let lastLoggedPercent = 0;\n const barLength = 30;\n\n // Log initial progress bar\n const fileName = path.basename(destPath);\n logger.info(`Downloading ${fileName}: ${'▱'.repeat(barLength)} 0%`);\n\n const file = fs.createWriteStream(tempPath);\n\n response.on('data', (chunk) => {\n downloadedSize += chunk.length;\n const percent = Math.round((downloadedSize / totalSize) * 100);\n\n // Only update progress bar when percentage changes significantly (every 5%)\n if (percent >= lastLoggedPercent + 5) {\n const filledLength = Math.floor((downloadedSize / totalSize) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(`Downloading ${fileName}: ${progressBar} ${percent}%`);\n lastLoggedPercent = percent;\n }\n });\n\n response.pipe(file);\n\n file.on('finish', () => {\n file.close(() => {\n try {\n // Show completed progress bar\n const completedBar = '▰'.repeat(barLength);\n logger.info(`Downloading ${fileName}: ${completedBar} 100%`);\n\n // Ensure the destination directory exists\n const destDir = path.dirname(destPath);\n if (!fs.existsSync(destDir)) {\n fs.mkdirSync(destDir, { recursive: true });\n }\n\n // Check if temp file exists before proceeding\n if (!fs.existsSync(tempPath)) {\n reject(new Error(`Temporary file ${tempPath} does not exist`));\n return;\n }\n\n // Only delete the existing file if the temp file is ready\n if (fs.existsSync(destPath)) {\n try {\n // Create a backup of the existing file before deleting it\n const backupPath = `${destPath}.bak`;\n fs.renameSync(destPath, backupPath);\n logger.info(`Created backup of existing file: ${backupPath}`);\n\n // Move temp file to destination\n fs.renameSync(tempPath, destPath);\n\n // If successful, remove the backup\n if (fs.existsSync(backupPath)) {\n fs.unlinkSync(backupPath);\n logger.info(`Removed backup file after successful update: ${backupPath}`);\n }\n } catch (moveErr) {\n logger.error(\n `Error replacing file: ${moveErr instanceof Error ? moveErr.message : String(moveErr)}`\n );\n\n // Try to restore from backup if the move failed\n const backupPath = `${destPath}.bak`;\n if (fs.existsSync(backupPath)) {\n try {\n fs.renameSync(backupPath, destPath);\n logger.info(`Restored from backup after failed update: ${backupPath}`);\n } catch (restoreErr) {\n logger.error(\n `Failed to restore from backup: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`\n );\n }\n }\n\n // Clean up temp file\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n\n reject(moveErr);\n return;\n }\n } else {\n // No existing file, just move the temp file\n fs.renameSync(tempPath, destPath);\n }\n\n logger.success(`Download of ${fileName} completed successfully`);\n\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n resolve();\n } catch (err) {\n logger.error(\n `Error finalizing download: ${err instanceof Error ? err.message : String(err)}`\n );\n // Clean up temp file if it exists\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n reject(err);\n }\n });\n });\n\n file.on('error', (err) => {\n logger.error(`File write error: ${err instanceof Error ? err.message : String(err)}`);\n file.close(() => {\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file after error: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n reject(err);\n });\n });\n }\n );\n\n request.on('error', (err) => {\n logger.error(`Request error: ${err instanceof Error ? err.message : String(err)}`);\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file after request error: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n reject(err);\n });\n\n request.on('timeout', () => {\n logger.error('Download timeout occurred');\n request.destroy();\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file after timeout: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n reject(new Error('Download timeout'));\n });\n });\n }\n\n /**\n * Asynchronously downloads a file from the specified URL to the destination path.\n *\n * @param {string} url - The URL of the file to download.\n * @param {string} destPath - The destination path to save the downloaded file.\n * @returns {Promise<void>} A Promise that resolves once the file has been successfully downloaded.\n */\n public async downloadFile(url: string, destPath: string): Promise<void> {\n // Check if this file is already being downloaded\n if (this.activeDownloads.has(destPath)) {\n logger.info(`Download for ${destPath} already in progress, waiting for it to complete...`);\n const existingDownload = this.activeDownloads.get(destPath);\n if (existingDownload) {\n return existingDownload;\n }\n // If somehow the download was removed from the map but the key still exists\n logger.warn(\n `Download for ${destPath} was marked as in progress but not found in tracking map`\n );\n }\n\n // Start a new download and track it\n const downloadPromise = this.downloadFileInternal(url, destPath);\n this.activeDownloads.set(destPath, downloadPromise);\n\n try {\n return await downloadPromise;\n } catch (error) {\n // Make sure to remove from active downloads in case of error\n this.activeDownloads.delete(destPath);\n throw error;\n }\n }\n\n /**\n * Downloads a model specified by the modelSpec and saves it to the provided modelPath.\n * If the model is successfully downloaded, returns true, otherwise returns false.\n *\n * @param {ModelSpec} modelSpec - The model specification containing repo and name.\n * @param {string} modelPath - The path where the model will be saved.\n * @returns {Promise<boolean>} - Indicates if the model was successfully downloaded or not.\n */\n public async downloadModel(modelSpec: ModelSpec, modelPath: string): Promise<boolean> {\n try {\n logger.info('Starting local model download...');\n\n // Ensure model directory exists\n const modelDir = path.dirname(modelPath);\n if (!fs.existsSync(modelDir)) {\n logger.info('Creating model directory:', modelDir);\n fs.mkdirSync(modelDir, { recursive: true });\n }\n\n if (!fs.existsSync(modelPath)) {\n // Try different URL patterns in sequence, similar to TTS manager approach\n const attempts = [\n {\n description: 'LFS URL with GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo}/resolve/main/${modelSpec.name}?download=true`,\n },\n {\n description: 'LFS URL without GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo.replace('-GGUF', '')}/resolve/main/${modelSpec.name}?download=true`,\n },\n {\n description: 'Standard URL with GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo}/resolve/main/${modelSpec.name}`,\n },\n {\n description: 'Standard URL without GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo.replace('-GGUF', '')}/resolve/main/${modelSpec.name}`,\n },\n ];\n\n // logger.info(\"Model download details:\", {\n // modelName: modelSpec.name,\n // repo: modelSpec.repo,\n // modelPath: modelPath,\n // attemptUrls: attempts.map(a => ({ description: a.description, url: a.url })),\n // timestamp: new Date().toISOString()\n // });\n\n let lastError = null;\n let downloadSuccess = false;\n\n for (const attempt of attempts) {\n try {\n logger.info('Attempting model download:', {\n description: attempt.description,\n url: attempt.url,\n timestamp: new Date().toISOString(),\n });\n\n // The downloadFile method now handles the progress bar display\n await this.downloadFile(attempt.url, modelPath);\n\n logger.success(\n `Model download complete: ${modelSpec.name} using ${attempt.description}`\n );\n downloadSuccess = true;\n break;\n } catch (error) {\n lastError = error;\n logger.warn('Model download attempt failed:', {\n description: attempt.description,\n error: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n if (!downloadSuccess) {\n throw lastError || new Error('All download attempts failed');\n }\n\n // Return true to indicate the model was newly downloaded\n return true;\n }\n\n // Model already exists\n logger.info('Model already exists at:', modelPath);\n // Return false to indicate the model already existed\n return false;\n } catch (error) {\n logger.error('Model download failed:', {\n error: error instanceof Error ? error.message : String(error),\n modelPath: modelPath,\n model: modelSpec.name,\n });\n throw error;\n }\n }\n\n /**\n * Returns the cache directory path.\n *\n * @returns {string} The path of the cache directory.\n */\n\n public getCacheDir(): string {\n return this.cacheDir;\n }\n\n /**\n * Downloads a file from a given URL to a specified destination path.\n *\n * @param {string} url - The URL of the file to download.\n * @param {string} destPath - The destination path where the file should be saved.\n * @returns {Promise<void>} A Promise that resolves once the file has been downloaded.\n */\n public async downloadFromUrl(url: string, destPath: string): Promise<void> {\n return this.downloadFile(url, destPath);\n }\n\n /**\n * Ensures that the specified directory exists. If it does not exist, it will be created.\n * @param {string} dirPath - The path of the directory to ensure existence of.\n * @returns {void}\n */\n public ensureDirectoryExists(dirPath: string): void {\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n logger.info(`Created directory: ${dirPath}`);\n }\n }\n}\n","import { exec } from 'node:child_process';\nimport os from 'node:os';\nimport { promisify } from 'node:util';\nimport { logger } from '@elizaos/core';\n\nconst execAsync = promisify(exec);\n\n/**\n * Represents the configuration of a system GPU.\n * @typedef {Object} SystemGPU\n * @property {string} name - The name of the GPU.\n * @property {number} [memory] - The memory size of the GPU. (Optional)\n * @property {\"cuda\" | \"metal\" | \"directml\" | \"none\"} type - The type of GPU.\n * @property {string} [version] - The version of the GPU. (Optional)\n * @property {boolean} [isAppleSilicon] - Indicates if the GPU is Apple Silicon. (Optional)\n */\nexport interface SystemGPU {\n name: string;\n memory?: number;\n type: 'cuda' | 'metal' | 'directml' | 'none';\n version?: string;\n isAppleSilicon?: boolean;\n}\n\n/**\n * Interface representing the system CPU information.\n * @typedef {Object} SystemCPU\n * @property {string} model - The model of the CPU.\n * @property {number} cores - The number of cores in the CPU.\n * @property {number} speed - The speed of the CPU.\n * @property {string} architecture - The architecture of the CPU.\n * @property {Object} memory - Object containing memory information.\n * @property {number} memory.total - The total memory available.\n * @property {number} memory.free - The free memory available.\n */\nexport interface SystemCPU {\n model: string;\n cores: number;\n speed: number;\n architecture: string;\n memory: {\n total: number;\n free: number;\n };\n}\n\n/**\n * Interface representing the capabilities of a system.\n *\n * @typedef {Object} SystemCapabilities\n * @property {NodeJS.Platform} platform - The platform of the system.\n * @property {SystemCPU} cpu - The CPU information of the system.\n * @property {SystemGPU | null} gpu - The GPU information of the system, can be null if no GPU is present.\n * @property {\"small\" | \"medium\" | \"large\"} recommendedModelSize - The recommended model size for the system.\n * @property {Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\">} supportedBackends - An array of supported backends for the system.\n */\nexport interface SystemCapabilities {\n platform: NodeJS.Platform;\n cpu: SystemCPU;\n gpu: SystemGPU | null;\n recommendedModelSize: 'small' | 'medium' | 'large';\n supportedBackends: Array<'cuda' | 'metal' | 'directml' | 'cpu'>;\n}\n\n/**\n * Class representing a Platform Manager.\n *\n * @class\n */\n\nexport class PlatformManager {\n private static instance: PlatformManager;\n private capabilities: SystemCapabilities | null = null;\n\n /**\n * Private constructor method.\n */\n private constructor() {}\n\n /**\n * Get the singleton instance of the PlatformManager class\n * @returns {PlatformManager} The instance of PlatformManager\n */\n static getInstance(): PlatformManager {\n if (!PlatformManager.instance) {\n PlatformManager.instance = new PlatformManager();\n }\n return PlatformManager.instance;\n }\n\n /**\n * Asynchronous method to initialize platform detection.\n *\n * @returns {Promise<void>} Promise that resolves once platform detection is completed.\n */\n async initialize(): Promise<void> {\n try {\n logger.info('Initializing platform detection...');\n this.capabilities = await this.detectSystemCapabilities();\n // logger.info(\"Platform detection completed\", {\n // platform: this.capabilities.platform,\n // gpu: this.capabilities.gpu?.type || \"none\",\n // recommendedModel: this.capabilities.recommendedModelSize,\n // });\n } catch (error) {\n logger.error('Platform detection failed', { error });\n throw error;\n }\n }\n\n /**\n * Detects the system capabilities including platform, CPU information, GPU information,\n * supported backends, and recommended model size.\n *\n * @returns {Promise<SystemCapabilities>} Details of the system capabilities including platform, CPU info, GPU info,\n * recommended model size, and supported backends.\n */\n private async detectSystemCapabilities(): Promise<SystemCapabilities> {\n const platform = process.platform;\n const cpuInfo = this.getCPUInfo();\n const gpu = await this.detectGPU();\n const supportedBackends = await this.getSupportedBackends(platform, gpu);\n const recommendedModelSize = this.getRecommendedModelSize(cpuInfo, gpu);\n\n return {\n platform,\n cpu: cpuInfo,\n gpu,\n recommendedModelSize,\n supportedBackends,\n };\n }\n\n /**\n * Returns information about the CPU and memory of the system.\n * @returns {SystemCPU} The CPU information including model, number of cores, speed, architecture, and memory details.\n */\n private getCPUInfo(): SystemCPU {\n const cpus = os.cpus();\n const totalMemory = os.totalmem();\n const freeMemory = os.freemem();\n\n return {\n model: cpus[0].model,\n cores: cpus.length,\n speed: cpus[0].speed,\n architecture: process.arch,\n memory: {\n total: totalMemory,\n free: freeMemory,\n },\n };\n }\n\n /**\n * Asynchronously detects the GPU information based on the current platform.\n * @returns A promise that resolves with the GPU information if detection is successful, otherwise null.\n */\n private async detectGPU(): Promise<SystemGPU | null> {\n const platform = process.platform;\n\n try {\n switch (platform) {\n case 'darwin':\n return await this.detectMacGPU();\n case 'win32':\n return await this.detectWindowsGPU();\n case 'linux':\n return await this.detectLinuxGPU();\n default:\n return null;\n }\n } catch (error) {\n logger.error('GPU detection failed', { error });\n return null;\n }\n }\n\n /**\n * Asynchronously detects the GPU of a Mac system.\n * @returns {Promise<SystemGPU>} A promise that resolves to an object representing the detected GPU.\n */\n private async detectMacGPU(): Promise<SystemGPU> {\n try {\n const { stdout } = await execAsync('sysctl -n machdep.cpu.brand_string');\n const isAppleSilicon = stdout.toLowerCase().includes('apple');\n\n if (isAppleSilicon) {\n return {\n name: 'Apple Silicon',\n type: 'metal',\n isAppleSilicon: true,\n };\n }\n\n // For Intel Macs with discrete GPU\n const { stdout: gpuInfo } = await execAsync('system_profiler SPDisplaysDataType');\n return {\n name: gpuInfo.split('Chipset Model:')[1]?.split('\\n')[0]?.trim() || 'Unknown GPU',\n type: 'metal',\n isAppleSilicon: false,\n };\n } catch (error) {\n logger.error('Mac GPU detection failed', { error });\n return {\n name: 'Unknown Mac GPU',\n type: 'metal',\n isAppleSilicon: false,\n };\n }\n }\n\n /**\n * Detects the GPU in a Windows system and returns information about it.\n *\n * @returns {Promise<SystemGPU | null>} A promise that resolves with the detected GPU information or null if detection fails.\n */\n private async detectWindowsGPU(): Promise<SystemGPU | null> {\n try {\n const { stdout } = await execAsync('wmic path win32_VideoController get name');\n const gpuName = stdout.split('\\n')[1].trim();\n\n // Check for NVIDIA GPU\n if (gpuName.toLowerCase().includes('nvidia')) {\n const { stdout: nvidiaInfo } = await execAsync(\n 'nvidia-smi --query-gpu=name,memory.total --format=csv,noheader'\n );\n const [name, memoryStr] = nvidiaInfo.split(',').map((s) => s.trim());\n const memory = Number.parseInt(memoryStr);\n\n return {\n name,\n memory,\n type: 'cuda',\n version: await this.getNvidiaDriverVersion(),\n };\n }\n\n // Default to DirectML for other GPUs\n return {\n name: gpuName,\n type: 'directml',\n };\n } catch (error) {\n logger.error('Windows GPU detection failed', { error });\n return null;\n }\n }\n\n /**\n * Asynchronously detects the GPU information for Linux systems.\n * Tries to detect NVIDIA GPU first using 'nvidia-smi' command and if successful,\n * returns the GPU name, memory size, type as 'cuda', and NVIDIA driver version.\n * If NVIDIA detection fails, it falls back to checking for other GPUs using 'lspci | grep -i vga' command.\n * If no GPU is detected, it returns null.\n *\n * @returns {Promise<SystemGPU | null>} The detected GPU information or null if detection fails.\n */\n private async detectLinuxGPU(): Promise<SystemGPU | null> {\n try {\n // Try NVIDIA first\n const { stdout } = await execAsync(\n 'nvidia-smi --query-gpu=name,memory.total --format=csv,noheader'\n );\n if (stdout) {\n const [name, memoryStr] = stdout.split(',').map((s) => s.trim());\n const memory = Number.parseInt(memoryStr);\n\n return {\n name,\n memory,\n type: 'cuda',\n version: await this.getNvidiaDriverVersion(),\n };\n }\n } catch {\n // If nvidia-smi fails, check for other GPUs\n try {\n const { stdout } = await execAsync('lspci | grep -i vga');\n return {\n name: stdout.split(':').pop()?.trim() || 'Unknown GPU',\n type: 'none',\n };\n } catch (error) {\n logger.error('Linux GPU detection failed', { error });\n return null;\n }\n }\n return null;\n }\n\n /**\n * Asynchronously retrieves the driver version of the Nvidia GPU using the 'nvidia-smi' command.\n *\n * @returns A promise that resolves with the driver version as a string, or 'unknown' if an error occurs.\n */\n private async getNvidiaDriverVersion(): Promise<string> {\n try {\n const { stdout } = await execAsync(\n 'nvidia-smi --query-gpu=driver_version --format=csv,noheader'\n );\n return stdout.trim();\n } catch {\n return 'unknown';\n }\n }\n\n /**\n * Retrieves the supported backends based on the platform and GPU type.\n * @param {NodeJS.Platform} platform - The platform on which the code is running.\n * @param {SystemGPU | null} gpu - The GPU information, if available.\n * @returns {Promise<Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\">>} - An array of supported backends including 'cuda', 'metal', 'directml', and 'cpu'.\n */\n private async getSupportedBackends(\n platform: NodeJS.Platform,\n gpu: SystemGPU | null\n ): Promise<Array<'cuda' | 'metal' | 'directml' | 'cpu'>> {\n const backends: Array<'cuda' | 'metal' | 'directml' | 'cpu'> = ['cpu'];\n\n if (gpu) {\n switch (platform) {\n case 'darwin':\n backends.push('metal');\n break;\n case 'win32':\n if (gpu.type === 'cuda') {\n backends.push('cuda');\n }\n backends.push('directml');\n break;\n case 'linux':\n if (gpu.type === 'cuda') {\n backends.push('cuda');\n }\n break;\n }\n }\n\n return backends;\n }\n\n /**\n * Determines the recommended model size based on the system's CPU and GPU.\n * @param {SystemCPU} cpu - The system's CPU.\n * @param {SystemGPU | null} gpu - The system's GPU, if available.\n * @returns {\"small\" | \"medium\" | \"large\"} - The recommended model size (\"small\", \"medium\", or \"large\").\n */\n private getRecommendedModelSize(\n cpu: SystemCPU,\n gpu: SystemGPU | null\n ): 'small' | 'medium' | 'large' {\n // For Apple Silicon\n if (gpu?.isAppleSilicon) {\n return cpu.memory.total > 16 * 1024 * 1024 * 1024 ? 'medium' : 'small';\n }\n\n // For NVIDIA GPUs\n if (gpu?.type === 'cuda') {\n const gpuMemGB = (gpu.memory || 0) / 1024;\n if (gpuMemGB >= 16) return 'large';\n if (gpuMemGB >= 8) return 'medium';\n }\n\n // For systems with significant RAM but no powerful GPU\n if (cpu.memory.total > 32 * 1024 * 1024 * 1024) return 'medium';\n\n // Default to small model\n return 'small';\n }\n\n /**\n * Returns the SystemCapabilities of the PlatformManager.\n *\n * @returns {SystemCapabilities} The SystemCapabilities of the PlatformManager.\n * @throws {Error} if PlatformManager is not initialized.\n */\n getCapabilities(): SystemCapabilities {\n if (!this.capabilities) {\n throw new Error('PlatformManager not initialized');\n }\n return this.capabilities;\n }\n\n /**\n * Checks if the device's GPU is Apple Silicon.\n * @returns {boolean} True if the GPU is Apple Silicon, false otherwise.\n */\n isAppleSilicon(): boolean {\n return !!this.capabilities?.gpu?.isAppleSilicon;\n }\n\n /**\n * Checks if the current device has GPU support.\n * @returns {boolean} - Returns true if the device has GPU support, false otherwise.\n */\n hasGPUSupport(): boolean {\n return !!this.capabilities?.gpu;\n }\n\n /**\n * Checks if the system supports CUDA GPU for processing.\n *\n * @returns {boolean} True if the system supports CUDA, false otherwise.\n */\n supportsCUDA(): boolean {\n return this.capabilities?.gpu?.type === 'cuda';\n }\n\n /**\n * Check if the device supports Metal API for rendering graphics.\n * @returns {boolean} True if the device supports Metal, false otherwise.\n */\n supportsMetal(): boolean {\n return this.capabilities?.gpu?.type === 'metal';\n }\n\n /**\n * Check if the device supports DirectML for GPU acceleration.\n *\n * @returns {boolean} True if the device supports DirectML, false otherwise.\n */\n supportsDirectML(): boolean {\n return this.capabilities?.gpu?.type === 'directml';\n }\n\n /**\n * Get the recommended backend for computation based on the available capabilities.\n * @returns {\"cuda\" | \"metal\" | \"directml\" | \"cpu\"} The recommended backend for computation.\n * @throws {Error} Throws an error if PlatformManager is not initialized.\n */\n getRecommendedBackend(): 'cuda' | 'metal' | 'directml' | 'cpu' {\n if (!this.capabilities) {\n throw new Error('PlatformManager not initialized');\n }\n\n const { gpu, supportedBackends } = this.capabilities;\n\n if (gpu?.type === 'cuda') return 'cuda';\n if (gpu?.type === 'metal') return 'metal';\n if (supportedBackends.includes('directml')) return 'directml';\n return 'cpu';\n }\n}\n\n// Export a helper function to get the singleton instance\nexport const getPlatformManager = (): PlatformManager => {\n return PlatformManager.getInstance();\n};\n","import { logger } from '@elizaos/core';\nimport { AutoTokenizer, type PreTrainedTokenizer } from '@huggingface/transformers';\n\n// Import the MODEL_SPECS type from a new types file we'll create later\nimport type { ModelSpec } from '../types';\n\n/**\n * Represents a Tokenizer Manager which manages tokenizers for different models.\n * * @class TokenizerManager\n */\nexport class TokenizerManager {\n private static instance: TokenizerManager | null = null;\n private tokenizers: Map<string, PreTrainedTokenizer>;\n private cacheDir: string;\n private modelsDir: string;\n\n /**\n * Constructor for creating a new instance of the class.\n *\n * @param {string} cacheDir - The directory for caching data.\n * @param {string} modelsDir - The directory for storing models.\n */\n private constructor(cacheDir: string, modelsDir: string) {\n this.tokenizers = new Map();\n this.cacheDir = cacheDir;\n this.modelsDir = modelsDir;\n }\n\n /**\n * Get the singleton instance of TokenizerManager class. If the instance does not exist, it will create a new one.\n *\n * @param {string} cacheDir - The directory to cache the tokenizer models.\n * @param {string} modelsDir - The directory where tokenizer models are stored.\n * @returns {TokenizerManager} The singleton instance of TokenizerManager.\n */\n static getInstance(cacheDir: string, modelsDir: string): TokenizerManager {\n if (!TokenizerManager.instance) {\n TokenizerManager.instance = new TokenizerManager(cacheDir, modelsDir);\n }\n return TokenizerManager.instance;\n }\n\n /**\n * Asynchronously loads a tokenizer based on the provided ModelSpec configuration.\n *\n * @param {ModelSpec} modelConfig - The configuration object for the model to load the tokenizer for.\n * @returns {Promise<PreTrainedTokenizer>} - A promise that resolves to the loaded tokenizer.\n */\n async loadTokenizer(modelConfig: ModelSpec): Promise<PreTrainedTokenizer> {\n try {\n const tokenizerKey = `${modelConfig.tokenizer.type}-${modelConfig.tokenizer.name}`;\n logger.info('Loading tokenizer:', {\n key: tokenizerKey,\n name: modelConfig.tokenizer.name,\n type: modelConfig.tokenizer.type,\n modelsDir: this.modelsDir,\n cacheDir: this.cacheDir,\n });\n\n if (this.tokenizers.has(tokenizerKey)) {\n logger.info('Using cached tokenizer:', { key: tokenizerKey });\n const cachedTokenizer = this.tokenizers.get(tokenizerKey);\n if (!cachedTokenizer) {\n throw new Error(`Tokenizer ${tokenizerKey} exists in map but returned undefined`);\n }\n return cachedTokenizer;\n }\n\n // Check if models directory exists\n const fs = await import('node:fs');\n if (!fs.existsSync(this.modelsDir)) {\n logger.warn('Models directory does not exist, creating it:', this.modelsDir);\n fs.mkdirSync(this.modelsDir, { recursive: true });\n }\n\n logger.info(\n 'Initializing new tokenizer from HuggingFace with models directory:',\n this.modelsDir\n );\n\n try {\n const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {\n cache_dir: this.modelsDir,\n local_files_only: false,\n });\n\n this.tokenizers.set(tokenizerKey, tokenizer);\n logger.success('Tokenizer loaded successfully:', { key: tokenizerKey });\n return tokenizer;\n } catch (tokenizeError) {\n logger.error('Failed to load tokenizer from HuggingFace:', {\n error: tokenizeError instanceof Error ? tokenizeError.message : String(tokenizeError),\n stack: tokenizeError instanceof Error ? tokenizeError.stack : undefined,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n\n // Try again with local_files_only set to false and a longer timeout\n logger.info('Retrying tokenizer loading...');\n const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {\n cache_dir: this.modelsDir,\n local_files_only: false,\n });\n\n this.tokenizers.set(tokenizerKey, tokenizer);\n logger.success('Tokenizer loaded successfully on retry:', {\n key: tokenizerKey,\n });\n return tokenizer;\n }\n } catch (error) {\n logger.error('Failed to load tokenizer:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n model: modelConfig.name,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n\n /**\n * Encodes the given text using the specified tokenizer model configuration.\n *\n * @param {string} text - The text to encode.\n * @param {ModelSpec} modelConfig - The configuration for the model tokenizer.\n * @returns {Promise<number[]>} - An array of integers representing the encoded text.\n * @throws {Error} - If the text encoding fails, an error is thrown.\n */\n async encode(text: string, modelConfig: ModelSpec): Promise<number[]> {\n try {\n logger.info('Encoding text with tokenizer:', {\n length: text.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n\n const tokenizer = await this.loadTokenizer(modelConfig);\n\n logger.info('Tokenizer loaded, encoding text...');\n const encoded = await tokenizer.encode(text, {\n add_special_tokens: true,\n return_token_type_ids: false,\n });\n\n logger.info('Text encoded successfully:', {\n tokenCount: encoded.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n return encoded;\n } catch (error) {\n logger.error('Text encoding failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n textLength: text.length,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously decodes an array of tokens using a tokenizer based on the provided ModelSpec.\n *\n * @param {number[]} tokens - The array of tokens to be decoded.\n * @param {ModelSpec} modelConfig - The ModelSpec object containing information about the model and tokenizer to be used.\n * @returns {Promise<string>} - A Promise that resolves with the decoded text.\n * @throws {Error} - If an error occurs during token decoding.\n */\n async decode(tokens: number[], modelConfig: ModelSpec): Promise<string> {\n try {\n logger.info('Decoding tokens with tokenizer:', {\n count: tokens.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n\n const tokenizer = await this.loadTokenizer(modelConfig);\n\n logger.info('Tokenizer loaded, decoding tokens...');\n const decoded = await tokenizer.decode(tokens, {\n skip_special_tokens: true,\n clean_up_tokenization_spaces: true,\n });\n\n logger.info('Tokens decoded successfully:', {\n textLength: decoded.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n return decoded;\n } catch (error) {\n logger.error('Token decoding failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n tokenCount: tokens.length,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n}\n","import { exec } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport { logger } from '@elizaos/core';\n\nconst execAsync = promisify(exec);\n\n// Lazy load whisper-node to avoid ESM/CommonJS issues\nlet whisperModule: any = null;\nasync function getWhisper() {\n if (!whisperModule) {\n // Dynamic import for CommonJS module\n const module = await import('whisper-node');\n // The module exports an object with a whisper property\n whisperModule = (module as any).whisper;\n }\n return whisperModule;\n}\n\n/**\n * Interface representing the result of a transcription process.\n * @interface\n * @property {string} text - The transcribed text.\n */\ninterface TranscriptionResult {\n text: string;\n}\n\n/**\n * Class representing a TranscribeManager.\n *\n * @property {TranscribeManager | null} instance - The singleton instance of the TranscribeManager class.\n * @property {string} cacheDir - The directory path for caching transcribed files.\n * @property {boolean} ffmpegAvailable - Flag indicating if ffmpeg is available for audio processing.\n * @property {string | null} ffmpegVersion - The version of ffmpeg if available.\n * @property {string | null} ffmpegPath - The path to the ffmpeg executable.\n * @property {boolean} ffmpegInitialized - Flag indicating if ffmpeg has been initialized.\n *\n * @constructor\n * Creates an instance of TranscribeManager with the specified cache directory.\n */\nexport class TranscribeManager {\n private static instance: TranscribeManager | null = null;\n private cacheDir: string;\n private ffmpegAvailable = false;\n private ffmpegVersion: string | null = null;\n private ffmpegPath: string | null = null;\n private ffmpegInitialized = false;\n\n /**\n * Constructor for TranscribeManager class.\n *\n * @param {string} cacheDir - The directory path for storing cached files.\n */\n private constructor(cacheDir: string) {\n this.cacheDir = path.join(cacheDir, 'whisper');\n logger.debug('Initializing TranscribeManager', {\n cacheDir: this.cacheDir,\n timestamp: new Date().toISOString(),\n });\n this.ensureCacheDirectory();\n }\n\n /**\n * Ensures that FFmpeg is initialized and available for use.\n * @returns {Promise<boolean>} A promise that resolves to a boolean value indicating if FFmpeg is available.\n */\n public async ensureFFmpeg(): Promise<boolean> {\n if (!this.ffmpegInitialized) {\n try {\n await this.initializeFFmpeg();\n this.ffmpegInitialized = true;\n } catch (error) {\n logger.error('FFmpeg initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n timestamp: new Date().toISOString(),\n });\n return false;\n }\n }\n return this.ffmpegAvailable;\n }\n\n /**\n * Checks if FFmpeg is available.\n * @returns {boolean} True if FFmpeg is available, false otherwise.\n */\n public isFFmpegAvailable(): boolean {\n return this.ffmpegAvailable;\n }\n\n /**\n * Asynchronously retrieves the FFmpeg version if it hasn't been fetched yet.\n * If the FFmpeg version has already been fetched, it will return the stored version.\n * @returns A Promise that resolves with the FFmpeg version as a string, or null if the version is not available.\n */\n public async getFFmpegVersion(): Promise<string | null> {\n if (!this.ffmpegVersion) {\n await this.fetchFFmpegVersion();\n }\n return this.ffmpegVersion;\n }\n\n /**\n * Fetches the FFmpeg version by executing the command \"ffmpeg -version\".\n * Updates the class property ffmpegVersion with the retrieved version.\n * Logs the FFmpeg version information or error message.\n * @returns {Promise<void>} A Promise that resolves once the FFmpeg version is fetched and logged.\n */\n private async fetchFFmpegVersion(): Promise<void> {\n try {\n const { stdout } = await execAsync('ffmpeg -version');\n this.ffmpegVersion = stdout.split('\\n')[0];\n logger.info('FFmpeg version:', {\n version: this.ffmpegVersion,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n this.ffmpegVersion = null;\n logger.error('Failed to get FFmpeg version:', {\n error: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Initializes FFmpeg by performing the following steps:\n * 1. Checks for FFmpeg availability in PATH\n * 2. Retrieves FFmpeg version information\n * 3. Verifies FFmpeg capabilities\n *\n * If FFmpeg is available, logs a success message with version, path, and timestamp.\n * If FFmpeg is not available, logs installation instructions.\n *\n * @returns A Promise that resolves once FFmpeg has been successfully initialized\n */\n private async initializeFFmpeg(): Promise<void> {\n try {\n // First check if ffmpeg exists in PATH\n await this.checkFFmpegAvailability();\n\n if (this.ffmpegAvailable) {\n // Get FFmpeg version info\n await this.fetchFFmpegVersion();\n\n // Verify FFmpeg capabilities\n await this.verifyFFmpegCapabilities();\n\n logger.success('FFmpeg initialized successfully', {\n version: this.ffmpegVersion,\n path: this.ffmpegPath,\n timestamp: new Date().toISOString(),\n });\n } else {\n this.logFFmpegInstallInstructions();\n }\n } catch (error) {\n this.ffmpegAvailable = false;\n logger.error('FFmpeg initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n timestamp: new Date().toISOString(),\n });\n this.logFFmpegInstallInstructions();\n }\n }\n\n /**\n * Asynchronously checks for the availability of FFmpeg in the system by executing a command to find the FFmpeg location.\n * Updates the class properties `ffmpegPath` and `ffmpegAvailable` accordingly.\n * Logs relevant information such as FFmpeg location and potential errors using the logger.\n *\n * @returns A Promise that resolves with no value upon completion.\n */\n private async checkFFmpegAvailability(): Promise<void> {\n try {\n const { stdout, stderr } = await execAsync('which ffmpeg || where ffmpeg');\n this.ffmpegPath = stdout.trim();\n this.ffmpegAvailable = true;\n logger.info('FFmpeg found at:', {\n path: this.ffmpegPath,\n stderr: stderr ? stderr.trim() : undefined,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n this.ffmpegAvailable = false;\n this.ffmpegPath = null;\n logger.error('FFmpeg not found in PATH:', {\n error: error instanceof Error ? error.message : String(error),\n stderr: error instanceof Error && 'stderr' in error ? error.stderr : undefined,\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Verifies the FFmpeg capabilities by checking if FFmpeg supports the required codecs and formats.\n *\n * @returns {Promise<void>} A Promise that resolves if FFmpeg has the required codecs, otherwise rejects with an error message.\n */\n private async verifyFFmpegCapabilities(): Promise<void> {\n try {\n // Check if FFmpeg supports required codecs and formats\n const { stdout } = await execAsync('ffmpeg -codecs');\n const hasRequiredCodecs = stdout.includes('pcm_s16le') && stdout.includes('wav');\n\n if (!hasRequiredCodecs) {\n throw new Error('FFmpeg installation missing required codecs (pcm_s16le, wav)');\n }\n\n // logger.info(\"FFmpeg capabilities verified\", {\n // hasRequiredCodecs,\n // timestamp: new Date().toISOString()\n // });\n } catch (error) {\n logger.error('FFmpeg capabilities verification failed:', {\n error: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n }\n\n /**\n * Logs instructions on how to install FFmpeg if it is not properly installed.\n */\n private logFFmpegInstallInstructions(): void {\n logger.warn('FFmpeg is required but not properly installed. Please install FFmpeg:', {\n instructions: {\n mac: 'brew install ffmpeg',\n ubuntu: 'sudo apt-get install ffmpeg',\n windows: 'choco install ffmpeg',\n manual: 'Download from https://ffmpeg.org/download.html',\n },\n requiredVersion: '4.0 or later',\n requiredCodecs: ['pcm_s16le', 'wav'],\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Gets the singleton instance of TranscribeManager, creates a new instance if it doesn't exist.\n *\n * @param {string} cacheDir - The directory path for caching transcriptions.\n * @returns {TranscribeManager} The singleton instance of TranscribeManager.\n */\n public static getInstance(cacheDir: string): TranscribeManager {\n if (!TranscribeManager.instance) {\n TranscribeManager.instance = new TranscribeManager(cacheDir);\n }\n return TranscribeManager.instance;\n }\n\n /**\n * Ensures that the cache directory exists. If it doesn't exist,\n * creates the directory using fs.mkdirSync with recursive set to true.\n * @returns {void}\n */\n private ensureCacheDirectory(): void {\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n // logger.info(\"Created whisper cache directory:\", this.cacheDir);\n }\n }\n\n /**\n * Converts an audio file to WAV format using FFmpeg.\n *\n * @param {string} inputPath - The input path of the audio file to convert.\n * @param {string} outputPath - The output path where the converted WAV file will be saved.\n * @returns {Promise<void>} A Promise that resolves when the conversion is completed.\n * @throws {Error} If FFmpeg is not installed or not properly configured, or if the audio conversion fails.\n */\n private async convertToWav(inputPath: string, outputPath: string): Promise<void> {\n if (!this.ffmpegAvailable) {\n throw new Error(\n 'FFmpeg is not installed or not properly configured. Please install FFmpeg to use audio transcription.'\n );\n }\n\n try {\n // Add -loglevel error to suppress FFmpeg output unless there's an error\n const { stderr } = await execAsync(\n `ffmpeg -y -loglevel error -i \"${inputPath}\" -acodec pcm_s16le -ar 16000 -ac 1 \"${outputPath}\"`\n );\n\n if (stderr) {\n logger.warn('FFmpeg conversion error:', {\n stderr,\n inputPath,\n outputPath,\n timestamp: new Date().toISOString(),\n });\n }\n\n if (!fs.existsSync(outputPath)) {\n throw new Error('WAV file was not created successfully');\n }\n } catch (error) {\n logger.error('Audio conversion failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n command: `ffmpeg -y -loglevel error -i \"${inputPath}\" -acodec pcm_s16le -ar 16000 -ac 1 \"${outputPath}\"`,\n ffmpegAvailable: this.ffmpegAvailable,\n ffmpegVersion: this.ffmpegVersion,\n ffmpegPath: this.ffmpegPath,\n timestamp: new Date().toISOString(),\n });\n throw new Error(\n `Failed to convert audio to WAV format: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Asynchronously preprocesses the audio by converting the provided audio buffer into a WAV file.\n * If FFmpeg is not installed, an error is thrown.\n *\n * @param {Buffer} audioBuffer The audio buffer to preprocess\n * @returns {Promise<string>} The path to the preprocessed WAV file\n * @throws {Error} If FFmpeg is not installed or if audio preprocessing fails\n */\n private async preprocessAudio(audioBuffer: Buffer): Promise<string> {\n if (!this.ffmpegAvailable) {\n throw new Error('FFmpeg is not installed. Please install FFmpeg to use audio transcription.');\n }\n\n try {\n // Check if the buffer is already a WAV file\n const isWav =\n audioBuffer.length > 4 &&\n audioBuffer.toString('ascii', 0, 4) === 'RIFF' &&\n audioBuffer.length > 12 &&\n audioBuffer.toString('ascii', 8, 12) === 'WAVE';\n\n // Use appropriate extension based on format detection\n const extension = isWav ? '.wav' : '';\n const tempInputFile = path.join(this.cacheDir, `temp_input_${Date.now()}${extension}`);\n const tempWavFile = path.join(this.cacheDir, `temp_${Date.now()}.wav`);\n\n // logger.info(\"Creating temporary files\", {\n // inputFile: tempInputFile,\n // wavFile: tempWavFile,\n // bufferSize: audioBuffer.length,\n // timestamp: new Date().toISOString()\n // });\n\n // Write buffer to temporary file\n fs.writeFileSync(tempInputFile, audioBuffer);\n // logger.info(\"Temporary input file created\", {\n // path: tempInputFile,\n // size: audioBuffer.length,\n // timestamp: new Date().toISOString()\n // });\n\n // If already WAV with correct format, skip conversion\n if (isWav) {\n // Check if it's already in the correct format (16kHz, mono, 16-bit)\n try {\n const { stdout } = await execAsync(\n `ffprobe -v error -show_entries stream=sample_rate,channels,bits_per_raw_sample -of json \"${tempInputFile}\"`\n );\n const probeResult = JSON.parse(stdout);\n const stream = probeResult.streams?.[0];\n\n if (\n stream?.sample_rate === '16000' &&\n stream?.channels === 1 &&\n (stream?.bits_per_raw_sample === 16 || stream?.bits_per_raw_sample === undefined)\n ) {\n // Already in correct format, just rename\n fs.renameSync(tempInputFile, tempWavFile);\n return tempWavFile;\n }\n } catch (probeError) {\n // If probe fails, continue with conversion\n logger.debug('FFprobe failed, continuing with conversion:', probeError);\n }\n }\n\n // Convert to WAV format\n await this.convertToWav(tempInputFile, tempWavFile);\n\n // Clean up the input file\n if (fs.existsSync(tempInputFile)) {\n fs.unlinkSync(tempInputFile);\n // logger.info(\"Temporary input file cleaned up\", {\n // path: tempInputFile,\n // timestamp: new Date().toISOString()\n // });\n }\n\n return tempWavFile;\n } catch (error) {\n logger.error('Audio preprocessing failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n ffmpegAvailable: this.ffmpegAvailable,\n timestamp: new Date().toISOString(),\n });\n throw new Error(\n `Failed to preprocess audio: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Transcribes the audio buffer to text using whisper.\n *\n * @param {Buffer} audioBuffer The audio buffer to transcribe.\n * @returns {Promise<TranscriptionResult>} A promise that resolves with the transcription result.\n * @throws {Error} If FFmpeg is not installed or properly configured.\n */\n\n public async transcribe(audioBuffer: Buffer): Promise<TranscriptionResult> {\n await this.ensureFFmpeg();\n\n if (!this.ffmpegAvailable) {\n throw new Error(\n 'FFmpeg is not installed or not properly configured. Please install FFmpeg to use audio transcription.'\n );\n }\n\n try {\n // Preprocess audio to WAV format\n const wavFile = await this.preprocessAudio(audioBuffer);\n\n logger.info('Starting transcription with whisper...');\n\n let segments;\n try {\n // Get the whisper function\n const whisper = await getWhisper();\n\n // Transcribe using whisper-node\n segments = await whisper(wavFile, {\n modelName: 'tiny',\n modelPath: path.join(this.cacheDir, 'models'), // Specify where to store models\n whisperOptions: {\n language: 'en',\n word_timestamps: false, // We don't need word-level timestamps\n },\n });\n } catch (whisperError) {\n // Check if it's a model download issue\n const errorMessage =\n whisperError instanceof Error ? whisperError.message : String(whisperError);\n if (errorMessage.includes('not found') || errorMessage.includes('download')) {\n logger.error('Whisper model not found. Please run: npx whisper-node download');\n throw new Error(\n 'Whisper model not found. Please install it with: npx whisper-node download'\n );\n }\n\n // For other errors, log and rethrow\n logger.error('Whisper transcription error:', whisperError);\n throw whisperError;\n }\n\n // Clean up temporary WAV file\n if (fs.existsSync(wavFile)) {\n fs.unlinkSync(wavFile);\n logger.info('Temporary WAV file cleaned up');\n }\n\n // Check if segments is valid\n if (!segments || !Array.isArray(segments)) {\n logger.warn('Whisper returned no segments (likely silence or very short audio)');\n // Return empty transcription for silent/empty audio\n return { text: '' };\n }\n\n // Handle empty segments array\n if (segments.length === 0) {\n logger.warn('No speech detected in audio');\n return { text: '' };\n }\n\n // Combine all segments into a single text\n const cleanText = segments\n .map((segment: any) => segment.speech?.trim() || '')\n .filter((text: string) => text) // Remove empty segments\n .join(' ');\n\n logger.success('Transcription complete:', {\n textLength: cleanText.length,\n segmentCount: segments.length,\n timestamp: new Date().toISOString(),\n });\n\n return { text: cleanText };\n } catch (error) {\n logger.error('Transcription failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n ffmpegAvailable: this.ffmpegAvailable,\n });\n throw error;\n }\n }\n}\n","import { logger } from '@elizaos/core';\nimport { pipeline, type TextToAudioPipeline } from '@huggingface/transformers';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fetch } from 'undici';\nimport { MODEL_SPECS } from '../types';\nimport { PassThrough, Readable } from 'node:stream';\n\n// Audio Utils\n\n/**\n * Generates a WAV file header based on the provided audio parameters.\n * @param {number} audioLength - The length of the audio data in bytes.\n * @param {number} sampleRate - The sample rate of the audio.\n * @param {number} [channelCount=1] - The number of channels (default is 1).\n * @param {number} [bitsPerSample=16] - The number of bits per sample (default is 16).\n * @returns {Buffer} The WAV file header as a Buffer object.\n */\nfunction getWavHeader(\n audioLength: number,\n sampleRate: number,\n channelCount = 1,\n bitsPerSample = 16\n): Buffer {\n const wavHeader = Buffer.alloc(44);\n wavHeader.write('RIFF', 0);\n wavHeader.writeUInt32LE(36 + audioLength, 4); // Length of entire file in bytes minus 8\n wavHeader.write('WAVE', 8);\n wavHeader.write('fmt ', 12);\n wavHeader.writeUInt32LE(16, 16); // Length of format data\n wavHeader.writeUInt16LE(1, 20); // Type of format (1 is PCM)\n wavHeader.writeUInt16LE(channelCount, 22); // Number of channels\n wavHeader.writeUInt32LE(sampleRate, 24); // Sample rate\n wavHeader.writeUInt32LE((sampleRate * bitsPerSample * channelCount) / 8, 28); // Byte rate\n wavHeader.writeUInt16LE((bitsPerSample * channelCount) / 8, 32); // Block align ((BitsPerSample * Channels) / 8)\n wavHeader.writeUInt16LE(bitsPerSample, 34); // Bits per sample\n wavHeader.write('data', 36); // Data chunk header\n wavHeader.writeUInt32LE(audioLength, 40); // Data chunk size\n return wavHeader;\n}\n\n/**\n * Prepends a WAV header to a readable stream of audio data.\n *\n * @param {Readable} readable - The readable stream containing the audio data.\n * @param {number} audioLength - The length of the audio data in bytes.\n * @param {number} sampleRate - The sample rate of the audio data.\n * @param {number} [channelCount=1] - The number of channels in the audio data (default is 1).\n * @param {number} [bitsPerSample=16] - The number of bits per sample in the audio data (default is 16).\n * @returns {PassThrough} A new pass-through stream with the WAV header prepended to the audio data.\n */\nfunction prependWavHeader(\n readable: Readable,\n audioLength: number,\n sampleRate: number,\n channelCount = 1,\n bitsPerSample = 16\n): PassThrough {\n const wavHeader = getWavHeader(audioLength, sampleRate, channelCount, bitsPerSample);\n let pushedHeader = false;\n const passThrough = new PassThrough();\n readable.on('data', (data: Buffer) => {\n if (!pushedHeader) {\n passThrough.push(wavHeader);\n pushedHeader = true;\n }\n passThrough.push(data);\n });\n readable.on('end', () => {\n passThrough.end();\n });\n return passThrough;\n}\n\n/**\n * Class representing a Text-to-Speech Manager using Transformers.js\n */\nexport class TTSManager {\n private static instance: TTSManager | null = null;\n private cacheDir: string;\n private synthesizer: TextToAudioPipeline | null = null;\n private defaultSpeakerEmbedding: Float32Array | null = null;\n private initialized = false;\n private initializingPromise: Promise<void> | null = null;\n\n private constructor(cacheDir: string) {\n this.cacheDir = path.join(cacheDir, 'tts');\n this.ensureCacheDirectory();\n logger.debug('TTSManager using Transformers.js initialized');\n }\n\n public static getInstance(cacheDir: string): TTSManager {\n if (!TTSManager.instance) {\n TTSManager.instance = new TTSManager(cacheDir);\n }\n return TTSManager.instance;\n }\n\n private ensureCacheDirectory(): void {\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n logger.debug('Created TTS cache directory:', this.cacheDir);\n }\n }\n\n private async initialize(): Promise<void> {\n // Guard against concurrent calls: if an initialization is already in progress, return its promise.\n if (this.initializingPromise) {\n logger.debug('TTS initialization already in progress, awaiting existing promise.');\n return this.initializingPromise;\n }\n\n // If already initialized, no need to do anything further.\n if (this.initialized) {\n logger.debug('TTS already initialized.');\n return;\n }\n\n // Start the initialization process.\n // The promise is stored in this.initializingPromise and cleared in the finally block.\n this.initializingPromise = (async () => {\n try {\n logger.info('Initializing TTS with Transformers.js backend...');\n\n const ttsModelSpec = MODEL_SPECS.tts.default;\n if (!ttsModelSpec) {\n throw new Error('Default TTS model specification not found in MODEL_SPECS.');\n }\n const modelName = ttsModelSpec.modelId;\n const speakerEmbeddingUrl = ttsModelSpec.defaultSpeakerEmbeddingUrl;\n\n // 1. Load the TTS Pipeline\n logger.info(`Loading TTS pipeline for model: ${modelName}`);\n this.synthesizer = await pipeline('text-to-audio', modelName);\n logger.success(`TTS pipeline loaded successfully for model: ${modelName}`);\n\n // 2. Load Default Speaker Embedding (if specified)\n if (speakerEmbeddingUrl) {\n const embeddingFilename = path.basename(new URL(speakerEmbeddingUrl).pathname);\n const embeddingPath = path.join(this.cacheDir, embeddingFilename);\n\n if (fs.existsSync(embeddingPath)) {\n logger.info('Loading default speaker embedding from cache...');\n const buffer = fs.readFileSync(embeddingPath);\n this.defaultSpeakerEmbedding = new Float32Array(\n buffer.buffer,\n buffer.byteOffset,\n buffer.length / Float32Array.BYTES_PER_ELEMENT\n );\n logger.success('Default speaker embedding loaded from cache.');\n } else {\n logger.info(`Downloading default speaker embedding from: ${speakerEmbeddingUrl}`);\n const response = await fetch(speakerEmbeddingUrl);\n if (!response.ok) {\n throw new Error(`Failed to download speaker embedding: ${response.statusText}`);\n }\n const buffer = await response.arrayBuffer();\n this.defaultSpeakerEmbedding = new Float32Array(buffer);\n fs.writeFileSync(embeddingPath, Buffer.from(buffer));\n logger.success('Default speaker embedding downloaded and cached.');\n }\n } else {\n logger.warn(\n `No default speaker embedding URL specified for model ${modelName}. Speaker control may be limited.`\n );\n this.defaultSpeakerEmbedding = null;\n }\n\n // Check synthesizer as embedding might be optional for some models\n if (!this.synthesizer) {\n throw new Error('TTS initialization failed: Pipeline not loaded.');\n }\n\n logger.success('TTS initialization complete (Transformers.js)');\n this.initialized = true;\n } catch (error) {\n logger.error('TTS (Transformers.js) initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n this.initialized = false;\n this.synthesizer = null;\n this.defaultSpeakerEmbedding = null;\n throw error; // Propagate error to reject the initializingPromise\n } finally {\n // Clear the promise once initialization is complete (successfully or not)\n this.initializingPromise = null;\n logger.debug('TTS initializingPromise cleared after completion/failure.');\n }\n })();\n\n return this.initializingPromise;\n }\n\n /**\n * Asynchronously generates speech from a given text using the Transformers.js pipeline.\n * @param {string} text - The text to generate speech from.\n * @returns {Promise<Readable>} A promise that resolves to a Readable stream containing the generated WAV audio data.\n * @throws {Error} If the TTS model is not initialized or if generation fails.\n */\n public async generateSpeech(text: string): Promise<Readable> {\n try {\n await this.initialize();\n\n // Check synthesizer is initialized (embedding might be null but handled in synthesizer call)\n if (!this.synthesizer) {\n throw new Error('TTS Manager not properly initialized.');\n }\n\n logger.info('Starting speech generation with Transformers.js for text:', {\n text: text.substring(0, 50) + '...',\n });\n\n // Generate audio using the pipeline\n const output = await this.synthesizer(text, {\n // Pass embedding only if it was loaded\n ...(this.defaultSpeakerEmbedding && {\n speaker_embeddings: this.defaultSpeakerEmbedding,\n }),\n });\n\n // output is { audio: Float32Array, sampling_rate: number }\n const audioFloat32 = output.audio;\n const samplingRate = output.sampling_rate;\n\n logger.info('Raw audio data received from pipeline:', {\n samplingRate,\n length: audioFloat32.length,\n });\n\n if (!audioFloat32 || audioFloat32.length === 0) {\n throw new Error('TTS pipeline generated empty audio output.');\n }\n\n // Convert Float32Array to Int16 Buffer (standard PCM for WAV)\n const pcmData = new Int16Array(audioFloat32.length);\n for (let i = 0; i < audioFloat32.length; i++) {\n const s = Math.max(-1, Math.min(1, audioFloat32[i])); // Clamp to [-1, 1]\n pcmData[i] = s < 0 ? s * 0x8000 : s * 0x7fff; // Convert to 16-bit [-32768, 32767]\n }\n const audioBuffer = Buffer.from(pcmData.buffer);\n\n logger.info('Audio data converted to 16-bit PCM Buffer:', {\n byteLength: audioBuffer.length,\n });\n\n // Create WAV format stream\n // Use samplingRate from the pipeline output\n const audioStream = prependWavHeader(\n Readable.from(audioBuffer),\n audioBuffer.length, // Pass buffer length in bytes\n samplingRate,\n 1, // Number of channels (assuming mono)\n 16 // Bit depth\n );\n\n logger.success('Speech generation complete (Transformers.js)');\n return audioStream;\n } catch (error) {\n logger.error('Transformers.js speech generation failed:', {\n error: error instanceof Error ? error.message : String(error),\n text: text.substring(0, 50) + '...',\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n }\n}\n","import { existsSync } from 'node:fs';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { logger } from '@elizaos/core';\nimport {\n AutoProcessor,\n AutoTokenizer,\n Florence2ForConditionalGeneration,\n type Florence2Processor,\n type PreTrainedTokenizer,\n type ProgressCallback,\n type ProgressInfo,\n RawImage,\n type Tensor,\n env,\n} from '@huggingface/transformers';\nimport { MODEL_SPECS } from '../types';\nimport { DownloadManager } from './downloadManager';\n\n// Define valid types based on HF transformers types\n/**\n * Defines the type 'DeviceType' which can take one of the three string values: 'cpu', 'gpu', or 'auto'\n */\ntype DeviceType = 'cpu' | 'gpu' | 'auto';\n/**\n * Represents the available data types options.\n */\ntype DTypeType = 'fp32' | 'fp16' | 'auto';\n\n/**\n * Interface for platform configuration options.\n * @typedef {Object} PlatformConfig\n * @property {DeviceType} device - The type of device to use.\n * @property {DTypeType} dtype - The data type to use.\n * @property {boolean} useOnnx - Flag indicating whether to use ONNX for processing.\n */\ninterface PlatformConfig {\n device: DeviceType;\n dtype: DTypeType;\n useOnnx: boolean;\n}\n\n/**\n * Represents a model component with a name, type, and optionally a data type.\n * @interface ModelComponent\n * @property { string } name - The name of the model component.\n * @property { string } type - The type of the model component.\n * @property { DTypeType } [dtype] - The data type of the model component (optional).\n */\ninterface ModelComponent {\n name: string;\n type: string;\n dtype?: DTypeType;\n}\n\n/**\n * Class representing a VisionManager.\n * @property {VisionManager | null} instance - The static instance of VisionManager.\n * @property {Florence2ForConditionalGeneration | null} model - The model for conditional generation.\n * @property {Florence2Processor | null} processor - The processor for Florence2.\n * @property {PreTrainedTokenizer | null} tokenizer - The pre-trained tokenizer.\n * @property {string} modelsDir - The directory for models.\n * @property {string} cacheDir - The directory for caching.\n * @property {boolean} initialized - Flag indicating if the VisionManager has been initialized.\n * @property {DownloadManager} downloadManager - The manager for downloading.\n */\nexport class VisionManager {\n private static instance: VisionManager | null = null;\n private model: Florence2ForConditionalGeneration | null = null;\n private processor: Florence2Processor | null = null;\n private tokenizer: PreTrainedTokenizer | null = null;\n private modelsDir: string;\n private cacheDir: string;\n private initialized = false;\n private downloadManager: DownloadManager;\n private modelDownloaded = false;\n private tokenizerDownloaded = false;\n private processorDownloaded = false;\n private platformConfig: PlatformConfig;\n private modelComponents: ModelComponent[] = [\n { name: 'embed_tokens', type: 'embeddings' },\n { name: 'vision_encoder', type: 'encoder' },\n { name: 'decoder_model_merged', type: 'decoder' },\n { name: 'encoder_model', type: 'encoder' },\n ];\n\n /**\n * Constructor for VisionManager class.\n *\n * @param {string} cacheDir - The directory path for caching vision models.\n */\n private constructor(cacheDir: string) {\n this.modelsDir = path.join(path.dirname(cacheDir), 'models', 'vision');\n this.cacheDir = cacheDir;\n this.ensureModelsDirExists();\n this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);\n this.platformConfig = this.getPlatformConfig();\n logger.debug('VisionManager initialized');\n }\n\n /**\n * Retrieves the platform configuration based on the operating system and architecture.\n * @returns {PlatformConfig} The platform configuration object with device, dtype, and useOnnx properties.\n */\n private getPlatformConfig(): PlatformConfig {\n const platform = os.platform();\n const arch = os.arch();\n\n // Default configuration\n let config: PlatformConfig = {\n device: 'cpu',\n dtype: 'fp32',\n useOnnx: true,\n };\n\n if (platform === 'darwin' && (arch === 'arm64' || arch === 'aarch64')) {\n // Apple Silicon\n config = {\n device: 'gpu',\n dtype: 'fp16',\n useOnnx: true,\n };\n } else if (platform === 'win32' || platform === 'linux') {\n // Windows or Linux with CUDA\n const hasCuda = process.env.CUDA_VISIBLE_DEVICES !== undefined;\n if (hasCuda) {\n config = {\n device: 'gpu',\n dtype: 'fp16',\n useOnnx: true,\n };\n }\n }\n return config;\n }\n\n /**\n * Ensures that the models directory exists. If it does not exist, it creates the directory.\n */\n private ensureModelsDirExists(): void {\n if (!existsSync(this.modelsDir)) {\n logger.debug(`Creating models directory at: ${this.modelsDir}`);\n fs.mkdirSync(this.modelsDir, { recursive: true });\n }\n }\n\n /**\n * Returns the singleton instance of VisionManager.\n * If an instance does not already exist, a new instance is created with the specified cache directory.\n *\n * @param {string} cacheDir - The directory where cache files will be stored.\n *\n * @returns {VisionManager} The singleton instance of VisionManager.\n */\n public static getInstance(cacheDir: string): VisionManager {\n if (!VisionManager.instance) {\n VisionManager.instance = new VisionManager(cacheDir);\n }\n return VisionManager.instance;\n }\n\n /**\n * Check if the cache exists for the specified model or tokenizer or processor.\n * @param {string} modelId - The ID of the model.\n * @param {\"model\" | \"tokenizer\" | \"processor\"} type - The type of the cache (\"model\", \"tokenizer\", or \"processor\").\n * @returns {boolean} - Returns true if cache exists, otherwise returns false.\n */\n private checkCacheExists(modelId: string, type: 'model' | 'tokenizer' | 'processor'): boolean {\n const modelPath = path.join(this.modelsDir, modelId.replace('/', '--'), type);\n if (existsSync(modelPath)) {\n logger.info(`${type} found at: ${modelPath}`);\n return true;\n }\n return false;\n }\n\n /**\n * Configures the model components based on the platform and architecture.\n * Sets the default data type (dtype) for components based on platform capabilities.\n * Updates all component dtypes to match the default dtype.\n */\n private configureModelComponents(): void {\n const platform = os.platform();\n const arch = os.arch();\n\n // Set dtype based on platform capabilities\n let defaultDtype: DTypeType = 'fp32';\n\n if (platform === 'darwin' && (arch === 'arm64' || arch === 'aarch64')) {\n // Apple Silicon can handle fp16\n defaultDtype = 'fp16';\n } else if (\n (platform === 'win32' || platform === 'linux') &&\n process.env.CUDA_VISIBLE_DEVICES !== undefined\n ) {\n // CUDA-enabled systems can handle fp16\n defaultDtype = 'fp16';\n }\n\n // Update all component dtypes\n this.modelComponents = this.modelComponents.map((component) => ({\n ...component,\n dtype: defaultDtype,\n }));\n\n logger.info('Model components configured with dtype:', {\n platform,\n arch,\n defaultDtype,\n components: this.modelComponents.map((c) => `${c.name}: ${c.dtype}`),\n });\n }\n\n /**\n * Get the model configuration based on the input component name.\n * @param {string} componentName - The name of the component to retrieve the configuration for.\n * @returns {object} The model configuration object containing device, dtype, and cache_dir.\n */\n private getModelConfig(componentName: string) {\n const component = this.modelComponents.find((c) => c.name === componentName);\n return {\n device: this.platformConfig.device,\n dtype: component?.dtype || 'fp32',\n cache_dir: this.modelsDir,\n };\n }\n\n /**\n * Asynchronous method to initialize the vision model by loading Florence2 model, vision tokenizer, and vision processor.\n *\n * @returns {Promise<void>} - Promise that resolves once the initialization process is completed.\n * @throws {Error} - If there is an error during the initialization process.\n */\n private async initialize() {\n try {\n if (this.initialized) {\n logger.info('Vision model already initialized, skipping initialization');\n return;\n }\n\n logger.info('Starting vision model initialization...');\n const modelSpec = MODEL_SPECS.vision;\n\n // Configure environment\n logger.info('Configuring environment for vision model...');\n env.allowLocalModels = true;\n env.allowRemoteModels = true;\n\n // Configure ONNX backend\n if (this.platformConfig.useOnnx) {\n env.backends.onnx.enabled = true;\n env.backends.onnx.logLevel = 'info';\n }\n\n // logger.info(\"Vision model configuration:\", {\n // modelId: modelSpec.modelId,\n // modelsDir: this.modelsDir,\n // allowLocalModels: env.allowLocalModels,\n // allowRemoteModels: env.allowRemoteModels,\n // platform: this.platformConfig\n // });\n\n // Initialize model with detailed logging\n logger.info('Loading Florence2 model...');\n try {\n let lastProgress = -1;\n const modelCached = this.checkCacheExists(modelSpec.modelId, 'model');\n\n const model = await Florence2ForConditionalGeneration.from_pretrained(modelSpec.modelId, {\n device: 'cpu',\n cache_dir: this.modelsDir,\n local_files_only: modelCached,\n revision: 'main',\n progress_callback: ((progressInfo: ProgressInfo) => {\n if (modelCached || this.modelDownloaded) return;\n const progress =\n 'progress' in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;\n const currentProgress = Math.round(progress * 100);\n if (currentProgress > lastProgress + 9 || currentProgress === 100) {\n lastProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor((currentProgress / 100) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(`Downloading vision model: ${progressBar} ${currentProgress}%`);\n if (currentProgress === 100) this.modelDownloaded = true;\n }\n }) as ProgressCallback,\n });\n\n this.model = model as unknown as Florence2ForConditionalGeneration;\n logger.success('Florence2 model loaded successfully');\n } catch (error) {\n logger.error('Failed to load Florence2 model:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelId: modelSpec.modelId,\n });\n throw error;\n }\n\n // Initialize tokenizer with detailed logging\n logger.info('Loading vision tokenizer...');\n try {\n const tokenizerCached = this.checkCacheExists(modelSpec.modelId, 'tokenizer');\n let tokenizerProgress = -1;\n\n this.tokenizer = await AutoTokenizer.from_pretrained(modelSpec.modelId, {\n cache_dir: this.modelsDir,\n local_files_only: tokenizerCached,\n progress_callback: ((progressInfo: ProgressInfo) => {\n if (tokenizerCached || this.tokenizerDownloaded) return;\n const progress =\n 'progress' in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;\n const currentProgress = Math.round(progress * 100);\n if (currentProgress !== tokenizerProgress) {\n tokenizerProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor((currentProgress / 100) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(`Downloading vision tokenizer: ${progressBar} ${currentProgress}%`);\n if (currentProgress === 100) this.tokenizerDownloaded = true;\n }\n }) as ProgressCallback,\n });\n logger.success('Vision tokenizer loaded successfully');\n } catch (error) {\n logger.error('Failed to load tokenizer:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelId: modelSpec.modelId,\n });\n throw error;\n }\n\n // Initialize processor with detailed logging\n logger.info('Loading vision processor...');\n try {\n const processorCached = this.checkCacheExists(modelSpec.modelId, 'processor');\n let processorProgress = -1;\n\n this.processor = (await AutoProcessor.from_pretrained(modelSpec.modelId, {\n device: 'cpu',\n cache_dir: this.modelsDir,\n local_files_only: processorCached,\n progress_callback: ((progressInfo: ProgressInfo) => {\n if (processorCached || this.processorDownloaded) return;\n const progress =\n 'progress' in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;\n const currentProgress = Math.round(progress * 100);\n if (currentProgress !== processorProgress) {\n processorProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor((currentProgress / 100) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(`Downloading vision processor: ${progressBar} ${currentProgress}%`);\n if (currentProgress === 100) this.processorDownloaded = true;\n }\n }) as ProgressCallback,\n })) as Florence2Processor;\n logger.success('Vision processor loaded successfully');\n } catch (error) {\n logger.error('Failed to load vision processor:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelId: modelSpec.modelId,\n });\n throw error;\n }\n\n this.initialized = true;\n logger.success('Vision model initialization complete');\n } catch (error) {\n logger.error('Vision model initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n\n /**\n * Fetches an image from a given URL and returns the image data as a Buffer along with its MIME type.\n *\n * @param {string} url - The URL of the image to fetch.\n * @returns {Promise<{ buffer: Buffer; mimeType: string }>} Object containing the image data as a Buffer and its MIME type.\n */\n private async fetchImage(url: string): Promise<{ buffer: Buffer; mimeType: string }> {\n try {\n logger.info(`Fetching image from URL: ${url.slice(0, 100)}...`);\n\n // Handle data URLs differently\n if (url.startsWith('data:')) {\n logger.info('Processing data URL...');\n const [header, base64Data] = url.split(',');\n const mimeType = header.split(';')[0].split(':')[1];\n const buffer = Buffer.from(base64Data, 'base64');\n logger.info('Data URL processed successfully');\n // logger.info(\"Data URL processed successfully:\", {\n // mimeType,\n // bufferSize: buffer.length\n // });\n return { buffer, mimeType };\n }\n\n // Handle regular URLs\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch image: ${response.statusText}`);\n }\n const buffer = Buffer.from(await response.arrayBuffer());\n const mimeType = response.headers.get('content-type') || 'image/jpeg';\n\n logger.info('Image fetched successfully:', {\n mimeType,\n bufferSize: buffer.length,\n status: response.status,\n });\n\n return { buffer, mimeType };\n } catch (error) {\n logger.error('Failed to fetch image:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n url,\n });\n throw error;\n }\n }\n\n /**\n * Processes the image from the provided URL using the initialized vision model components.\n * @param {string} imageUrl - The URL of the image to process.\n * @returns {Promise<{ title: string; description: string }>} An object containing the title and description of the processed image.\n */\n public async processImage(imageUrl: string): Promise<{ title: string; description: string }> {\n try {\n logger.info('Starting image processing...');\n\n // Ensure model is initialized\n if (!this.initialized) {\n logger.info('Vision model not initialized, initializing now...');\n await this.initialize();\n }\n\n if (!this.model || !this.processor || !this.tokenizer) {\n throw new Error('Vision model components not properly initialized');\n }\n\n // Fetch and process image\n logger.info('Fetching image...');\n const { buffer, mimeType } = await this.fetchImage(imageUrl);\n\n // Process image\n logger.info('Creating image blob...');\n const blob = new Blob([buffer], { type: mimeType });\n logger.info('Converting blob to RawImage...');\n // @ts-ignore - RawImage.fromBlob expects web Blob but works with node Blob\n const image = await RawImage.fromBlob(blob);\n\n logger.info('Processing image with vision processor...');\n const visionInputs = await this.processor(image);\n logger.info('Constructing prompts...');\n const prompts = this.processor.construct_prompts('<DETAILED_CAPTION>');\n logger.info('Tokenizing prompts...');\n const textInputs = this.tokenizer(prompts);\n\n // Generate description\n logger.info('Generating image description...');\n const generatedIds = (await this.model.generate({\n ...textInputs,\n ...visionInputs,\n max_new_tokens: MODEL_SPECS.vision.maxTokens,\n })) as Tensor;\n\n logger.info('Decoding generated text...');\n const generatedText = this.tokenizer.batch_decode(generatedIds, {\n skip_special_tokens: false,\n })[0];\n\n logger.info('Post-processing generation...');\n const result = this.processor.post_process_generation(\n generatedText,\n '<DETAILED_CAPTION>',\n image.size\n );\n\n const detailedCaption = result['<DETAILED_CAPTION>'] as string;\n const response = {\n title: `${detailedCaption.split('.')[0]}.`,\n description: detailedCaption,\n };\n\n logger.success('Image processing complete:', {\n titleLength: response.title.length,\n descriptionLength: response.description.length,\n });\n\n return response;\n } catch (error) {\n logger.error('Image processing failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n imageUrl,\n modelInitialized: this.initialized,\n hasModel: !!this.model,\n hasProcessor: !!this.processor,\n hasTokenizer: !!this.tokenizer,\n });\n throw error;\n }\n }\n}\n"],"mappings":"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","names":["fs","os","path","Readable","logger","logger","logger","logger","fs","exec","fs","path","promisify","logger","execAsync","logger","fs","path","fetch","path","logger","fs","fetch","fs","os","path","process","logger","AutoTokenizer","path","logger","os","process","fs","AutoTokenizer","mimeType","buffer","path","logger","os","fs","Readable"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/environment.ts","../src/types.ts","../src/utils/downloadManager.ts","../src/utils/platform.ts","../src/utils/tokenizerManager.ts","../src/utils/transcribeManager.ts","../src/utils/ttsManager.ts","../src/utils/visionManager.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\nimport type {\n GenerateTextParams,\n ModelTypeName,\n TextEmbeddingParams,\n ObjectGenerationParams,\n} from '@elizaos/core';\nimport { type IAgentRuntime, ModelType, type Plugin, logger } from '@elizaos/core';\nimport {\n type Llama,\n LlamaChatSession,\n type LlamaContext,\n type LlamaContextSequence,\n LlamaEmbeddingContext,\n type LlamaModel,\n getLlama,\n} from 'node-llama-cpp';\nimport { validateConfig, type Config } from './environment';\nimport { MODEL_SPECS, type ModelSpec, type EmbeddingModelSpec } from './types';\nimport { DownloadManager } from './utils/downloadManager';\nimport { getPlatformManager } from './utils/platform';\nimport { TokenizerManager } from './utils/tokenizerManager';\nimport { TranscribeManager } from './utils/transcribeManager';\nimport { TTSManager } from './utils/ttsManager';\nimport { VisionManager } from './utils/visionManager';\nimport { basename } from 'path';\n\n// Words to punish in LLM responses\n/**\n * Array containing words that should trigger a punishment when used in a message.\n * This array includes words like \"please\", \"feel\", \"free\", punctuation marks, and various topic-related words.\n * @type {string[]}\n */\nconst wordsToPunish = [\n ' please',\n ' feel',\n ' free',\n '!',\n '–',\n '—',\n '?',\n '.',\n ',',\n '; ',\n ' cosmos',\n ' tapestry',\n ' tapestries',\n ' glitch',\n ' matrix',\n ' cyberspace',\n ' troll',\n ' questions',\n ' topics',\n ' discuss',\n ' basically',\n ' simulation',\n ' simulate',\n ' universe',\n ' like',\n ' debug',\n ' debugging',\n ' wild',\n ' existential',\n ' juicy',\n ' circuits',\n ' help',\n ' ask',\n ' happy',\n ' just',\n ' cosmic',\n ' cool',\n ' joke',\n ' punchline',\n ' fancy',\n ' glad',\n ' assist',\n ' algorithm',\n ' Indeed',\n ' Furthermore',\n ' However',\n ' Notably',\n ' Therefore',\n];\n\n/**\n * Class representing a LocalAIManager.\n * @property {LocalAIManager | null} instance - The static instance of LocalAIManager.\n * @property {Llama | undefined} llama - The llama object.\n * @property {LlamaModel | undefined} smallModel - The small LlamaModel object.\n * @property {LlamaModel | undefined} mediumModel - The medium LlamaModel object.\n * @property {LlamaContext | undefined} ctx - The LlamaContext object.\n * @property {LlamaContextSequence | undefined} sequence - The LlamaContextSequence object.\n * @property {LlamaChatSession | undefined} chatSession - The LlamaChatSession object.\n * @property {string} modelPath - The path to the model.\n */\nclass LocalAIManager {\n private static instance: LocalAIManager | null = null;\n private llama: Llama | undefined;\n private smallModel: LlamaModel | undefined;\n private mediumModel: LlamaModel | undefined;\n private embeddingModel: LlamaModel | undefined;\n private embeddingContext: LlamaEmbeddingContext | undefined;\n private ctx: LlamaContext | undefined;\n private sequence: LlamaContextSequence | undefined;\n private chatSession: LlamaChatSession | undefined;\n private modelPath!: string;\n private mediumModelPath!: string;\n private embeddingModelPath!: string;\n private cacheDir!: string;\n private tokenizerManager!: TokenizerManager;\n private downloadManager!: DownloadManager;\n private visionManager!: VisionManager;\n private activeModelConfig: ModelSpec;\n private embeddingModelConfig: EmbeddingModelSpec;\n private transcribeManager!: TranscribeManager;\n private ttsManager!: TTSManager;\n private config: Config | null = null; // Store validated config\n\n // Initialization state flag\n private smallModelInitialized = false;\n private mediumModelInitialized = false;\n private embeddingInitialized = false;\n private visionInitialized = false;\n private transcriptionInitialized = false;\n private ttsInitialized = false;\n private environmentInitialized = false; // Add flag for environment initialization\n\n // Initialization promises to prevent duplicate initialization\n private smallModelInitializingPromise: Promise<void> | null = null;\n private mediumModelInitializingPromise: Promise<void> | null = null;\n private embeddingInitializingPromise: Promise<void> | null = null;\n private visionInitializingPromise: Promise<void> | null = null;\n private transcriptionInitializingPromise: Promise<void> | null = null;\n private ttsInitializingPromise: Promise<void> | null = null;\n private environmentInitializingPromise: Promise<void> | null = null; // Add promise for environment\n\n private modelsDir!: string;\n\n /**\n * Private constructor function to initialize base managers and paths.\n * Model paths are set after environment initialization.\n */\n private constructor() {\n this.config = validateConfig();\n\n this._setupCacheDir();\n\n // Initialize active model config (default)\n this.activeModelConfig = MODEL_SPECS.small;\n // Initialize embedding model config (spec details)\n this.embeddingModelConfig = MODEL_SPECS.embedding;\n }\n\n /**\n * Post-validation initialization steps that require config to be set.\n * Called after config validation in initializeEnvironment.\n */\n private _postValidateInit(): void {\n this._setupModelsDir();\n\n // Initialize managers that depend on modelsDir\n this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);\n this.tokenizerManager = TokenizerManager.getInstance(this.cacheDir, this.modelsDir);\n this.visionManager = VisionManager.getInstance(this.cacheDir);\n this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);\n this.ttsManager = TTSManager.getInstance(this.cacheDir);\n }\n\n /**\n * Sets up the models directory, reading from config or environment variables,\n * and ensures the directory exists.\n */\n private _setupModelsDir(): void {\n // Set up models directory consistently, similar to cacheDir\n const modelsDirEnv = this.config?.MODELS_DIR?.trim() || process.env.MODELS_DIR?.trim();\n if (modelsDirEnv) {\n this.modelsDir = path.resolve(modelsDirEnv);\n logger.info('Using models directory from MODELS_DIR environment variable:', this.modelsDir);\n } else {\n this.modelsDir = path.join(os.homedir(), '.eliza', 'models');\n logger.info(\n 'MODELS_DIR environment variable not set, using default models directory:',\n this.modelsDir\n );\n }\n\n // Ensure models directory exists\n if (!fs.existsSync(this.modelsDir)) {\n fs.mkdirSync(this.modelsDir, { recursive: true });\n logger.debug('Ensured models directory exists (created):', this.modelsDir);\n } else {\n logger.debug('Models directory already exists:', this.modelsDir);\n }\n }\n\n /**\n * Sets up the cache directory, reading from config or environment variables,\n * and ensures the directory exists.\n */\n private _setupCacheDir(): void {\n // Set up cache directory\n const cacheDirEnv = this.config?.CACHE_DIR?.trim() || process.env.CACHE_DIR?.trim();\n if (cacheDirEnv) {\n this.cacheDir = path.resolve(cacheDirEnv);\n logger.info('Using cache directory from CACHE_DIR environment variable:', this.cacheDir);\n } else {\n const cacheDir = path.join(os.homedir(), '.eliza', 'cache');\n // Ensure cache directory exists\n if (!fs.existsSync(cacheDir)) {\n fs.mkdirSync(cacheDir, { recursive: true });\n logger.debug('Ensuring cache directory exists (created):', cacheDir);\n }\n this.cacheDir = cacheDir;\n logger.info(\n 'CACHE_DIR environment variable not set, using default cache directory:',\n this.cacheDir\n );\n }\n // Ensure cache directory exists if specified via env var but not yet created\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n logger.debug('Ensured cache directory exists (created):', this.cacheDir);\n } else {\n logger.debug('Cache directory already exists:', this.cacheDir);\n }\n }\n\n /**\n * Retrieves the singleton instance of LocalAIManager. If an instance does not already exist, a new one is created and returned.\n * @returns {LocalAIManager} The singleton instance of LocalAIManager\n */\n public static getInstance(): LocalAIManager {\n if (!LocalAIManager.instance) {\n LocalAIManager.instance = new LocalAIManager();\n }\n return LocalAIManager.instance;\n }\n\n /**\n * Initializes the environment by validating the configuration and setting model paths.\n * Now public to be callable from plugin init and model handlers.\n *\n * @returns {Promise<void>} A Promise that resolves once the environment has been successfully initialized.\n */\n public async initializeEnvironment(): Promise<void> {\n // Prevent duplicate initialization\n if (this.environmentInitialized) return;\n if (this.environmentInitializingPromise) {\n await this.environmentInitializingPromise;\n return;\n }\n\n this.environmentInitializingPromise = (async () => {\n try {\n logger.info('Initializing environment configuration...');\n\n // Re-validate config to ensure it's up to date\n this.config = await validateConfig();\n\n // Initialize components that depend on validated config\n this._postValidateInit();\n\n // Set model paths based on validated config\n this.modelPath = path.join(this.modelsDir, this.config.LOCAL_SMALL_MODEL);\n this.mediumModelPath = path.join(this.modelsDir, this.config.LOCAL_LARGE_MODEL);\n this.embeddingModelPath = path.join(this.modelsDir, this.config.LOCAL_EMBEDDING_MODEL); // Set embedding path\n\n logger.info('Using small model path:', basename(this.modelPath));\n logger.info('Using medium model path:', basename(this.mediumModelPath));\n logger.info('Using embedding model path:', basename(this.embeddingModelPath));\n\n logger.info('Environment configuration validated and model paths set');\n\n this.environmentInitialized = true;\n logger.success('Environment initialization complete');\n } catch (error) {\n logger.error('Environment validation failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n this.environmentInitializingPromise = null; // Allow retry on failure\n throw error;\n }\n })();\n\n await this.environmentInitializingPromise;\n }\n\n /**\n * Downloads the model based on the modelPath provided.\n * Determines the model spec and path based on the model type.\n *\n * @param {ModelTypeName} modelType - The type of model to download\n * @param {ModelSpec} [customModelSpec] - Optional custom model spec to use instead of the default\n * @returns A Promise that resolves to a boolean indicating whether the model download was successful.\n */\n private async downloadModel(\n modelType: ModelTypeName,\n customModelSpec?: ModelSpec\n ): Promise<boolean> {\n let modelSpec: ModelSpec;\n let modelPathToDownload: string;\n\n // Ensure environment is initialized to have correct paths\n await this.initializeEnvironment();\n\n if (customModelSpec) {\n modelSpec = customModelSpec;\n // Use appropriate path based on model type, now read from instance properties\n modelPathToDownload =\n modelType === ModelType.TEXT_EMBEDDING\n ? this.embeddingModelPath\n : modelType === ModelType.TEXT_LARGE\n ? this.mediumModelPath\n : this.modelPath;\n } else if (modelType === ModelType.TEXT_EMBEDDING) {\n modelSpec = MODEL_SPECS.embedding;\n modelPathToDownload = this.embeddingModelPath; // Use configured path\n } else {\n modelSpec = modelType === ModelType.TEXT_LARGE ? MODEL_SPECS.medium : MODEL_SPECS.small;\n modelPathToDownload =\n modelType === ModelType.TEXT_LARGE ? this.mediumModelPath : this.modelPath; // Use configured path\n }\n\n try {\n // Pass the determined path to the download manager\n return await this.downloadManager.downloadModel(modelSpec, modelPathToDownload);\n } catch (error) {\n logger.error('Model download failed:', {\n error: error instanceof Error ? error.message : String(error),\n modelType,\n modelPath: modelPathToDownload,\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously checks the platform capabilities.\n *\n * @returns {Promise<void>} A promise that resolves once the platform capabilities have been checked.\n */\n public async checkPlatformCapabilities(): Promise<void> {\n try {\n const platformManager = getPlatformManager();\n await platformManager.initialize();\n const capabilities = platformManager.getCapabilities();\n\n logger.info('Platform capabilities detected:', {\n platform: capabilities.platform,\n gpu: capabilities.gpu?.type || 'none',\n recommendedModel: capabilities.recommendedModelSize,\n supportedBackends: capabilities.supportedBackends,\n });\n } catch (error) {\n logger.warn('Platform detection failed:', error);\n }\n }\n\n /**\n * Initializes the LocalAI Manager for a given model type.\n *\n * @param {ModelTypeName} modelType - The type of model to initialize (default: ModelType.TEXT_SMALL)\n * @returns {Promise<void>} A promise that resolves when initialization is complete or rejects if an error occurs\n */\n async initialize(modelType: ModelTypeName = ModelType.TEXT_SMALL): Promise<void> {\n await this.initializeEnvironment(); // Ensure environment is initialized first\n if (modelType === ModelType.TEXT_LARGE) {\n await this.lazyInitMediumModel();\n } else {\n await this.lazyInitSmallModel();\n }\n }\n\n /**\n * Asynchronously initializes the embedding model.\n *\n * @returns {Promise<void>} A promise that resolves once the initialization is complete.\n */\n public async initializeEmbedding(): Promise<void> {\n try {\n await this.initializeEnvironment(); // Ensure environment/paths are ready\n logger.info('Initializing embedding model...');\n logger.info('Models directory:', this.modelsDir);\n\n // Ensure models directory exists\n if (!fs.existsSync(this.modelsDir)) {\n logger.warn('Models directory does not exist, creating it:', this.modelsDir);\n fs.mkdirSync(this.modelsDir, { recursive: true });\n }\n\n // Download the embedding model using the common downloadModel function\n // This will now use the correct embeddingModelPath\n await this.downloadModel(ModelType.TEXT_EMBEDDING);\n\n // Initialize the llama instance if not already done\n if (!this.llama) {\n this.llama = await getLlama();\n }\n\n // Load the embedding model\n if (!this.embeddingModel) {\n logger.info('Loading embedding model:', this.embeddingModelPath); // Use the correct path\n\n this.embeddingModel = await this.llama.loadModel({\n modelPath: this.embeddingModelPath, // Use the correct path\n gpuLayers: 0, // Embedding models are typically small enough to run on CPU\n vocabOnly: false,\n });\n\n // Create context for embeddings\n this.embeddingContext = await this.embeddingModel.createEmbeddingContext({\n contextSize: this.embeddingModelConfig.contextSize,\n batchSize: 512,\n });\n\n logger.success('Embedding model initialized successfully');\n }\n } catch (error) {\n logger.error('Embedding initialization failed with details:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelsDir: this.modelsDir,\n embeddingModelPath: this.embeddingModelPath, // Log the path being used\n });\n throw error;\n }\n }\n\n /**\n * Generate embeddings using the proper LlamaContext.getEmbedding method.\n */\n async generateEmbedding(text: string): Promise<number[]> {\n try {\n // Lazy initialize embedding model\n await this.lazyInitEmbedding();\n\n if (!this.embeddingModel || !this.embeddingContext) {\n throw new Error('Failed to initialize embedding model');\n }\n\n logger.info('Generating embedding for text', { textLength: text.length });\n\n // Use the native getEmbedding method\n const embeddingResult = await this.embeddingContext.getEmbeddingFor(text);\n\n // Convert readonly array to mutable array\n const mutableEmbedding = [...embeddingResult.vector];\n\n // Normalize the embedding if needed (may already be normalized)\n const normalizedEmbedding = this.normalizeEmbedding(mutableEmbedding);\n\n logger.info('Embedding generation complete', {\n dimensions: normalizedEmbedding.length,\n });\n return normalizedEmbedding;\n } catch (error) {\n logger.error('Embedding generation failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n textLength: text?.length ?? 'text is null',\n });\n\n // Return zero vector with correct dimensions as fallback\n const zeroDimensions = this.config?.LOCAL_EMBEDDING_DIMENSIONS // Use validated config\n ? this.config.LOCAL_EMBEDDING_DIMENSIONS\n : this.embeddingModelConfig.dimensions;\n\n return new Array(zeroDimensions).fill(0);\n }\n }\n\n /**\n * Normalizes an embedding vector using L2 normalization\n *\n * @param {number[]} embedding - The embedding vector to normalize\n * @returns {number[]} - The normalized embedding vector\n */\n private normalizeEmbedding(embedding: number[]): number[] {\n // Calculate the L2 norm (Euclidean norm)\n const squareSum = embedding.reduce((sum, val) => sum + val * val, 0);\n const norm = Math.sqrt(squareSum);\n\n // Avoid division by zero\n if (norm === 0) {\n return embedding;\n }\n\n // Normalize each component\n return embedding.map((val) => val / norm);\n }\n\n /**\n * Lazy initialize the embedding model\n */\n private async lazyInitEmbedding(): Promise<void> {\n if (this.embeddingInitialized) return;\n\n if (!this.embeddingInitializingPromise) {\n this.embeddingInitializingPromise = (async () => {\n try {\n // Ensure environment is initialized first to get correct paths\n await this.initializeEnvironment();\n\n // Download model if needed (uses the correct path now)\n await this.downloadModel(ModelType.TEXT_EMBEDDING);\n\n // Initialize the llama instance if not already done\n if (!this.llama) {\n this.llama = await getLlama();\n }\n\n // Load the embedding model (uses the correct path)\n this.embeddingModel = await this.llama.loadModel({\n modelPath: this.embeddingModelPath,\n gpuLayers: 0, // Embedding models are typically small enough to run on CPU\n vocabOnly: false,\n });\n\n // Create context for embeddings\n this.embeddingContext = await this.embeddingModel.createEmbeddingContext({\n contextSize: this.embeddingModelConfig.contextSize,\n batchSize: 512,\n });\n\n this.embeddingInitialized = true;\n logger.info('Embedding model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize embedding model:', error);\n this.embeddingInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.embeddingInitializingPromise;\n }\n\n /**\n * Asynchronously generates text based on the provided parameters.\n * Now uses lazy initialization for models\n */\n async generateText(params: GenerateTextParams): Promise<string> {\n try {\n // Call LlamaContext.dispose() to free GPU memory.\n if(this.ctx){\n this.ctx.dispose();\n this.ctx = undefined;\n }\n await this.initializeEnvironment(); // Ensure environment is initialized\n logger.info('Generating text with model:', params.modelType);\n // Lazy initialize the appropriate model\n if (params.modelType === ModelType.TEXT_LARGE) {\n await this.lazyInitMediumModel();\n\n if (!this.mediumModel) {\n throw new Error('Medium model initialization failed');\n }\n\n this.activeModelConfig = MODEL_SPECS.medium;\n const mediumModel = this.mediumModel;\n\n // Create fresh context\n this.ctx = await mediumModel.createContext({\n contextSize: MODEL_SPECS.medium.contextSize,\n });\n } else {\n await this.lazyInitSmallModel();\n\n if (!this.smallModel) {\n throw new Error('Small model initialization failed');\n }\n\n this.activeModelConfig = MODEL_SPECS.small;\n const smallModel = this.smallModel;\n\n // Create fresh context\n this.ctx = await smallModel.createContext({\n contextSize: MODEL_SPECS.small.contextSize,\n });\n }\n\n if (!this.ctx) {\n throw new Error('Failed to create prompt');\n }\n\n // QUICK TEST FIX: Always get fresh sequence\n this.sequence = this.ctx.getSequence();\n\n // QUICK TEST FIX: Create new session each time without maintaining state\n // Only use valid options for LlamaChatSession\n this.chatSession = new LlamaChatSession({\n contextSequence: this.sequence,\n });\n\n if (!this.chatSession) {\n throw new Error('Failed to create chat session');\n }\n logger.info('Created new chat session for model:', params.modelType);\n // Log incoming prompt for debugging\n logger.info('Incoming prompt structure:', {\n contextLength: params.prompt.length,\n hasAction: params.prompt.includes('action'),\n runtime: !!params.runtime,\n stopSequences: params.stopSequences,\n });\n\n const tokens = await this.tokenizerManager.encode(params.prompt, this.activeModelConfig);\n logger.info('Input tokens:', { count: tokens.length });\n\n // QUICK TEST FIX: Add system message to reset prompt\n const systemMessage = 'You are a helpful AI assistant. Respond to the current request only.';\n await this.chatSession.prompt(systemMessage, {\n maxTokens: 1, // Minimal tokens for system message\n temperature: 0.0,\n });\n\n let response = await this.chatSession.prompt(params.prompt, {\n maxTokens: 8192,\n temperature: 0.7,\n topP: 0.9,\n repeatPenalty: {\n punishTokensFilter: () =>\n this.smallModel ? this.smallModel.tokenize(wordsToPunish.join(' ')) : [],\n penalty: 1.2,\n frequencyPenalty: 0.7,\n presencePenalty: 0.7,\n },\n });\n\n // Log raw response for debugging\n logger.info('Raw response structure:', {\n responseLength: response.length,\n hasAction: response.includes('action'),\n hasThinkTag: response.includes('<think>'),\n });\n\n // Clean think tags if present\n if (response.includes('<think>')) {\n logger.info('Cleaning think tags from response');\n response = response.replace(/<think>[\\s\\S]*?<\\/think>\\n?/g, '');\n logger.info('Think tags removed from response');\n }\n\n // Return the raw response and let the framework handle JSON parsing and action validation\n return response;\n } catch (error) {\n logger.error('Text generation failed:', error);\n throw error;\n }\n }\n\n /**\n * Describe image with lazy vision model initialization\n */\n public async describeImage(\n imageData: Buffer,\n mimeType: string\n ): Promise<{ title: string; description: string }> {\n try {\n // Lazy initialize vision model\n await this.lazyInitVision();\n\n // Convert buffer to data URL\n const base64 = imageData.toString('base64');\n const dataUrl = `data:${mimeType};base64,${base64}`;\n return await this.visionManager.processImage(dataUrl);\n } catch (error) {\n logger.error('Image description failed:', error);\n throw error;\n }\n }\n\n /**\n * Transcribe audio with lazy transcription model initialization\n */\n public async transcribeAudio(audioBuffer: Buffer): Promise<string> {\n try {\n // Lazy initialize transcription model\n await this.lazyInitTranscription();\n\n const result = await this.transcribeManager.transcribe(audioBuffer);\n return result.text;\n } catch (error) {\n logger.error('Audio transcription failed:', {\n error: error instanceof Error ? error.message : String(error),\n bufferSize: audioBuffer.length,\n });\n throw error;\n }\n }\n\n /**\n * Generate speech with lazy TTS model initialization\n */\n public async generateSpeech(text: string): Promise<Readable> {\n try {\n // Lazy initialize TTS model\n await this.lazyInitTTS();\n\n return await this.ttsManager.generateSpeech(text);\n } catch (error) {\n logger.error('Speech generation failed:', {\n error: error instanceof Error ? error.message : String(error),\n textLength: text.length,\n });\n throw error;\n }\n }\n\n /**\n * Returns the TokenizerManager associated with this object.\n *\n * @returns {TokenizerManager} The TokenizerManager object.\n */\n public getTokenizerManager(): TokenizerManager {\n return this.tokenizerManager;\n }\n\n /**\n * Returns the active model configuration.\n * @returns {ModelSpec} The active model configuration.\n */\n public getActiveModelConfig(): ModelSpec {\n return this.activeModelConfig;\n }\n\n /**\n * Lazy initialize the small text model\n */\n private async lazyInitSmallModel(): Promise<void> {\n if (this.smallModelInitialized) return;\n\n if (!this.smallModelInitializingPromise) {\n this.smallModelInitializingPromise = (async () => {\n await this.initializeEnvironment(); // Ensure environment is initialized first\n await this.checkPlatformCapabilities();\n\n // Download model if needed\n // Pass the correct model path determined during environment init\n await this.downloadModel(ModelType.TEXT_SMALL);\n\n // Initialize Llama and small model\n try {\n // Use getLlama helper instead of directly creating\n this.llama = await getLlama();\n\n const smallModel = await this.llama.loadModel({\n gpuLayers: 43,\n modelPath: this.modelPath, // Use the potentially overridden path\n vocabOnly: false,\n });\n\n this.smallModel = smallModel;\n\n const ctx = await smallModel.createContext({\n contextSize: MODEL_SPECS.small.contextSize,\n });\n\n this.ctx = ctx;\n this.sequence = undefined; // Reset sequence to create a new one\n this.smallModelInitialized = true;\n logger.info('Small model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize small model:', error);\n this.smallModelInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.smallModelInitializingPromise;\n }\n\n /**\n * Lazy initialize the medium text model\n */\n private async lazyInitMediumModel(): Promise<void> {\n if (this.mediumModelInitialized) return;\n\n if (!this.mediumModelInitializingPromise) {\n this.mediumModelInitializingPromise = (async () => {\n await this.initializeEnvironment(); // Ensure environment is initialized first\n // Make sure llama is initialized first (implicitly done by small model init if needed)\n if (!this.llama) {\n // Attempt to initialize small model first to get llama instance\n // This might download the small model even if only medium is requested,\n // but ensures llama is ready.\n await this.lazyInitSmallModel();\n }\n\n // Download model if needed\n // Pass the correct model path determined during environment init\n await this.downloadModel(ModelType.TEXT_LARGE);\n\n // Initialize medium model\n try {\n const mediumModel = await this.llama!.loadModel({\n gpuLayers: 43,\n modelPath: this.mediumModelPath, // Use the potentially overridden path\n vocabOnly: false,\n });\n\n this.mediumModel = mediumModel;\n this.mediumModelInitialized = true;\n logger.info('Medium model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize medium model:', error);\n this.mediumModelInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.mediumModelInitializingPromise;\n }\n\n /**\n * Lazy initialize the vision model\n */\n private async lazyInitVision(): Promise<void> {\n if (this.visionInitialized) return;\n\n if (!this.visionInitializingPromise) {\n this.visionInitializingPromise = (async () => {\n try {\n // Initialize vision model directly\n // Use existing initialization code from the file\n // ...\n this.visionInitialized = true;\n logger.info('Vision model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize vision model:', error);\n this.visionInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.visionInitializingPromise;\n }\n\n /**\n * Lazy initialize the transcription model\n */\n private async lazyInitTranscription(): Promise<void> {\n if (this.transcriptionInitialized) return;\n\n if (!this.transcriptionInitializingPromise) {\n this.transcriptionInitializingPromise = (async () => {\n try {\n // Ensure environment is initialized first\n await this.initializeEnvironment();\n\n // Initialize TranscribeManager if not already done\n if (!this.transcribeManager) {\n this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);\n }\n\n // Ensure FFmpeg is available\n const ffmpegReady = await this.transcribeManager.ensureFFmpeg();\n if (!ffmpegReady) {\n // FFmpeg is not available, log instructions and throw\n // The TranscribeManager's ensureFFmpeg or initializeFFmpeg would have already logged instructions.\n logger.error(\n 'FFmpeg is not available or not configured correctly. Cannot proceed with transcription.'\n );\n // No need to call logFFmpegInstallInstructions here as ensureFFmpeg/initializeFFmpeg already does.\n throw new Error(\n 'FFmpeg is required for transcription but is not available. Please see server logs for installation instructions.'\n );\n }\n\n // Proceed with transcription model initialization if FFmpeg is ready\n // (Assuming TranscribeManager handles its own specific model init if any,\n // or that nodewhisper handles it internally)\n this.transcriptionInitialized = true;\n logger.info('Transcription prerequisites (FFmpeg) checked and ready.');\n logger.info('Transcription model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize transcription model:', error);\n this.transcriptionInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.transcriptionInitializingPromise;\n }\n\n /**\n * Lazy initialize the TTS model\n */\n private async lazyInitTTS(): Promise<void> {\n if (this.ttsInitialized) return;\n\n if (!this.ttsInitializingPromise) {\n this.ttsInitializingPromise = (async () => {\n try {\n // Initialize TTS model directly\n // Use existing initialization code from the file\n // Get the TTSManager instance (ensure environment is initialized for cacheDir)\n await this.initializeEnvironment();\n this.ttsManager = TTSManager.getInstance(this.cacheDir);\n // Note: The internal pipeline initialization within TTSManager happens\n // when generateSpeech calls its own initialize method.\n this.ttsInitialized = true;\n logger.info('TTS model initialized successfully');\n } catch (error) {\n logger.error('Failed to lazy initialize TTS components:', error);\n this.ttsInitializingPromise = null; // Allow retry\n throw error;\n }\n })();\n }\n\n await this.ttsInitializingPromise;\n }\n}\n\n// Create manager instance\nconst localAIManager = LocalAIManager.getInstance();\n\n/**\n * Plugin that provides functionality for local AI using LLaMA models.\n * @type {Plugin}\n */\nexport const localAiPlugin: Plugin = {\n name: 'local-ai',\n description: 'Local AI plugin using LLaMA models',\n\n async init(_config: any, runtime: IAgentRuntime) {\n logger.info('🚀 Initializing Local AI plugin...');\n \n try {\n // Initialize environment and validate configuration\n await localAIManager.initializeEnvironment();\n const config = validateConfig();\n \n // Check for critical configuration\n if (!config.LOCAL_SMALL_MODEL || !config.LOCAL_LARGE_MODEL || !config.LOCAL_EMBEDDING_MODEL) {\n logger.warn('⚠️ Local AI plugin: Model configuration is incomplete');\n logger.warn('Please ensure the following environment variables are set:');\n logger.warn('- LOCAL_SMALL_MODEL: Path to small language model file');\n logger.warn('- LOCAL_LARGE_MODEL: Path to large language model file');\n logger.warn('- LOCAL_EMBEDDING_MODEL: Path to embedding model file');\n logger.warn('Example: LOCAL_SMALL_MODEL=llama-3.2-1b-instruct-q8_0.gguf');\n }\n \n // Check if models directory is accessible\n const modelsDir = config.MODELS_DIR || path.join(os.homedir(), '.eliza', 'models');\n if (!fs.existsSync(modelsDir)) {\n logger.warn(`⚠️ Models directory does not exist: ${modelsDir}`);\n logger.warn('The directory will be created, but you need to download model files');\n logger.warn('Visit https://huggingface.co/models to download compatible GGUF models');\n }\n \n // Perform a basic initialization test\n logger.info('🔍 Testing Local AI initialization...');\n \n try {\n // Check platform capabilities\n await localAIManager.checkPlatformCapabilities();\n \n // Test if we can get the llama instance\n const llamaInstance = await getLlama();\n if (llamaInstance) {\n logger.success('✅ Local AI: llama.cpp library loaded successfully');\n } else {\n throw new Error('Failed to load llama.cpp library');\n }\n \n // Check if at least one model file exists\n const smallModelPath = path.join(modelsDir, config.LOCAL_SMALL_MODEL);\n const largeModelPath = path.join(modelsDir, config.LOCAL_LARGE_MODEL);\n const embeddingModelPath = path.join(modelsDir, config.LOCAL_EMBEDDING_MODEL);\n \n const modelsExist = {\n small: fs.existsSync(smallModelPath),\n large: fs.existsSync(largeModelPath),\n embedding: fs.existsSync(embeddingModelPath)\n };\n \n if (!modelsExist.small && !modelsExist.large && !modelsExist.embedding) {\n logger.warn('⚠️ No model files found in models directory');\n logger.warn('Models will be downloaded on first use, which may take time');\n logger.warn('To pre-download models, run the plugin and it will fetch them automatically');\n } else {\n logger.info('📦 Found model files:', {\n small: modelsExist.small ? '✓' : '✗',\n large: modelsExist.large ? '✓' : '✗',\n embedding: modelsExist.embedding ? '✓' : '✗'\n });\n }\n \n logger.success('✅ Local AI plugin initialized successfully');\n logger.info('💡 Models will be loaded on-demand when first used');\n \n } catch (testError) {\n logger.error('❌ Local AI initialization test failed:', testError);\n logger.warn('The plugin may not function correctly');\n logger.warn('Please check:');\n logger.warn('1. Your system has sufficient memory (8GB+ recommended)');\n logger.warn('2. C++ build tools are installed (for node-llama-cpp)');\n logger.warn('3. Your CPU supports the required instruction sets');\n // Don't throw here - allow the plugin to load even if the test fails\n }\n \n } catch (error) {\n logger.error('❌ Failed to initialize Local AI plugin:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n \n // Provide helpful guidance based on common errors\n if (error instanceof Error) {\n if (error.message.includes('Cannot find module')) {\n logger.error('📚 Missing dependencies detected');\n logger.error('Please run: npm install or bun install');\n } else if (error.message.includes('node-llama-cpp')) {\n logger.error('🔧 node-llama-cpp build issue detected');\n logger.error('Please ensure C++ build tools are installed:');\n logger.error('- Windows: Install Visual Studio Build Tools');\n logger.error('- macOS: Install Xcode Command Line Tools');\n logger.error('- Linux: Install build-essential package');\n }\n }\n \n // Don't throw - allow the system to continue without this plugin\n logger.warn('⚠️ Local AI plugin will not be available');\n }\n },\n models: {\n [ModelType.TEXT_SMALL]: async (\n runtime: IAgentRuntime,\n { prompt, stopSequences = [] }: GenerateTextParams\n ) => {\n try {\n // Ensure environment is initialized before generating text (now public)\n await localAIManager.initializeEnvironment();\n return await localAIManager.generateText({\n prompt,\n stopSequences,\n runtime,\n modelType: ModelType.TEXT_SMALL,\n });\n } catch (error) {\n logger.error('Error in TEXT_SMALL handler:', error);\n throw error;\n }\n },\n\n [ModelType.TEXT_LARGE]: async (\n runtime: IAgentRuntime,\n { prompt, stopSequences = [] }: GenerateTextParams\n ) => {\n try {\n // Ensure environment is initialized before generating text (now public)\n await localAIManager.initializeEnvironment();\n return await localAIManager.generateText({\n prompt,\n stopSequences,\n runtime,\n modelType: ModelType.TEXT_LARGE,\n });\n } catch (error) {\n logger.error('Error in TEXT_LARGE handler:', error);\n throw error;\n }\n },\n\n [ModelType.TEXT_EMBEDDING]: async (_runtime: IAgentRuntime, params: TextEmbeddingParams) => {\n const text = params?.text;\n try {\n // Handle null/undefined/empty text\n if (!text) {\n logger.debug('Null or empty text input for embedding, returning zero vector');\n return new Array(384).fill(0);\n }\n\n // Pass the raw text directly to the framework without any manipulation\n return await localAIManager.generateEmbedding(text);\n } catch (error) {\n logger.error('Error in TEXT_EMBEDDING handler:', {\n error: error instanceof Error ? error.message : String(error),\n fullText: text,\n textType: typeof text,\n textStructure: text !== null ? JSON.stringify(text, null, 2) : 'null',\n });\n return new Array(384).fill(0);\n }\n },\n\n [ModelType.OBJECT_SMALL]: async (runtime: IAgentRuntime, params: ObjectGenerationParams) => {\n try {\n // Ensure environment is initialized (now public)\n await localAIManager.initializeEnvironment();\n logger.info('OBJECT_SMALL handler - Processing request:', {\n prompt: params.prompt,\n hasSchema: !!params.schema,\n temperature: params.temperature,\n });\n\n // Enhance the prompt to request JSON output\n let jsonPrompt = params.prompt;\n if (!jsonPrompt.includes('```json') && !jsonPrompt.includes('respond with valid JSON')) {\n jsonPrompt +=\n '\\nPlease respond with valid JSON only, without any explanations, markdown formatting, or additional text.';\n }\n\n // Directly generate text using the local small model\n const textResponse = await localAIManager.generateText({\n prompt: jsonPrompt,\n stopSequences: params.stopSequences,\n runtime,\n modelType: ModelType.TEXT_SMALL,\n });\n\n // Extract and parse JSON from the text response\n try {\n // Function to extract JSON content from text\n const extractJSON = (text: string): string => {\n // Try to find content between JSON codeblocks or markdown blocks\n const jsonBlockRegex = /```(?:json)?\\s*([\\s\\S]*?)\\s*```/;\n const match = text.match(jsonBlockRegex);\n\n if (match && match[1]) {\n return match[1].trim();\n }\n\n // If no code blocks, try to find JSON-like content\n // This regex looks for content that starts with { and ends with }\n const jsonContentRegex = /\\s*(\\{[\\s\\S]*\\})\\s*$/;\n const contentMatch = text.match(jsonContentRegex);\n\n if (contentMatch && contentMatch[1]) {\n return contentMatch[1].trim();\n }\n\n // If no JSON-like content found, return the original text\n return text.trim();\n };\n\n const extractedJsonText = extractJSON(textResponse);\n logger.debug('Extracted JSON text:', extractedJsonText);\n\n let jsonObject;\n try {\n jsonObject = JSON.parse(extractedJsonText);\n } catch (parseError) {\n // Try fixing common JSON issues\n logger.debug('Initial JSON parse failed, attempting to fix common issues');\n\n // Replace any unescaped newlines in string values\n const fixedJson = extractedJsonText\n .replace(/:\\s*\"([^\"]*)(?:\\n)([^\"]*)\"/g, ': \"$1\\\\n$2\"')\n // Remove any non-JSON text that might have gotten mixed into string values\n .replace(/\"([^\"]*?)[^a-zA-Z0-9\\s\\.,;:\\-_\\(\\)\"'\\[\\]{}]([^\"]*?)\"/g, '\"$1$2\"')\n // Fix missing quotes around property names\n .replace(/(\\s*)(\\w+)(\\s*):/g, '$1\"$2\"$3:')\n // Fix trailing commas in arrays and objects\n .replace(/,(\\s*[\\]}])/g, '$1');\n\n try {\n jsonObject = JSON.parse(fixedJson);\n } catch (finalError) {\n logger.error('Failed to parse JSON after fixing:', finalError);\n throw new Error('Invalid JSON returned from model');\n }\n }\n\n // Validate against schema if provided\n if (params.schema) {\n try {\n // Simplistic schema validation - check if all required properties exist\n for (const key of Object.keys(params.schema)) {\n if (!(key in jsonObject)) {\n jsonObject[key] = null; // Add missing properties with null value\n }\n }\n } catch (schemaError) {\n logger.error('Schema validation failed:', schemaError);\n }\n }\n\n return jsonObject;\n } catch (parseError) {\n logger.error('Failed to parse JSON:', parseError);\n logger.error('Raw response:', textResponse);\n throw new Error('Invalid JSON returned from model');\n }\n } catch (error) {\n logger.error('Error in OBJECT_SMALL handler:', error);\n throw error;\n }\n },\n\n [ModelType.OBJECT_LARGE]: async (runtime: IAgentRuntime, params: ObjectGenerationParams) => {\n try {\n // Ensure environment is initialized (now public)\n await localAIManager.initializeEnvironment();\n logger.info('OBJECT_LARGE handler - Processing request:', {\n prompt: params.prompt,\n hasSchema: !!params.schema,\n temperature: params.temperature,\n });\n\n // Enhance the prompt to request JSON output\n let jsonPrompt = params.prompt;\n if (!jsonPrompt.includes('```json') && !jsonPrompt.includes('respond with valid JSON')) {\n jsonPrompt +=\n '\\nPlease respond with valid JSON only, without any explanations, markdown formatting, or additional text.';\n }\n\n // Directly generate text using the local large model\n const textResponse = await localAIManager.generateText({\n prompt: jsonPrompt,\n stopSequences: params.stopSequences,\n runtime,\n modelType: ModelType.TEXT_LARGE,\n });\n\n // Extract and parse JSON from the text response\n try {\n // Function to extract JSON content from text\n const extractJSON = (text: string): string => {\n // Try to find content between JSON codeblocks or markdown blocks\n const jsonBlockRegex = /```(?:json)?\\s*([\\s\\S]*?)\\s*```/;\n const match = text.match(jsonBlockRegex);\n\n if (match && match[1]) {\n return match[1].trim();\n }\n\n // If no code blocks, try to find JSON-like content\n // This regex looks for content that starts with { and ends with }\n const jsonContentRegex = /\\s*(\\{[\\s\\S]*\\})\\s*$/;\n const contentMatch = text.match(jsonContentRegex);\n\n if (contentMatch && contentMatch[1]) {\n return contentMatch[1].trim();\n }\n\n // If no JSON-like content found, return the original text\n return text.trim();\n };\n\n // Clean up the extracted JSON to handle common formatting issues\n const cleanupJSON = (jsonText: string): string => {\n // Remove common logging/debugging patterns that might get mixed into the JSON\n return (\n jsonText\n // Remove any lines that look like log statements\n .replace(/\\[DEBUG\\].*?(\\n|$)/g, '\\n')\n .replace(/\\[LOG\\].*?(\\n|$)/g, '\\n')\n .replace(/console\\.log.*?(\\n|$)/g, '\\n')\n );\n };\n\n const extractedJsonText = extractJSON(textResponse);\n const cleanedJsonText = cleanupJSON(extractedJsonText);\n logger.debug('Extracted JSON text:', cleanedJsonText);\n\n let jsonObject;\n try {\n jsonObject = JSON.parse(cleanedJsonText);\n } catch (parseError) {\n // Try fixing common JSON issues\n logger.debug('Initial JSON parse failed, attempting to fix common issues');\n\n // Replace any unescaped newlines in string values\n const fixedJson = cleanedJsonText\n .replace(/:\\s*\"([^\"]*)(?:\\n)([^\"]*)\"/g, ': \"$1\\\\n$2\"')\n // Remove any non-JSON text that might have gotten mixed into string values\n .replace(/\"([^\"]*?)[^a-zA-Z0-9\\s\\.,;:\\-_\\(\\)\"'\\[\\]{}]([^\"]*?)\"/g, '\"$1$2\"')\n // Fix missing quotes around property names\n .replace(/(\\s*)(\\w+)(\\s*):/g, '$1\"$2\"$3:')\n // Fix trailing commas in arrays and objects\n .replace(/,(\\s*[\\]}])/g, '$1');\n\n try {\n jsonObject = JSON.parse(fixedJson);\n } catch (finalError) {\n logger.error('Failed to parse JSON after fixing:', finalError);\n throw new Error('Invalid JSON returned from model');\n }\n }\n\n // Validate against schema if provided\n if (params.schema) {\n try {\n // Simplistic schema validation - check if all required properties exist\n for (const key of Object.keys(params.schema)) {\n if (!(key in jsonObject)) {\n jsonObject[key] = null; // Add missing properties with null value\n }\n }\n } catch (schemaError) {\n logger.error('Schema validation failed:', schemaError);\n }\n }\n\n return jsonObject;\n } catch (parseError) {\n logger.error('Failed to parse JSON:', parseError);\n logger.error('Raw response:', textResponse);\n throw new Error('Invalid JSON returned from model');\n }\n } catch (error) {\n logger.error('Error in OBJECT_LARGE handler:', error);\n throw error;\n }\n },\n\n [ModelType.TEXT_TOKENIZER_ENCODE]: async (\n _runtime: IAgentRuntime,\n { text }: { text: string }\n ) => {\n try {\n const manager = localAIManager.getTokenizerManager();\n const config = localAIManager.getActiveModelConfig();\n return await manager.encode(text, config);\n } catch (error) {\n logger.error('Error in TEXT_TOKENIZER_ENCODE handler:', error);\n throw error;\n }\n },\n\n [ModelType.TEXT_TOKENIZER_DECODE]: async (\n _runtime: IAgentRuntime,\n { tokens }: { tokens: number[] }\n ) => {\n try {\n const manager = localAIManager.getTokenizerManager();\n const config = localAIManager.getActiveModelConfig();\n return await manager.decode(tokens, config);\n } catch (error) {\n logger.error('Error in TEXT_TOKENIZER_DECODE handler:', error);\n throw error;\n }\n },\n\n [ModelType.IMAGE_DESCRIPTION]: async (_runtime: IAgentRuntime, imageUrl: string) => {\n try {\n logger.info('Processing image from URL:', imageUrl);\n\n // Fetch the image from URL\n const response = await fetch(imageUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch image: ${response.statusText}`);\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const mimeType = response.headers.get('content-type') || 'image/jpeg';\n\n return await localAIManager.describeImage(buffer, mimeType);\n } catch (error) {\n logger.error('Error in IMAGE_DESCRIPTION handler:', {\n error: error instanceof Error ? error.message : String(error),\n imageUrl,\n });\n throw error;\n }\n },\n\n [ModelType.TRANSCRIPTION]: async (_runtime: IAgentRuntime, audioBuffer: Buffer) => {\n try {\n logger.info('Processing audio transcription:', {\n bufferSize: audioBuffer.length,\n });\n\n return await localAIManager.transcribeAudio(audioBuffer);\n } catch (error) {\n logger.error('Error in TRANSCRIPTION handler:', {\n error: error instanceof Error ? error.message : String(error),\n bufferSize: audioBuffer.length,\n });\n throw error;\n }\n },\n\n [ModelType.TEXT_TO_SPEECH]: async (_runtime: IAgentRuntime, text: string) => {\n try {\n return await localAIManager.generateSpeech(text);\n } catch (error) {\n logger.error('Error in TEXT_TO_SPEECH handler:', {\n error: error instanceof Error ? error.message : String(error),\n textLength: text.length,\n });\n throw error;\n }\n },\n },\n tests: [\n {\n name: 'local_ai_plugin_tests',\n tests: [\n {\n name: 'local_ai_test_initialization',\n fn: async (runtime) => {\n try {\n logger.info('Starting initialization test');\n\n // Test TEXT_SMALL model initialization\n const result = await runtime.useModel(ModelType.TEXT_SMALL, {\n prompt:\n \"Debug Mode: Test initialization. Respond with 'Initialization successful' if you can read this.\",\n stopSequences: [],\n });\n\n logger.info('Model response:', result);\n\n if (!result || typeof result !== 'string') {\n throw new Error('Invalid response from model');\n }\n\n if (!result.includes('successful')) {\n throw new Error('Model response does not indicate success');\n }\n\n logger.success('Initialization test completed successfully');\n } catch (error) {\n logger.error('Initialization test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_text_large',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_LARGE model test');\n\n const result = await runtime.useModel(ModelType.TEXT_LARGE, {\n prompt:\n 'Debug Mode: Generate a one-sentence response about artificial intelligence.',\n stopSequences: [],\n });\n\n logger.info('Large model response:', result);\n\n if (!result || typeof result !== 'string') {\n throw new Error('Invalid response from large model');\n }\n\n if (result.length < 10) {\n throw new Error('Response too short, possible model failure');\n }\n\n logger.success('TEXT_LARGE test completed successfully');\n } catch (error) {\n logger.error('TEXT_LARGE test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_text_embedding',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_EMBEDDING test');\n\n // Test with normal text\n const embedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, {\n text: 'This is a test of the text embedding model.',\n });\n\n logger.info('Embedding generated with dimensions:', embedding.length);\n\n if (!Array.isArray(embedding)) {\n throw new Error('Embedding is not an array');\n }\n\n if (embedding.length === 0) {\n throw new Error('Embedding array is empty');\n }\n\n if (embedding.some((val) => typeof val !== 'number')) {\n throw new Error('Embedding contains non-numeric values');\n }\n\n // Test with null input (should return zero vector)\n const nullEmbedding = await runtime.useModel(ModelType.TEXT_EMBEDDING, null);\n if (!Array.isArray(nullEmbedding) || nullEmbedding.some((val) => val !== 0)) {\n throw new Error('Null input did not return zero vector');\n }\n\n logger.success('TEXT_EMBEDDING test completed successfully');\n } catch (error) {\n logger.error('TEXT_EMBEDDING test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_tokenizer_encode',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_TOKENIZER_ENCODE test');\n const text = 'Hello tokenizer test!';\n\n const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, { text });\n logger.info('Encoded tokens:', { count: tokens.length });\n\n if (!Array.isArray(tokens)) {\n throw new Error('Tokens output is not an array');\n }\n\n if (tokens.length === 0) {\n throw new Error('No tokens generated');\n }\n\n if (tokens.some((token) => !Number.isInteger(token))) {\n throw new Error('Tokens contain non-integer values');\n }\n\n logger.success('TEXT_TOKENIZER_ENCODE test completed successfully');\n } catch (error) {\n logger.error('TEXT_TOKENIZER_ENCODE test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_tokenizer_decode',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_TOKENIZER_DECODE test');\n\n // First encode some text\n const originalText = 'Hello tokenizer test!';\n const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, {\n text: originalText,\n });\n\n // Then decode it back\n const decodedText = await runtime.useModel(ModelType.TEXT_TOKENIZER_DECODE, {\n tokens,\n });\n logger.info('Round trip tokenization:', {\n original: originalText,\n decoded: decodedText,\n });\n\n if (typeof decodedText !== 'string') {\n throw new Error('Decoded output is not a string');\n }\n\n logger.success('TEXT_TOKENIZER_DECODE test completed successfully');\n } catch (error) {\n logger.error('TEXT_TOKENIZER_DECODE test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_image_description',\n fn: async (runtime) => {\n try {\n logger.info('Starting IMAGE_DESCRIPTION test');\n\n // Use a more stable test image URL\n const imageUrl =\n 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/320px-Cat03.jpg';\n const result = await runtime.useModel(ModelType.IMAGE_DESCRIPTION, imageUrl);\n\n logger.info('Image description result:', result);\n\n if (!result || typeof result !== 'object') {\n throw new Error('Invalid response format');\n }\n\n if (!result.title || !result.description) {\n throw new Error('Missing title or description in response');\n }\n\n if (typeof result.title !== 'string' || typeof result.description !== 'string') {\n throw new Error('Title or description is not a string');\n }\n\n logger.success('IMAGE_DESCRIPTION test completed successfully');\n } catch (error) {\n logger.error('IMAGE_DESCRIPTION test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_transcription',\n fn: async (runtime) => {\n try {\n logger.info('Starting TRANSCRIPTION test');\n\n // Create a proper WAV file header and minimal audio data\n // WAV file format: RIFF header + fmt chunk + data chunk\n const channels = 1;\n const sampleRate = 16000;\n const bitsPerSample = 16;\n const duration = 0.5; // 500ms for better transcription\n const numSamples = Math.floor(sampleRate * duration);\n const dataSize = numSamples * channels * (bitsPerSample / 8);\n\n // Create the WAV header\n const buffer = Buffer.alloc(44 + dataSize);\n\n // RIFF header\n buffer.write('RIFF', 0);\n buffer.writeUInt32LE(36 + dataSize, 4); // File size - 8\n buffer.write('WAVE', 8);\n\n // fmt chunk\n buffer.write('fmt ', 12);\n buffer.writeUInt32LE(16, 16); // fmt chunk size\n buffer.writeUInt16LE(1, 20); // Audio format (1 = PCM)\n buffer.writeUInt16LE(channels, 22); // Number of channels\n buffer.writeUInt32LE(sampleRate, 24); // Sample rate\n buffer.writeUInt32LE(sampleRate * channels * (bitsPerSample / 8), 28); // Byte rate\n buffer.writeUInt16LE(channels * (bitsPerSample / 8), 32); // Block align\n buffer.writeUInt16LE(bitsPerSample, 34); // Bits per sample\n\n // data chunk\n buffer.write('data', 36);\n buffer.writeUInt32LE(dataSize, 40); // Data size\n\n // Generate a simple sine wave tone (440Hz) instead of silence\n const frequency = 440; // A4 note\n for (let i = 0; i < numSamples; i++) {\n const sample = Math.sin((2 * Math.PI * frequency * i) / sampleRate) * 0.1 * 32767;\n buffer.writeInt16LE(Math.floor(sample), 44 + i * 2);\n }\n\n const transcription = await runtime.useModel(ModelType.TRANSCRIPTION, buffer);\n logger.info('Transcription result:', transcription);\n\n if (typeof transcription !== 'string') {\n throw new Error('Transcription result is not a string');\n }\n\n // Accept empty string as valid result (for non-speech audio)\n logger.info('Transcription completed (may be empty for non-speech audio)');\n\n logger.success('TRANSCRIPTION test completed successfully');\n } catch (error) {\n logger.error('TRANSCRIPTION test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n {\n name: 'local_ai_test_text_to_speech',\n fn: async (runtime) => {\n try {\n logger.info('Starting TEXT_TO_SPEECH test');\n\n const testText = 'This is a test of the text to speech system.';\n const audioStream = await runtime.useModel(ModelType.TEXT_TO_SPEECH, testText);\n\n if (!(audioStream instanceof Readable)) {\n throw new Error('TTS output is not a readable stream');\n }\n\n // Test stream readability\n let dataReceived = false;\n audioStream.on('data', () => {\n dataReceived = true;\n });\n\n await new Promise((resolve, reject) => {\n audioStream.on('end', () => {\n if (!dataReceived) {\n reject(new Error('No audio data received from stream'));\n } else {\n resolve(true);\n }\n });\n audioStream.on('error', reject);\n });\n\n logger.success('TEXT_TO_SPEECH test completed successfully');\n } catch (error) {\n logger.error('TEXT_TO_SPEECH test failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n },\n },\n ],\n },\n ],\n};\n\nexport default localAiPlugin;\n","import { logger } from '@elizaos/core';\nimport { z } from 'zod';\n\n// Default model filenames\nconst DEFAULT_SMALL_MODEL = 'DeepHermes-3-Llama-3-3B-Preview-q4.gguf';\nconst DEFAULT_LARGE_MODEL = 'DeepHermes-3-Llama-3-8B-q4.gguf';\nconst DEFAULT_EMBEDDING_MODEL = 'bge-small-en-v1.5.Q4_K_M.gguf';\n\n// Configuration schema focused only on local AI settings\n/**\n * Configuration schema for local AI settings.\n * Allows overriding default model filenames via environment variables.\n */\nexport const configSchema = z.object({\n LOCAL_SMALL_MODEL: z.string().optional().default(DEFAULT_SMALL_MODEL),\n LOCAL_LARGE_MODEL: z.string().optional().default(DEFAULT_LARGE_MODEL),\n LOCAL_EMBEDDING_MODEL: z.string().optional().default(DEFAULT_EMBEDDING_MODEL),\n MODELS_DIR: z.string().optional(), // Path for the models directory\n CACHE_DIR: z.string().optional(), // Path for the cache directory\n LOCAL_EMBEDDING_DIMENSIONS: z\n .string()\n .optional()\n .default('384') // Default to 384 if not provided\n .transform((val) => parseInt(val, 10)), // Transform to number\n});\n\n/**\n * Export type representing the inferred type of the 'configSchema'.\n */\nexport type Config = z.infer<typeof configSchema>;\n\n/**\n * Validates and parses the configuration, reading from environment variables.\n * Since only local AI is supported, this primarily ensures the structure\n * and applies defaults or environment variable overrides for model filenames.\n * @returns {Config} The validated configuration object.\n */\nexport function validateConfig(): Config {\n try {\n // Prepare the config for parsing, reading from process.env\n const configToParse = {\n // Read model filenames from environment variables or use undefined (so zod defaults apply)\n LOCAL_SMALL_MODEL: process.env.LOCAL_SMALL_MODEL,\n LOCAL_LARGE_MODEL: process.env.LOCAL_LARGE_MODEL,\n LOCAL_EMBEDDING_MODEL: process.env.LOCAL_EMBEDDING_MODEL,\n MODELS_DIR: process.env.MODELS_DIR, // Read models directory path from env\n CACHE_DIR: process.env.CACHE_DIR, // Read cache directory path from env\n LOCAL_EMBEDDING_DIMENSIONS: process.env.LOCAL_EMBEDDING_DIMENSIONS, // Read embedding dimensions\n };\n\n logger.debug('Validating configuration for local AI plugin from env:', {\n LOCAL_SMALL_MODEL: configToParse.LOCAL_SMALL_MODEL,\n LOCAL_LARGE_MODEL: configToParse.LOCAL_LARGE_MODEL,\n LOCAL_EMBEDDING_MODEL: configToParse.LOCAL_EMBEDDING_MODEL,\n MODELS_DIR: configToParse.MODELS_DIR,\n CACHE_DIR: configToParse.CACHE_DIR,\n LOCAL_EMBEDDING_DIMENSIONS: configToParse.LOCAL_EMBEDDING_DIMENSIONS,\n });\n\n const validatedConfig = configSchema.parse(configToParse);\n\n logger.info('Using local AI configuration:', validatedConfig);\n\n return validatedConfig;\n } catch (error) {\n if (error instanceof z.ZodError) {\n const errorMessages = error.errors\n .map((err) => `${err.path.join('.')}: ${err.message}`)\n .join('\\n');\n logger.error('Zod validation failed:', errorMessages);\n throw new Error(`Configuration validation failed:\\n${errorMessages}`);\n }\n logger.error('Configuration validation failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n}\n","// Model specifications and configurations\n/**\n * Interface representing a Tokenizer configuration.\n * @property {string} name - The name of the tokenizer.\n * @property {string} type - The type of the tokenizer.\n */\nexport interface TokenizerConfig {\n name: string;\n type: string;\n}\n\n/**\n * Interface representing the specification of a model.\n * @typedef {Object} ModelSpec\n * @property {string} name - The name of the model.\n * @property {string} repo - The repository of the model.\n * @property {string} size - The size of the model.\n * @property {string} quantization - The quantization of the model.\n * @property {number} contextSize - The context size of the model.\n * @property {TokenizerConfig} tokenizer - The configuration for the tokenizer used by the model.\n */\nexport interface ModelSpec {\n name: string;\n repo: string;\n size: string;\n quantization: string;\n contextSize: number;\n tokenizer: TokenizerConfig;\n}\n\n/**\n * Interface representing the specification of an embedding model.\n * @typedef {Object} EmbeddingModelSpec\n * @property {string} name - The name of the embedding model.\n * @property {string} repo - The repository of the embedding model.\n * @property {string} size - The size of the embedding model.\n * @property {string} quantization - The quantization of the embedding model.\n * @property {number} contextSize - The context size of the embedding model.\n * @property {number} dimensions - The embedding dimensions.\n * @property {TokenizerConfig} tokenizer - The configuration for the tokenizer used by the model.\n */\nexport interface EmbeddingModelSpec extends ModelSpec {\n dimensions: number;\n}\n\n/**\n * Interface representing a specification for a vision model.\n * @typedef {object} VisionModelSpec\n * @property {string} name - The name of the vision model.\n * @property {string} repo - The repository of the vision model.\n * @property {string} size - The size of the vision model.\n * @property {string} modelId - The ID of the vision model.\n * @property {number} contextSize - The context size of the vision model.\n * @property {number} maxTokens - The maximum tokens of the vision model.\n * @property {Array.<string>} tasks - The tasks performed by the vision model.\n */\nexport interface VisionModelSpec {\n name: string;\n repo: string;\n size: string;\n modelId: string;\n contextSize: number;\n maxTokens: number;\n tasks: string[];\n}\n\n/**\n * Interface representing the specification for a TTS model.\n * @typedef { Object } TTSModelSpec\n * @property { string } name - The name of the model.\n * @property { string } repo - The repository where the model is stored.\n * @property { string } size - The size of the model.\n * @property { string } quantization - The quantization method used for the model.\n * @property {string[]} speakers - An array of speakers the model can mimic.\n * @property {string[]} languages - An array of languages the model can speak in.\n * @property {string[]} features - An array of features supported by the model.\n * @property { number } maxInputLength - The maximum input length accepted by the model.\n * @property { number } sampleRate - The sample rate used by the model.\n * @property { number } contextSize - The context size used by the model.\n * @property { TokenizerConfig } tokenizer - The configuration for the tokenizer used by the model.\n */\nexport interface TTSModelSpec {\n name: string;\n repo: string;\n size: string;\n quantization: string;\n speakers: string[];\n languages: string[];\n features: string[];\n maxInputLength: number;\n sampleRate: number;\n contextSize: number;\n tokenizer: TokenizerConfig;\n}\n\n/**\n * Interface representing a specification for a TTS model runnable with Transformers.js.\n * @typedef { object } TransformersJsTTSModelSpec\n * @property { string } modelId - The Hugging Face model identifier (e.g., 'Xenova/speecht5_tts').\n * @property { number } defaultSampleRate - The typical sample rate for this model (e.g., 16000 for SpeechT5).\n * @property { string } [defaultSpeakerEmbeddingUrl] - Optional URL to a default speaker embedding .bin file.\n */\nexport interface TransformersJsTTSModelSpec {\n modelId: string;\n defaultSampleRate: number;\n defaultSpeakerEmbeddingUrl?: string;\n}\n\n// Model specifications mapping\n/**\n * Interface for specifying different models for a project.\n * @interface ModelSpecs\n * @property {ModelSpec} small - Specifications for a small model\n * @property {ModelSpec} medium - Specifications for a medium model\n * @property {EmbeddingModelSpec} embedding - Specifications for an embedding model\n * @property {VisionModelSpec} vision - Specifications for a vision model\n * @property {VisionModelSpec} visionvl - Specifications for a vision model with vision loss\n * @property {Object} tts - Specifications for text-to-speech models (using Transformers.js)\n * @property {TransformersJsTTSModelSpec} tts.default - Specifications for the default text-to-speech model\n */\nexport interface ModelSpecs {\n small: ModelSpec;\n medium: ModelSpec;\n embedding: EmbeddingModelSpec;\n vision: VisionModelSpec;\n visionvl: VisionModelSpec;\n tts: {\n default: TransformersJsTTSModelSpec;\n };\n}\n\n// Export MODEL_SPECS constant type\n/**\n * Model specifications containing information about various models such as name, repository, size, quantization, context size, tokenizer details, tasks, speakers, languages, features, max input length, sample rate, and other relevant information.\n */\nexport const MODEL_SPECS: ModelSpecs = {\n small: {\n name: 'DeepHermes-3-Llama-3-3B-Preview-q4.gguf',\n repo: 'NousResearch/DeepHermes-3-Llama-3-3B-Preview-GGUF',\n size: '3B',\n quantization: 'Q4_0',\n contextSize: 8192,\n tokenizer: {\n name: 'NousResearch/DeepHermes-3-Llama-3-3B-Preview',\n type: 'llama',\n },\n },\n medium: {\n name: 'DeepHermes-3-Llama-3-8B-q4.gguf',\n repo: 'NousResearch/DeepHermes-3-Llama-3-8B-Preview-GGUF',\n size: '8B',\n quantization: 'Q4_0',\n contextSize: 8192,\n tokenizer: {\n name: 'NousResearch/DeepHermes-3-Llama-3-8B-Preview',\n type: 'llama',\n },\n },\n embedding: {\n name: 'bge-small-en-v1.5.Q4_K_M.gguf',\n repo: 'ChristianAzinn/bge-small-en-v1.5-gguf',\n size: '133 MB',\n quantization: 'Q4_K_M',\n contextSize: 512,\n dimensions: 384,\n tokenizer: {\n name: 'ChristianAzinn/bge-small-en-v1.5-gguf',\n type: 'llama',\n },\n },\n vision: {\n name: 'Florence-2-base-ft',\n repo: 'onnx-community/Florence-2-base-ft',\n size: '0.23B',\n modelId: 'onnx-community/Florence-2-base-ft',\n contextSize: 1024,\n maxTokens: 256,\n tasks: [\n 'CAPTION',\n 'DETAILED_CAPTION',\n 'MORE_DETAILED_CAPTION',\n 'CAPTION_TO_PHRASE_GROUNDING',\n 'OD',\n 'DENSE_REGION_CAPTION',\n 'REGION_PROPOSAL',\n 'OCR',\n 'OCR_WITH_REGION',\n ],\n },\n visionvl: {\n name: 'Qwen2.5-VL-3B-Instruct',\n repo: 'Qwen/Qwen2.5-VL-3B-Instruct',\n size: '3B',\n modelId: 'Qwen/Qwen2.5-VL-3B-Instruct',\n contextSize: 32768,\n maxTokens: 1024,\n tasks: [\n 'CAPTION',\n 'DETAILED_CAPTION',\n 'IMAGE_UNDERSTANDING',\n 'VISUAL_QUESTION_ANSWERING',\n 'OCR',\n 'VISUAL_LOCALIZATION',\n 'REGION_ANALYSIS',\n ],\n },\n tts: {\n default: {\n modelId: 'Xenova/speecht5_tts',\n defaultSampleRate: 16000, // SpeechT5 default\n // Use the standard embedding URL\n defaultSpeakerEmbeddingUrl:\n 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/speaker_embeddings.bin',\n },\n },\n};\n","import fs from 'node:fs';\nimport https from 'node:https';\nimport path from 'node:path';\nimport { logger } from '@elizaos/core';\nimport type { ModelSpec } from '../types';\n\n/**\n * Class representing a Download Manager.\n */\nexport class DownloadManager {\n private static instance: DownloadManager | null = null;\n private cacheDir: string;\n private modelsDir: string;\n // Track active downloads to prevent duplicates\n private activeDownloads: Map<string, Promise<void>> = new Map();\n\n /**\n * Creates a new instance of CacheManager.\n *\n * @param {string} cacheDir - The directory path for caching data.\n * @param {string} modelsDir - The directory path for model files.\n */\n private constructor(cacheDir: string, modelsDir: string) {\n this.cacheDir = cacheDir;\n this.modelsDir = modelsDir;\n this.ensureCacheDirectory();\n this.ensureModelsDirectory();\n }\n\n /**\n * Returns the singleton instance of the DownloadManager class.\n * If an instance does not already exist, it creates a new one using the provided cache directory and models directory.\n *\n * @param {string} cacheDir - The directory where downloaded files are stored.\n * @param {string} modelsDir - The directory where model files are stored.\n * @returns {DownloadManager} The singleton instance of the DownloadManager class.\n */\n public static getInstance(cacheDir: string, modelsDir: string): DownloadManager {\n if (!DownloadManager.instance) {\n DownloadManager.instance = new DownloadManager(cacheDir, modelsDir);\n }\n return DownloadManager.instance;\n }\n\n /**\n * Ensure that the cache directory exists.\n */\n private ensureCacheDirectory(): void {\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n logger.debug('Created cache directory');\n }\n }\n\n /**\n * Ensure that the models directory exists. If it does not exist, create it.\n */\n private ensureModelsDirectory(): void {\n logger.debug('Ensuring models directory exists:', this.modelsDir);\n if (!fs.existsSync(this.modelsDir)) {\n fs.mkdirSync(this.modelsDir, { recursive: true });\n logger.debug('Created models directory');\n }\n }\n\n /**\n * Downloads a file from a given URL to a specified destination path asynchronously.\n *\n * @param {string} url - The URL from which to download the file.\n * @param {string} destPath - The destination path where the downloaded file will be saved.\n * @returns {Promise<void>} A Promise that resolves when the file download is completed successfully or rejects if an error occurs.\n */\n private async downloadFileInternal(url: string, destPath: string): Promise<void> {\n return new Promise((resolve, reject) => {\n logger.info(`Starting download to: ${destPath}`);\n\n // Create a temporary file path in the same directory as destPath\n const tempPath = `${destPath}.tmp`;\n\n // Check if temp file already exists and remove it to avoid conflicts\n if (fs.existsSync(tempPath)) {\n try {\n logger.warn(`Removing existing temporary file: ${tempPath}`);\n fs.unlinkSync(tempPath);\n } catch (err) {\n logger.error(\n `Failed to remove existing temporary file: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n\n const request = https.get(\n url,\n {\n headers: {\n 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',\n },\n timeout: 300000, // Increase timeout to 5 minutes\n },\n (response) => {\n if (response.statusCode === 301 || response.statusCode === 302) {\n const redirectUrl = response.headers.location;\n if (!redirectUrl) {\n reject(new Error('Redirect location not found'));\n return;\n }\n // logger.info(`Following redirect to: ${redirectUrl}`);\n // Remove the current download from tracking before starting a new one\n this.activeDownloads.delete(destPath);\n this.downloadFile(redirectUrl, destPath).then(resolve).catch(reject);\n return;\n }\n\n if (response.statusCode !== 200) {\n reject(new Error(`Failed to download: ${response.statusCode}`));\n return;\n }\n\n const totalSize = Number.parseInt(response.headers['content-length'] || '0', 10);\n let downloadedSize = 0;\n let lastLoggedPercent = 0;\n const barLength = 30;\n\n // Log initial progress bar\n const fileName = path.basename(destPath);\n logger.info(`Downloading ${fileName}: ${'▱'.repeat(barLength)} 0%`);\n\n const file = fs.createWriteStream(tempPath);\n\n response.on('data', (chunk) => {\n downloadedSize += chunk.length;\n const percent = Math.round((downloadedSize / totalSize) * 100);\n\n // Only update progress bar when percentage changes significantly (every 5%)\n if (percent >= lastLoggedPercent + 5) {\n const filledLength = Math.floor((downloadedSize / totalSize) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(`Downloading ${fileName}: ${progressBar} ${percent}%`);\n lastLoggedPercent = percent;\n }\n });\n\n response.pipe(file);\n\n file.on('finish', () => {\n file.close(() => {\n try {\n // Show completed progress bar\n const completedBar = '▰'.repeat(barLength);\n logger.info(`Downloading ${fileName}: ${completedBar} 100%`);\n\n // Ensure the destination directory exists\n const destDir = path.dirname(destPath);\n if (!fs.existsSync(destDir)) {\n fs.mkdirSync(destDir, { recursive: true });\n }\n\n // Check if temp file exists before proceeding\n if (!fs.existsSync(tempPath)) {\n reject(new Error(`Temporary file ${tempPath} does not exist`));\n return;\n }\n\n // Only delete the existing file if the temp file is ready\n if (fs.existsSync(destPath)) {\n try {\n // Create a backup of the existing file before deleting it\n const backupPath = `${destPath}.bak`;\n fs.renameSync(destPath, backupPath);\n logger.info(`Created backup of existing file: ${backupPath}`);\n\n // Move temp file to destination\n fs.renameSync(tempPath, destPath);\n\n // If successful, remove the backup\n if (fs.existsSync(backupPath)) {\n fs.unlinkSync(backupPath);\n logger.info(`Removed backup file after successful update: ${backupPath}`);\n }\n } catch (moveErr) {\n logger.error(\n `Error replacing file: ${moveErr instanceof Error ? moveErr.message : String(moveErr)}`\n );\n\n // Try to restore from backup if the move failed\n const backupPath = `${destPath}.bak`;\n if (fs.existsSync(backupPath)) {\n try {\n fs.renameSync(backupPath, destPath);\n logger.info(`Restored from backup after failed update: ${backupPath}`);\n } catch (restoreErr) {\n logger.error(\n `Failed to restore from backup: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`\n );\n }\n }\n\n // Clean up temp file\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n\n reject(moveErr);\n return;\n }\n } else {\n // No existing file, just move the temp file\n fs.renameSync(tempPath, destPath);\n }\n\n logger.success(`Download of ${fileName} completed successfully`);\n\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n resolve();\n } catch (err) {\n logger.error(\n `Error finalizing download: ${err instanceof Error ? err.message : String(err)}`\n );\n // Clean up temp file if it exists\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n reject(err);\n }\n });\n });\n\n file.on('error', (err) => {\n logger.error(`File write error: ${err instanceof Error ? err.message : String(err)}`);\n file.close(() => {\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file after error: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n reject(err);\n });\n });\n }\n );\n\n request.on('error', (err) => {\n logger.error(`Request error: ${err instanceof Error ? err.message : String(err)}`);\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file after request error: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n reject(err);\n });\n\n request.on('timeout', () => {\n logger.error('Download timeout occurred');\n request.destroy();\n if (fs.existsSync(tempPath)) {\n try {\n fs.unlinkSync(tempPath);\n } catch (unlinkErr) {\n logger.error(\n `Failed to clean up temp file after timeout: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}`\n );\n }\n }\n // Remove from active downloads\n this.activeDownloads.delete(destPath);\n reject(new Error('Download timeout'));\n });\n });\n }\n\n /**\n * Asynchronously downloads a file from the specified URL to the destination path.\n *\n * @param {string} url - The URL of the file to download.\n * @param {string} destPath - The destination path to save the downloaded file.\n * @returns {Promise<void>} A Promise that resolves once the file has been successfully downloaded.\n */\n public async downloadFile(url: string, destPath: string): Promise<void> {\n // Check if this file is already being downloaded\n if (this.activeDownloads.has(destPath)) {\n logger.info(`Download for ${destPath} already in progress, waiting for it to complete...`);\n const existingDownload = this.activeDownloads.get(destPath);\n if (existingDownload) {\n return existingDownload;\n }\n // If somehow the download was removed from the map but the key still exists\n logger.warn(\n `Download for ${destPath} was marked as in progress but not found in tracking map`\n );\n }\n\n // Start a new download and track it\n const downloadPromise = this.downloadFileInternal(url, destPath);\n this.activeDownloads.set(destPath, downloadPromise);\n\n try {\n return await downloadPromise;\n } catch (error) {\n // Make sure to remove from active downloads in case of error\n this.activeDownloads.delete(destPath);\n throw error;\n }\n }\n\n /**\n * Downloads a model specified by the modelSpec and saves it to the provided modelPath.\n * If the model is successfully downloaded, returns true, otherwise returns false.\n *\n * @param {ModelSpec} modelSpec - The model specification containing repo and name.\n * @param {string} modelPath - The path where the model will be saved.\n * @returns {Promise<boolean>} - Indicates if the model was successfully downloaded or not.\n */\n public async downloadModel(modelSpec: ModelSpec, modelPath: string): Promise<boolean> {\n try {\n logger.info('Starting local model download...');\n\n // Ensure model directory exists\n const modelDir = path.dirname(modelPath);\n if (!fs.existsSync(modelDir)) {\n logger.info('Creating model directory:', modelDir);\n fs.mkdirSync(modelDir, { recursive: true });\n }\n\n if (!fs.existsSync(modelPath)) {\n // Try different URL patterns in sequence, similar to TTS manager approach\n const attempts = [\n {\n description: 'LFS URL with GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo}/resolve/main/${modelSpec.name}?download=true`,\n },\n {\n description: 'LFS URL without GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo.replace('-GGUF', '')}/resolve/main/${modelSpec.name}?download=true`,\n },\n {\n description: 'Standard URL with GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo}/resolve/main/${modelSpec.name}`,\n },\n {\n description: 'Standard URL without GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo.replace('-GGUF', '')}/resolve/main/${modelSpec.name}`,\n },\n ];\n\n // logger.info(\"Model download details:\", {\n // modelName: modelSpec.name,\n // repo: modelSpec.repo,\n // modelPath: modelPath,\n // attemptUrls: attempts.map(a => ({ description: a.description, url: a.url })),\n // timestamp: new Date().toISOString()\n // });\n\n let lastError = null;\n let downloadSuccess = false;\n\n for (const attempt of attempts) {\n try {\n logger.info('Attempting model download:', {\n description: attempt.description,\n url: attempt.url,\n timestamp: new Date().toISOString(),\n });\n\n // The downloadFile method now handles the progress bar display\n await this.downloadFile(attempt.url, modelPath);\n\n logger.success(\n `Model download complete: ${modelSpec.name} using ${attempt.description}`\n );\n downloadSuccess = true;\n break;\n } catch (error) {\n lastError = error;\n logger.warn('Model download attempt failed:', {\n description: attempt.description,\n error: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n if (!downloadSuccess) {\n throw lastError || new Error('All download attempts failed');\n }\n\n // Return true to indicate the model was newly downloaded\n return true;\n }\n\n // Model already exists\n logger.info('Model already exists at:', modelPath);\n // Return false to indicate the model already existed\n return false;\n } catch (error) {\n logger.error('Model download failed:', {\n error: error instanceof Error ? error.message : String(error),\n modelPath: modelPath,\n model: modelSpec.name,\n });\n throw error;\n }\n }\n\n /**\n * Returns the cache directory path.\n *\n * @returns {string} The path of the cache directory.\n */\n\n public getCacheDir(): string {\n return this.cacheDir;\n }\n\n /**\n * Downloads a file from a given URL to a specified destination path.\n *\n * @param {string} url - The URL of the file to download.\n * @param {string} destPath - The destination path where the file should be saved.\n * @returns {Promise<void>} A Promise that resolves once the file has been downloaded.\n */\n public async downloadFromUrl(url: string, destPath: string): Promise<void> {\n return this.downloadFile(url, destPath);\n }\n\n /**\n * Ensures that the specified directory exists. If it does not exist, it will be created.\n * @param {string} dirPath - The path of the directory to ensure existence of.\n * @returns {void}\n */\n public ensureDirectoryExists(dirPath: string): void {\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n logger.info(`Created directory: ${dirPath}`);\n }\n }\n}\n","import { exec } from 'node:child_process';\nimport os from 'node:os';\nimport { promisify } from 'node:util';\nimport { logger } from '@elizaos/core';\n\nconst execAsync = promisify(exec);\n\n/**\n * Represents the configuration of a system GPU.\n * @typedef {Object} SystemGPU\n * @property {string} name - The name of the GPU.\n * @property {number} [memory] - The memory size of the GPU. (Optional)\n * @property {\"cuda\" | \"metal\" | \"directml\" | \"none\"} type - The type of GPU.\n * @property {string} [version] - The version of the GPU. (Optional)\n * @property {boolean} [isAppleSilicon] - Indicates if the GPU is Apple Silicon. (Optional)\n */\nexport interface SystemGPU {\n name: string;\n memory?: number;\n type: 'cuda' | 'metal' | 'directml' | 'none';\n version?: string;\n isAppleSilicon?: boolean;\n}\n\n/**\n * Interface representing the system CPU information.\n * @typedef {Object} SystemCPU\n * @property {string} model - The model of the CPU.\n * @property {number} cores - The number of cores in the CPU.\n * @property {number} speed - The speed of the CPU.\n * @property {string} architecture - The architecture of the CPU.\n * @property {Object} memory - Object containing memory information.\n * @property {number} memory.total - The total memory available.\n * @property {number} memory.free - The free memory available.\n */\nexport interface SystemCPU {\n model: string;\n cores: number;\n speed: number;\n architecture: string;\n memory: {\n total: number;\n free: number;\n };\n}\n\n/**\n * Interface representing the capabilities of a system.\n *\n * @typedef {Object} SystemCapabilities\n * @property {NodeJS.Platform} platform - The platform of the system.\n * @property {SystemCPU} cpu - The CPU information of the system.\n * @property {SystemGPU | null} gpu - The GPU information of the system, can be null if no GPU is present.\n * @property {\"small\" | \"medium\" | \"large\"} recommendedModelSize - The recommended model size for the system.\n * @property {Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\">} supportedBackends - An array of supported backends for the system.\n */\nexport interface SystemCapabilities {\n platform: NodeJS.Platform;\n cpu: SystemCPU;\n gpu: SystemGPU | null;\n recommendedModelSize: 'small' | 'medium' | 'large';\n supportedBackends: Array<'cuda' | 'metal' | 'directml' | 'cpu'>;\n}\n\n/**\n * Class representing a Platform Manager.\n *\n * @class\n */\n\nexport class PlatformManager {\n private static instance: PlatformManager;\n private capabilities: SystemCapabilities | null = null;\n\n /**\n * Private constructor method.\n */\n private constructor() {}\n\n /**\n * Get the singleton instance of the PlatformManager class\n * @returns {PlatformManager} The instance of PlatformManager\n */\n static getInstance(): PlatformManager {\n if (!PlatformManager.instance) {\n PlatformManager.instance = new PlatformManager();\n }\n return PlatformManager.instance;\n }\n\n /**\n * Asynchronous method to initialize platform detection.\n *\n * @returns {Promise<void>} Promise that resolves once platform detection is completed.\n */\n async initialize(): Promise<void> {\n try {\n logger.info('Initializing platform detection...');\n this.capabilities = await this.detectSystemCapabilities();\n // logger.info(\"Platform detection completed\", {\n // platform: this.capabilities.platform,\n // gpu: this.capabilities.gpu?.type || \"none\",\n // recommendedModel: this.capabilities.recommendedModelSize,\n // });\n } catch (error) {\n logger.error('Platform detection failed', { error });\n throw error;\n }\n }\n\n /**\n * Detects the system capabilities including platform, CPU information, GPU information,\n * supported backends, and recommended model size.\n *\n * @returns {Promise<SystemCapabilities>} Details of the system capabilities including platform, CPU info, GPU info,\n * recommended model size, and supported backends.\n */\n private async detectSystemCapabilities(): Promise<SystemCapabilities> {\n const platform = process.platform;\n const cpuInfo = this.getCPUInfo();\n const gpu = await this.detectGPU();\n const supportedBackends = await this.getSupportedBackends(platform, gpu);\n const recommendedModelSize = this.getRecommendedModelSize(cpuInfo, gpu);\n\n return {\n platform,\n cpu: cpuInfo,\n gpu,\n recommendedModelSize,\n supportedBackends,\n };\n }\n\n /**\n * Returns information about the CPU and memory of the system.\n * @returns {SystemCPU} The CPU information including model, number of cores, speed, architecture, and memory details.\n */\n private getCPUInfo(): SystemCPU {\n const cpus = os.cpus();\n const totalMemory = os.totalmem();\n const freeMemory = os.freemem();\n\n return {\n model: cpus[0].model,\n cores: cpus.length,\n speed: cpus[0].speed,\n architecture: process.arch,\n memory: {\n total: totalMemory,\n free: freeMemory,\n },\n };\n }\n\n /**\n * Asynchronously detects the GPU information based on the current platform.\n * @returns A promise that resolves with the GPU information if detection is successful, otherwise null.\n */\n private async detectGPU(): Promise<SystemGPU | null> {\n const platform = process.platform;\n\n try {\n switch (platform) {\n case 'darwin':\n return await this.detectMacGPU();\n case 'win32':\n return await this.detectWindowsGPU();\n case 'linux':\n return await this.detectLinuxGPU();\n default:\n return null;\n }\n } catch (error) {\n logger.error('GPU detection failed', { error });\n return null;\n }\n }\n\n /**\n * Asynchronously detects the GPU of a Mac system.\n * @returns {Promise<SystemGPU>} A promise that resolves to an object representing the detected GPU.\n */\n private async detectMacGPU(): Promise<SystemGPU> {\n try {\n const { stdout } = await execAsync('sysctl -n machdep.cpu.brand_string');\n const isAppleSilicon = stdout.toLowerCase().includes('apple');\n\n if (isAppleSilicon) {\n return {\n name: 'Apple Silicon',\n type: 'metal',\n isAppleSilicon: true,\n };\n }\n\n // For Intel Macs with discrete GPU\n const { stdout: gpuInfo } = await execAsync('system_profiler SPDisplaysDataType');\n return {\n name: gpuInfo.split('Chipset Model:')[1]?.split('\\n')[0]?.trim() || 'Unknown GPU',\n type: 'metal',\n isAppleSilicon: false,\n };\n } catch (error) {\n logger.error('Mac GPU detection failed', { error });\n return {\n name: 'Unknown Mac GPU',\n type: 'metal',\n isAppleSilicon: false,\n };\n }\n }\n\n /**\n * Detects the GPU in a Windows system and returns information about it.\n *\n * @returns {Promise<SystemGPU | null>} A promise that resolves with the detected GPU information or null if detection fails.\n */\n private async detectWindowsGPU(): Promise<SystemGPU | null> {\n try {\n const { stdout } = await execAsync('wmic path win32_VideoController get name');\n const gpuName = stdout.split('\\n')[1].trim();\n\n // Check for NVIDIA GPU\n if (gpuName.toLowerCase().includes('nvidia')) {\n const { stdout: nvidiaInfo } = await execAsync(\n 'nvidia-smi --query-gpu=name,memory.total --format=csv,noheader'\n );\n const [name, memoryStr] = nvidiaInfo.split(',').map((s) => s.trim());\n const memory = Number.parseInt(memoryStr);\n\n return {\n name,\n memory,\n type: 'cuda',\n version: await this.getNvidiaDriverVersion(),\n };\n }\n\n // Default to DirectML for other GPUs\n return {\n name: gpuName,\n type: 'directml',\n };\n } catch (error) {\n logger.error('Windows GPU detection failed', { error });\n return null;\n }\n }\n\n /**\n * Asynchronously detects the GPU information for Linux systems.\n * Tries to detect NVIDIA GPU first using 'nvidia-smi' command and if successful,\n * returns the GPU name, memory size, type as 'cuda', and NVIDIA driver version.\n * If NVIDIA detection fails, it falls back to checking for other GPUs using 'lspci | grep -i vga' command.\n * If no GPU is detected, it returns null.\n *\n * @returns {Promise<SystemGPU | null>} The detected GPU information or null if detection fails.\n */\n private async detectLinuxGPU(): Promise<SystemGPU | null> {\n try {\n // Try NVIDIA first\n const { stdout } = await execAsync(\n 'nvidia-smi --query-gpu=name,memory.total --format=csv,noheader'\n );\n if (stdout) {\n const [name, memoryStr] = stdout.split(',').map((s) => s.trim());\n const memory = Number.parseInt(memoryStr);\n\n return {\n name,\n memory,\n type: 'cuda',\n version: await this.getNvidiaDriverVersion(),\n };\n }\n } catch {\n // If nvidia-smi fails, check for other GPUs\n try {\n const { stdout } = await execAsync('lspci | grep -i vga');\n return {\n name: stdout.split(':').pop()?.trim() || 'Unknown GPU',\n type: 'none',\n };\n } catch (error) {\n logger.error('Linux GPU detection failed', { error });\n return null;\n }\n }\n return null;\n }\n\n /**\n * Asynchronously retrieves the driver version of the Nvidia GPU using the 'nvidia-smi' command.\n *\n * @returns A promise that resolves with the driver version as a string, or 'unknown' if an error occurs.\n */\n private async getNvidiaDriverVersion(): Promise<string> {\n try {\n const { stdout } = await execAsync(\n 'nvidia-smi --query-gpu=driver_version --format=csv,noheader'\n );\n return stdout.trim();\n } catch {\n return 'unknown';\n }\n }\n\n /**\n * Retrieves the supported backends based on the platform and GPU type.\n * @param {NodeJS.Platform} platform - The platform on which the code is running.\n * @param {SystemGPU | null} gpu - The GPU information, if available.\n * @returns {Promise<Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\">>} - An array of supported backends including 'cuda', 'metal', 'directml', and 'cpu'.\n */\n private async getSupportedBackends(\n platform: NodeJS.Platform,\n gpu: SystemGPU | null\n ): Promise<Array<'cuda' | 'metal' | 'directml' | 'cpu'>> {\n const backends: Array<'cuda' | 'metal' | 'directml' | 'cpu'> = ['cpu'];\n\n if (gpu) {\n switch (platform) {\n case 'darwin':\n backends.push('metal');\n break;\n case 'win32':\n if (gpu.type === 'cuda') {\n backends.push('cuda');\n }\n backends.push('directml');\n break;\n case 'linux':\n if (gpu.type === 'cuda') {\n backends.push('cuda');\n }\n break;\n }\n }\n\n return backends;\n }\n\n /**\n * Determines the recommended model size based on the system's CPU and GPU.\n * @param {SystemCPU} cpu - The system's CPU.\n * @param {SystemGPU | null} gpu - The system's GPU, if available.\n * @returns {\"small\" | \"medium\" | \"large\"} - The recommended model size (\"small\", \"medium\", or \"large\").\n */\n private getRecommendedModelSize(\n cpu: SystemCPU,\n gpu: SystemGPU | null\n ): 'small' | 'medium' | 'large' {\n // For Apple Silicon\n if (gpu?.isAppleSilicon) {\n return cpu.memory.total > 16 * 1024 * 1024 * 1024 ? 'medium' : 'small';\n }\n\n // For NVIDIA GPUs\n if (gpu?.type === 'cuda') {\n const gpuMemGB = (gpu.memory || 0) / 1024;\n if (gpuMemGB >= 16) return 'large';\n if (gpuMemGB >= 8) return 'medium';\n }\n\n // For systems with significant RAM but no powerful GPU\n if (cpu.memory.total > 32 * 1024 * 1024 * 1024) return 'medium';\n\n // Default to small model\n return 'small';\n }\n\n /**\n * Returns the SystemCapabilities of the PlatformManager.\n *\n * @returns {SystemCapabilities} The SystemCapabilities of the PlatformManager.\n * @throws {Error} if PlatformManager is not initialized.\n */\n getCapabilities(): SystemCapabilities {\n if (!this.capabilities) {\n throw new Error('PlatformManager not initialized');\n }\n return this.capabilities;\n }\n\n /**\n * Checks if the device's GPU is Apple Silicon.\n * @returns {boolean} True if the GPU is Apple Silicon, false otherwise.\n */\n isAppleSilicon(): boolean {\n return !!this.capabilities?.gpu?.isAppleSilicon;\n }\n\n /**\n * Checks if the current device has GPU support.\n * @returns {boolean} - Returns true if the device has GPU support, false otherwise.\n */\n hasGPUSupport(): boolean {\n return !!this.capabilities?.gpu;\n }\n\n /**\n * Checks if the system supports CUDA GPU for processing.\n *\n * @returns {boolean} True if the system supports CUDA, false otherwise.\n */\n supportsCUDA(): boolean {\n return this.capabilities?.gpu?.type === 'cuda';\n }\n\n /**\n * Check if the device supports Metal API for rendering graphics.\n * @returns {boolean} True if the device supports Metal, false otherwise.\n */\n supportsMetal(): boolean {\n return this.capabilities?.gpu?.type === 'metal';\n }\n\n /**\n * Check if the device supports DirectML for GPU acceleration.\n *\n * @returns {boolean} True if the device supports DirectML, false otherwise.\n */\n supportsDirectML(): boolean {\n return this.capabilities?.gpu?.type === 'directml';\n }\n\n /**\n * Get the recommended backend for computation based on the available capabilities.\n * @returns {\"cuda\" | \"metal\" | \"directml\" | \"cpu\"} The recommended backend for computation.\n * @throws {Error} Throws an error if PlatformManager is not initialized.\n */\n getRecommendedBackend(): 'cuda' | 'metal' | 'directml' | 'cpu' {\n if (!this.capabilities) {\n throw new Error('PlatformManager not initialized');\n }\n\n const { gpu, supportedBackends } = this.capabilities;\n\n if (gpu?.type === 'cuda') return 'cuda';\n if (gpu?.type === 'metal') return 'metal';\n if (supportedBackends.includes('directml')) return 'directml';\n return 'cpu';\n }\n}\n\n// Export a helper function to get the singleton instance\nexport const getPlatformManager = (): PlatformManager => {\n return PlatformManager.getInstance();\n};\n","import { logger } from '@elizaos/core';\nimport { AutoTokenizer, type PreTrainedTokenizer } from '@huggingface/transformers';\n\n// Import the MODEL_SPECS type from a new types file we'll create later\nimport type { ModelSpec } from '../types';\n\n/**\n * Represents a Tokenizer Manager which manages tokenizers for different models.\n * * @class TokenizerManager\n */\nexport class TokenizerManager {\n private static instance: TokenizerManager | null = null;\n private tokenizers: Map<string, PreTrainedTokenizer>;\n private cacheDir: string;\n private modelsDir: string;\n\n /**\n * Constructor for creating a new instance of the class.\n *\n * @param {string} cacheDir - The directory for caching data.\n * @param {string} modelsDir - The directory for storing models.\n */\n private constructor(cacheDir: string, modelsDir: string) {\n this.tokenizers = new Map();\n this.cacheDir = cacheDir;\n this.modelsDir = modelsDir;\n }\n\n /**\n * Get the singleton instance of TokenizerManager class. If the instance does not exist, it will create a new one.\n *\n * @param {string} cacheDir - The directory to cache the tokenizer models.\n * @param {string} modelsDir - The directory where tokenizer models are stored.\n * @returns {TokenizerManager} The singleton instance of TokenizerManager.\n */\n static getInstance(cacheDir: string, modelsDir: string): TokenizerManager {\n if (!TokenizerManager.instance) {\n TokenizerManager.instance = new TokenizerManager(cacheDir, modelsDir);\n }\n return TokenizerManager.instance;\n }\n\n /**\n * Asynchronously loads a tokenizer based on the provided ModelSpec configuration.\n *\n * @param {ModelSpec} modelConfig - The configuration object for the model to load the tokenizer for.\n * @returns {Promise<PreTrainedTokenizer>} - A promise that resolves to the loaded tokenizer.\n */\n async loadTokenizer(modelConfig: ModelSpec): Promise<PreTrainedTokenizer> {\n try {\n const tokenizerKey = `${modelConfig.tokenizer.type}-${modelConfig.tokenizer.name}`;\n logger.info('Loading tokenizer:', {\n key: tokenizerKey,\n name: modelConfig.tokenizer.name,\n type: modelConfig.tokenizer.type,\n modelsDir: this.modelsDir,\n cacheDir: this.cacheDir,\n });\n\n if (this.tokenizers.has(tokenizerKey)) {\n logger.info('Using cached tokenizer:', { key: tokenizerKey });\n const cachedTokenizer = this.tokenizers.get(tokenizerKey);\n if (!cachedTokenizer) {\n throw new Error(`Tokenizer ${tokenizerKey} exists in map but returned undefined`);\n }\n return cachedTokenizer;\n }\n\n // Check if models directory exists\n const fs = await import('node:fs');\n if (!fs.existsSync(this.modelsDir)) {\n logger.warn('Models directory does not exist, creating it:', this.modelsDir);\n fs.mkdirSync(this.modelsDir, { recursive: true });\n }\n\n logger.info(\n 'Initializing new tokenizer from HuggingFace with models directory:',\n this.modelsDir\n );\n\n try {\n const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {\n cache_dir: this.modelsDir,\n local_files_only: false,\n });\n\n this.tokenizers.set(tokenizerKey, tokenizer);\n logger.success('Tokenizer loaded successfully:', { key: tokenizerKey });\n return tokenizer;\n } catch (tokenizeError) {\n logger.error('Failed to load tokenizer from HuggingFace:', {\n error: tokenizeError instanceof Error ? tokenizeError.message : String(tokenizeError),\n stack: tokenizeError instanceof Error ? tokenizeError.stack : undefined,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n\n // Try again with local_files_only set to false and a longer timeout\n logger.info('Retrying tokenizer loading...');\n const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {\n cache_dir: this.modelsDir,\n local_files_only: false,\n });\n\n this.tokenizers.set(tokenizerKey, tokenizer);\n logger.success('Tokenizer loaded successfully on retry:', {\n key: tokenizerKey,\n });\n return tokenizer;\n }\n } catch (error) {\n logger.error('Failed to load tokenizer:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n model: modelConfig.name,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n\n /**\n * Encodes the given text using the specified tokenizer model configuration.\n *\n * @param {string} text - The text to encode.\n * @param {ModelSpec} modelConfig - The configuration for the model tokenizer.\n * @returns {Promise<number[]>} - An array of integers representing the encoded text.\n * @throws {Error} - If the text encoding fails, an error is thrown.\n */\n async encode(text: string, modelConfig: ModelSpec): Promise<number[]> {\n try {\n logger.info('Encoding text with tokenizer:', {\n length: text.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n\n const tokenizer = await this.loadTokenizer(modelConfig);\n\n logger.info('Tokenizer loaded, encoding text...');\n const encoded = await tokenizer.encode(text, {\n add_special_tokens: true,\n return_token_type_ids: false,\n });\n\n logger.info('Text encoded successfully:', {\n tokenCount: encoded.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n return encoded;\n } catch (error) {\n logger.error('Text encoding failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n textLength: text.length,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously decodes an array of tokens using a tokenizer based on the provided ModelSpec.\n *\n * @param {number[]} tokens - The array of tokens to be decoded.\n * @param {ModelSpec} modelConfig - The ModelSpec object containing information about the model and tokenizer to be used.\n * @returns {Promise<string>} - A Promise that resolves with the decoded text.\n * @throws {Error} - If an error occurs during token decoding.\n */\n async decode(tokens: number[], modelConfig: ModelSpec): Promise<string> {\n try {\n logger.info('Decoding tokens with tokenizer:', {\n count: tokens.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n\n const tokenizer = await this.loadTokenizer(modelConfig);\n\n logger.info('Tokenizer loaded, decoding tokens...');\n const decoded = await tokenizer.decode(tokens, {\n skip_special_tokens: true,\n clean_up_tokenization_spaces: true,\n });\n\n logger.info('Tokens decoded successfully:', {\n textLength: decoded.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n return decoded;\n } catch (error) {\n logger.error('Token decoding failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n tokenCount: tokens.length,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n}\n","import { exec } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport { logger } from '@elizaos/core';\n\nconst execAsync = promisify(exec);\n\n// Lazy load whisper-node to avoid ESM/CommonJS issues\nlet whisperModule: any = null;\nasync function getWhisper() {\n if (!whisperModule) {\n // Dynamic import for CommonJS module\n const module = await import('whisper-node');\n // The module exports an object with a whisper property\n whisperModule = (module as any).whisper;\n }\n return whisperModule;\n}\n\n/**\n * Interface representing the result of a transcription process.\n * @interface\n * @property {string} text - The transcribed text.\n */\ninterface TranscriptionResult {\n text: string;\n}\n\n/**\n * Class representing a TranscribeManager.\n *\n * @property {TranscribeManager | null} instance - The singleton instance of the TranscribeManager class.\n * @property {string} cacheDir - The directory path for caching transcribed files.\n * @property {boolean} ffmpegAvailable - Flag indicating if ffmpeg is available for audio processing.\n * @property {string | null} ffmpegVersion - The version of ffmpeg if available.\n * @property {string | null} ffmpegPath - The path to the ffmpeg executable.\n * @property {boolean} ffmpegInitialized - Flag indicating if ffmpeg has been initialized.\n *\n * @constructor\n * Creates an instance of TranscribeManager with the specified cache directory.\n */\nexport class TranscribeManager {\n private static instance: TranscribeManager | null = null;\n private cacheDir: string;\n private ffmpegAvailable = false;\n private ffmpegVersion: string | null = null;\n private ffmpegPath: string | null = null;\n private ffmpegInitialized = false;\n\n /**\n * Constructor for TranscribeManager class.\n *\n * @param {string} cacheDir - The directory path for storing cached files.\n */\n private constructor(cacheDir: string) {\n this.cacheDir = path.join(cacheDir, 'whisper');\n logger.debug('Initializing TranscribeManager', {\n cacheDir: this.cacheDir,\n timestamp: new Date().toISOString(),\n });\n this.ensureCacheDirectory();\n }\n\n /**\n * Ensures that FFmpeg is initialized and available for use.\n * @returns {Promise<boolean>} A promise that resolves to a boolean value indicating if FFmpeg is available.\n */\n public async ensureFFmpeg(): Promise<boolean> {\n if (!this.ffmpegInitialized) {\n try {\n await this.initializeFFmpeg();\n this.ffmpegInitialized = true;\n } catch (error) {\n logger.error('FFmpeg initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n timestamp: new Date().toISOString(),\n });\n return false;\n }\n }\n return this.ffmpegAvailable;\n }\n\n /**\n * Checks if FFmpeg is available.\n * @returns {boolean} True if FFmpeg is available, false otherwise.\n */\n public isFFmpegAvailable(): boolean {\n return this.ffmpegAvailable;\n }\n\n /**\n * Asynchronously retrieves the FFmpeg version if it hasn't been fetched yet.\n * If the FFmpeg version has already been fetched, it will return the stored version.\n * @returns A Promise that resolves with the FFmpeg version as a string, or null if the version is not available.\n */\n public async getFFmpegVersion(): Promise<string | null> {\n if (!this.ffmpegVersion) {\n await this.fetchFFmpegVersion();\n }\n return this.ffmpegVersion;\n }\n\n /**\n * Fetches the FFmpeg version by executing the command \"ffmpeg -version\".\n * Updates the class property ffmpegVersion with the retrieved version.\n * Logs the FFmpeg version information or error message.\n * @returns {Promise<void>} A Promise that resolves once the FFmpeg version is fetched and logged.\n */\n private async fetchFFmpegVersion(): Promise<void> {\n try {\n const { stdout } = await execAsync('ffmpeg -version');\n this.ffmpegVersion = stdout.split('\\n')[0];\n logger.info('FFmpeg version:', {\n version: this.ffmpegVersion,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n this.ffmpegVersion = null;\n logger.error('Failed to get FFmpeg version:', {\n error: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Initializes FFmpeg by performing the following steps:\n * 1. Checks for FFmpeg availability in PATH\n * 2. Retrieves FFmpeg version information\n * 3. Verifies FFmpeg capabilities\n *\n * If FFmpeg is available, logs a success message with version, path, and timestamp.\n * If FFmpeg is not available, logs installation instructions.\n *\n * @returns A Promise that resolves once FFmpeg has been successfully initialized\n */\n private async initializeFFmpeg(): Promise<void> {\n try {\n // First check if ffmpeg exists in PATH\n await this.checkFFmpegAvailability();\n\n if (this.ffmpegAvailable) {\n // Get FFmpeg version info\n await this.fetchFFmpegVersion();\n\n // Verify FFmpeg capabilities\n await this.verifyFFmpegCapabilities();\n\n logger.success('FFmpeg initialized successfully', {\n version: this.ffmpegVersion,\n path: this.ffmpegPath,\n timestamp: new Date().toISOString(),\n });\n } else {\n this.logFFmpegInstallInstructions();\n }\n } catch (error) {\n this.ffmpegAvailable = false;\n logger.error('FFmpeg initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n timestamp: new Date().toISOString(),\n });\n this.logFFmpegInstallInstructions();\n }\n }\n\n /**\n * Asynchronously checks for the availability of FFmpeg in the system by executing a command to find the FFmpeg location.\n * Updates the class properties `ffmpegPath` and `ffmpegAvailable` accordingly.\n * Logs relevant information such as FFmpeg location and potential errors using the logger.\n *\n * @returns A Promise that resolves with no value upon completion.\n */\n private async checkFFmpegAvailability(): Promise<void> {\n try {\n const { stdout, stderr } = await execAsync('which ffmpeg || where ffmpeg');\n this.ffmpegPath = stdout.trim();\n this.ffmpegAvailable = true;\n logger.info('FFmpeg found at:', {\n path: this.ffmpegPath,\n stderr: stderr ? stderr.trim() : undefined,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n this.ffmpegAvailable = false;\n this.ffmpegPath = null;\n logger.error('FFmpeg not found in PATH:', {\n error: error instanceof Error ? error.message : String(error),\n stderr: error instanceof Error && 'stderr' in error ? error.stderr : undefined,\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Verifies the FFmpeg capabilities by checking if FFmpeg supports the required codecs and formats.\n *\n * @returns {Promise<void>} A Promise that resolves if FFmpeg has the required codecs, otherwise rejects with an error message.\n */\n private async verifyFFmpegCapabilities(): Promise<void> {\n try {\n // Check if FFmpeg supports required codecs and formats\n const { stdout } = await execAsync('ffmpeg -codecs');\n const hasRequiredCodecs = stdout.includes('pcm_s16le') && stdout.includes('wav');\n\n if (!hasRequiredCodecs) {\n throw new Error('FFmpeg installation missing required codecs (pcm_s16le, wav)');\n }\n\n // logger.info(\"FFmpeg capabilities verified\", {\n // hasRequiredCodecs,\n // timestamp: new Date().toISOString()\n // });\n } catch (error) {\n logger.error('FFmpeg capabilities verification failed:', {\n error: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n }\n\n /**\n * Logs instructions on how to install FFmpeg if it is not properly installed.\n */\n private logFFmpegInstallInstructions(): void {\n logger.warn('FFmpeg is required but not properly installed. Please install FFmpeg:', {\n instructions: {\n mac: 'brew install ffmpeg',\n ubuntu: 'sudo apt-get install ffmpeg',\n windows: 'choco install ffmpeg',\n manual: 'Download from https://ffmpeg.org/download.html',\n },\n requiredVersion: '4.0 or later',\n requiredCodecs: ['pcm_s16le', 'wav'],\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Gets the singleton instance of TranscribeManager, creates a new instance if it doesn't exist.\n *\n * @param {string} cacheDir - The directory path for caching transcriptions.\n * @returns {TranscribeManager} The singleton instance of TranscribeManager.\n */\n public static getInstance(cacheDir: string): TranscribeManager {\n if (!TranscribeManager.instance) {\n TranscribeManager.instance = new TranscribeManager(cacheDir);\n }\n return TranscribeManager.instance;\n }\n\n /**\n * Ensures that the cache directory exists. If it doesn't exist,\n * creates the directory using fs.mkdirSync with recursive set to true.\n * @returns {void}\n */\n private ensureCacheDirectory(): void {\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n // logger.info(\"Created whisper cache directory:\", this.cacheDir);\n }\n }\n\n /**\n * Converts an audio file to WAV format using FFmpeg.\n *\n * @param {string} inputPath - The input path of the audio file to convert.\n * @param {string} outputPath - The output path where the converted WAV file will be saved.\n * @returns {Promise<void>} A Promise that resolves when the conversion is completed.\n * @throws {Error} If FFmpeg is not installed or not properly configured, or if the audio conversion fails.\n */\n private async convertToWav(inputPath: string, outputPath: string): Promise<void> {\n if (!this.ffmpegAvailable) {\n throw new Error(\n 'FFmpeg is not installed or not properly configured. Please install FFmpeg to use audio transcription.'\n );\n }\n\n try {\n // Add -loglevel error to suppress FFmpeg output unless there's an error\n const { stderr } = await execAsync(\n `ffmpeg -y -loglevel error -i \"${inputPath}\" -acodec pcm_s16le -ar 16000 -ac 1 \"${outputPath}\"`\n );\n\n if (stderr) {\n logger.warn('FFmpeg conversion error:', {\n stderr,\n inputPath,\n outputPath,\n timestamp: new Date().toISOString(),\n });\n }\n\n if (!fs.existsSync(outputPath)) {\n throw new Error('WAV file was not created successfully');\n }\n } catch (error) {\n logger.error('Audio conversion failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n command: `ffmpeg -y -loglevel error -i \"${inputPath}\" -acodec pcm_s16le -ar 16000 -ac 1 \"${outputPath}\"`,\n ffmpegAvailable: this.ffmpegAvailable,\n ffmpegVersion: this.ffmpegVersion,\n ffmpegPath: this.ffmpegPath,\n timestamp: new Date().toISOString(),\n });\n throw new Error(\n `Failed to convert audio to WAV format: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Asynchronously preprocesses the audio by converting the provided audio buffer into a WAV file.\n * If FFmpeg is not installed, an error is thrown.\n *\n * @param {Buffer} audioBuffer The audio buffer to preprocess\n * @returns {Promise<string>} The path to the preprocessed WAV file\n * @throws {Error} If FFmpeg is not installed or if audio preprocessing fails\n */\n private async preprocessAudio(audioBuffer: Buffer): Promise<string> {\n if (!this.ffmpegAvailable) {\n throw new Error('FFmpeg is not installed. Please install FFmpeg to use audio transcription.');\n }\n\n try {\n // Check if the buffer is already a WAV file\n const isWav =\n audioBuffer.length > 4 &&\n audioBuffer.toString('ascii', 0, 4) === 'RIFF' &&\n audioBuffer.length > 12 &&\n audioBuffer.toString('ascii', 8, 12) === 'WAVE';\n\n // Use appropriate extension based on format detection\n const extension = isWav ? '.wav' : '';\n const tempInputFile = path.join(this.cacheDir, `temp_input_${Date.now()}${extension}`);\n const tempWavFile = path.join(this.cacheDir, `temp_${Date.now()}.wav`);\n\n // logger.info(\"Creating temporary files\", {\n // inputFile: tempInputFile,\n // wavFile: tempWavFile,\n // bufferSize: audioBuffer.length,\n // timestamp: new Date().toISOString()\n // });\n\n // Write buffer to temporary file\n fs.writeFileSync(tempInputFile, audioBuffer);\n // logger.info(\"Temporary input file created\", {\n // path: tempInputFile,\n // size: audioBuffer.length,\n // timestamp: new Date().toISOString()\n // });\n\n // If already WAV with correct format, skip conversion\n if (isWav) {\n // Check if it's already in the correct format (16kHz, mono, 16-bit)\n try {\n const { stdout } = await execAsync(\n `ffprobe -v error -show_entries stream=sample_rate,channels,bits_per_raw_sample -of json \"${tempInputFile}\"`\n );\n const probeResult = JSON.parse(stdout);\n const stream = probeResult.streams?.[0];\n\n if (\n stream?.sample_rate === '16000' &&\n stream?.channels === 1 &&\n (stream?.bits_per_raw_sample === 16 || stream?.bits_per_raw_sample === undefined)\n ) {\n // Already in correct format, just rename\n fs.renameSync(tempInputFile, tempWavFile);\n return tempWavFile;\n }\n } catch (probeError) {\n // If probe fails, continue with conversion\n logger.debug('FFprobe failed, continuing with conversion:', probeError);\n }\n }\n\n // Convert to WAV format\n await this.convertToWav(tempInputFile, tempWavFile);\n\n // Clean up the input file\n if (fs.existsSync(tempInputFile)) {\n fs.unlinkSync(tempInputFile);\n // logger.info(\"Temporary input file cleaned up\", {\n // path: tempInputFile,\n // timestamp: new Date().toISOString()\n // });\n }\n\n return tempWavFile;\n } catch (error) {\n logger.error('Audio preprocessing failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n ffmpegAvailable: this.ffmpegAvailable,\n timestamp: new Date().toISOString(),\n });\n throw new Error(\n `Failed to preprocess audio: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Transcribes the audio buffer to text using whisper.\n *\n * @param {Buffer} audioBuffer The audio buffer to transcribe.\n * @returns {Promise<TranscriptionResult>} A promise that resolves with the transcription result.\n * @throws {Error} If FFmpeg is not installed or properly configured.\n */\n\n public async transcribe(audioBuffer: Buffer): Promise<TranscriptionResult> {\n await this.ensureFFmpeg();\n\n if (!this.ffmpegAvailable) {\n throw new Error(\n 'FFmpeg is not installed or not properly configured. Please install FFmpeg to use audio transcription.'\n );\n }\n\n try {\n // Preprocess audio to WAV format\n const wavFile = await this.preprocessAudio(audioBuffer);\n\n logger.info('Starting transcription with whisper...');\n\n let segments;\n try {\n // Get the whisper function\n const whisper = await getWhisper();\n\n // Transcribe using whisper-node\n segments = await whisper(wavFile, {\n modelName: 'tiny',\n modelPath: path.join(this.cacheDir, 'models'), // Specify where to store models\n whisperOptions: {\n language: 'en',\n word_timestamps: false, // We don't need word-level timestamps\n },\n });\n } catch (whisperError) {\n // Check if it's a model download issue\n const errorMessage =\n whisperError instanceof Error ? whisperError.message : String(whisperError);\n if (errorMessage.includes('not found') || errorMessage.includes('download')) {\n logger.error('Whisper model not found. Please run: npx whisper-node download');\n throw new Error(\n 'Whisper model not found. Please install it with: npx whisper-node download'\n );\n }\n\n // For other errors, log and rethrow\n logger.error('Whisper transcription error:', whisperError);\n throw whisperError;\n }\n\n // Clean up temporary WAV file\n if (fs.existsSync(wavFile)) {\n fs.unlinkSync(wavFile);\n logger.info('Temporary WAV file cleaned up');\n }\n\n // Check if segments is valid\n if (!segments || !Array.isArray(segments)) {\n logger.warn('Whisper returned no segments (likely silence or very short audio)');\n // Return empty transcription for silent/empty audio\n return { text: '' };\n }\n\n // Handle empty segments array\n if (segments.length === 0) {\n logger.warn('No speech detected in audio');\n return { text: '' };\n }\n\n // Combine all segments into a single text\n const cleanText = segments\n .map((segment: any) => segment.speech?.trim() || '')\n .filter((text: string) => text) // Remove empty segments\n .join(' ');\n\n logger.success('Transcription complete:', {\n textLength: cleanText.length,\n segmentCount: segments.length,\n timestamp: new Date().toISOString(),\n });\n\n return { text: cleanText };\n } catch (error) {\n logger.error('Transcription failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n ffmpegAvailable: this.ffmpegAvailable,\n });\n throw error;\n }\n }\n}\n","import { logger } from '@elizaos/core';\nimport { pipeline, type TextToAudioPipeline } from '@huggingface/transformers';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fetch } from 'undici';\nimport { MODEL_SPECS } from '../types';\nimport { PassThrough, Readable } from 'node:stream';\n\n// Audio Utils\n\n/**\n * Generates a WAV file header based on the provided audio parameters.\n * @param {number} audioLength - The length of the audio data in bytes.\n * @param {number} sampleRate - The sample rate of the audio.\n * @param {number} [channelCount=1] - The number of channels (default is 1).\n * @param {number} [bitsPerSample=16] - The number of bits per sample (default is 16).\n * @returns {Buffer} The WAV file header as a Buffer object.\n */\nfunction getWavHeader(\n audioLength: number,\n sampleRate: number,\n channelCount = 1,\n bitsPerSample = 16\n): Buffer {\n const wavHeader = Buffer.alloc(44);\n wavHeader.write('RIFF', 0);\n wavHeader.writeUInt32LE(36 + audioLength, 4); // Length of entire file in bytes minus 8\n wavHeader.write('WAVE', 8);\n wavHeader.write('fmt ', 12);\n wavHeader.writeUInt32LE(16, 16); // Length of format data\n wavHeader.writeUInt16LE(1, 20); // Type of format (1 is PCM)\n wavHeader.writeUInt16LE(channelCount, 22); // Number of channels\n wavHeader.writeUInt32LE(sampleRate, 24); // Sample rate\n wavHeader.writeUInt32LE((sampleRate * bitsPerSample * channelCount) / 8, 28); // Byte rate\n wavHeader.writeUInt16LE((bitsPerSample * channelCount) / 8, 32); // Block align ((BitsPerSample * Channels) / 8)\n wavHeader.writeUInt16LE(bitsPerSample, 34); // Bits per sample\n wavHeader.write('data', 36); // Data chunk header\n wavHeader.writeUInt32LE(audioLength, 40); // Data chunk size\n return wavHeader;\n}\n\n/**\n * Prepends a WAV header to a readable stream of audio data.\n *\n * @param {Readable} readable - The readable stream containing the audio data.\n * @param {number} audioLength - The length of the audio data in bytes.\n * @param {number} sampleRate - The sample rate of the audio data.\n * @param {number} [channelCount=1] - The number of channels in the audio data (default is 1).\n * @param {number} [bitsPerSample=16] - The number of bits per sample in the audio data (default is 16).\n * @returns {PassThrough} A new pass-through stream with the WAV header prepended to the audio data.\n */\nfunction prependWavHeader(\n readable: Readable,\n audioLength: number,\n sampleRate: number,\n channelCount = 1,\n bitsPerSample = 16\n): PassThrough {\n const wavHeader = getWavHeader(audioLength, sampleRate, channelCount, bitsPerSample);\n let pushedHeader = false;\n const passThrough = new PassThrough();\n readable.on('data', (data: Buffer) => {\n if (!pushedHeader) {\n passThrough.push(wavHeader);\n pushedHeader = true;\n }\n passThrough.push(data);\n });\n readable.on('end', () => {\n passThrough.end();\n });\n return passThrough;\n}\n\n/**\n * Class representing a Text-to-Speech Manager using Transformers.js\n */\nexport class TTSManager {\n private static instance: TTSManager | null = null;\n private cacheDir: string;\n private synthesizer: TextToAudioPipeline | null = null;\n private defaultSpeakerEmbedding: Float32Array | null = null;\n private initialized = false;\n private initializingPromise: Promise<void> | null = null;\n\n private constructor(cacheDir: string) {\n this.cacheDir = path.join(cacheDir, 'tts');\n this.ensureCacheDirectory();\n logger.debug('TTSManager using Transformers.js initialized');\n }\n\n public static getInstance(cacheDir: string): TTSManager {\n if (!TTSManager.instance) {\n TTSManager.instance = new TTSManager(cacheDir);\n }\n return TTSManager.instance;\n }\n\n private ensureCacheDirectory(): void {\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n logger.debug('Created TTS cache directory:', this.cacheDir);\n }\n }\n\n private async initialize(): Promise<void> {\n // Guard against concurrent calls: if an initialization is already in progress, return its promise.\n if (this.initializingPromise) {\n logger.debug('TTS initialization already in progress, awaiting existing promise.');\n return this.initializingPromise;\n }\n\n // If already initialized, no need to do anything further.\n if (this.initialized) {\n logger.debug('TTS already initialized.');\n return;\n }\n\n // Start the initialization process.\n // The promise is stored in this.initializingPromise and cleared in the finally block.\n this.initializingPromise = (async () => {\n try {\n logger.info('Initializing TTS with Transformers.js backend...');\n\n const ttsModelSpec = MODEL_SPECS.tts.default;\n if (!ttsModelSpec) {\n throw new Error('Default TTS model specification not found in MODEL_SPECS.');\n }\n const modelName = ttsModelSpec.modelId;\n const speakerEmbeddingUrl = ttsModelSpec.defaultSpeakerEmbeddingUrl;\n\n // 1. Load the TTS Pipeline\n logger.info(`Loading TTS pipeline for model: ${modelName}`);\n this.synthesizer = await pipeline('text-to-audio', modelName);\n logger.success(`TTS pipeline loaded successfully for model: ${modelName}`);\n\n // 2. Load Default Speaker Embedding (if specified)\n if (speakerEmbeddingUrl) {\n const embeddingFilename = path.basename(new URL(speakerEmbeddingUrl).pathname);\n const embeddingPath = path.join(this.cacheDir, embeddingFilename);\n\n if (fs.existsSync(embeddingPath)) {\n logger.info('Loading default speaker embedding from cache...');\n const buffer = fs.readFileSync(embeddingPath);\n this.defaultSpeakerEmbedding = new Float32Array(\n buffer.buffer,\n buffer.byteOffset,\n buffer.length / Float32Array.BYTES_PER_ELEMENT\n );\n logger.success('Default speaker embedding loaded from cache.');\n } else {\n logger.info(`Downloading default speaker embedding from: ${speakerEmbeddingUrl}`);\n const response = await fetch(speakerEmbeddingUrl);\n if (!response.ok) {\n throw new Error(`Failed to download speaker embedding: ${response.statusText}`);\n }\n const buffer = await response.arrayBuffer();\n this.defaultSpeakerEmbedding = new Float32Array(buffer);\n fs.writeFileSync(embeddingPath, Buffer.from(buffer));\n logger.success('Default speaker embedding downloaded and cached.');\n }\n } else {\n logger.warn(\n `No default speaker embedding URL specified for model ${modelName}. Speaker control may be limited.`\n );\n this.defaultSpeakerEmbedding = null;\n }\n\n // Check synthesizer as embedding might be optional for some models\n if (!this.synthesizer) {\n throw new Error('TTS initialization failed: Pipeline not loaded.');\n }\n\n logger.success('TTS initialization complete (Transformers.js)');\n this.initialized = true;\n } catch (error) {\n logger.error('TTS (Transformers.js) initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n this.initialized = false;\n this.synthesizer = null;\n this.defaultSpeakerEmbedding = null;\n throw error; // Propagate error to reject the initializingPromise\n } finally {\n // Clear the promise once initialization is complete (successfully or not)\n this.initializingPromise = null;\n logger.debug('TTS initializingPromise cleared after completion/failure.');\n }\n })();\n\n return this.initializingPromise;\n }\n\n /**\n * Asynchronously generates speech from a given text using the Transformers.js pipeline.\n * @param {string} text - The text to generate speech from.\n * @returns {Promise<Readable>} A promise that resolves to a Readable stream containing the generated WAV audio data.\n * @throws {Error} If the TTS model is not initialized or if generation fails.\n */\n public async generateSpeech(text: string): Promise<Readable> {\n try {\n await this.initialize();\n\n // Check synthesizer is initialized (embedding might be null but handled in synthesizer call)\n if (!this.synthesizer) {\n throw new Error('TTS Manager not properly initialized.');\n }\n\n logger.info('Starting speech generation with Transformers.js for text:', {\n text: text.substring(0, 50) + '...',\n });\n\n // Generate audio using the pipeline\n const output = await this.synthesizer(text, {\n // Pass embedding only if it was loaded\n ...(this.defaultSpeakerEmbedding && {\n speaker_embeddings: this.defaultSpeakerEmbedding,\n }),\n });\n\n // output is { audio: Float32Array, sampling_rate: number }\n const audioFloat32 = output.audio;\n const samplingRate = output.sampling_rate;\n\n logger.info('Raw audio data received from pipeline:', {\n samplingRate,\n length: audioFloat32.length,\n });\n\n if (!audioFloat32 || audioFloat32.length === 0) {\n throw new Error('TTS pipeline generated empty audio output.');\n }\n\n // Convert Float32Array to Int16 Buffer (standard PCM for WAV)\n const pcmData = new Int16Array(audioFloat32.length);\n for (let i = 0; i < audioFloat32.length; i++) {\n const s = Math.max(-1, Math.min(1, audioFloat32[i])); // Clamp to [-1, 1]\n pcmData[i] = s < 0 ? s * 0x8000 : s * 0x7fff; // Convert to 16-bit [-32768, 32767]\n }\n const audioBuffer = Buffer.from(pcmData.buffer);\n\n logger.info('Audio data converted to 16-bit PCM Buffer:', {\n byteLength: audioBuffer.length,\n });\n\n // Create WAV format stream\n // Use samplingRate from the pipeline output\n const audioStream = prependWavHeader(\n Readable.from(audioBuffer),\n audioBuffer.length, // Pass buffer length in bytes\n samplingRate,\n 1, // Number of channels (assuming mono)\n 16 // Bit depth\n );\n\n logger.success('Speech generation complete (Transformers.js)');\n return audioStream;\n } catch (error) {\n logger.error('Transformers.js speech generation failed:', {\n error: error instanceof Error ? error.message : String(error),\n text: text.substring(0, 50) + '...',\n stack: error instanceof Error ? error.stack : undefined,\n });\n throw error;\n }\n }\n}\n","import { existsSync } from 'node:fs';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { logger } from '@elizaos/core';\nimport {\n AutoProcessor,\n AutoTokenizer,\n Florence2ForConditionalGeneration,\n type Florence2Processor,\n type PreTrainedTokenizer,\n type ProgressCallback,\n type ProgressInfo,\n RawImage,\n type Tensor,\n env,\n} from '@huggingface/transformers';\nimport { MODEL_SPECS } from '../types';\nimport { DownloadManager } from './downloadManager';\n\n// Define valid types based on HF transformers types\n/**\n * Defines the type 'DeviceType' which can take one of the three string values: 'cpu', 'gpu', or 'auto'\n */\ntype DeviceType = 'cpu' | 'gpu' | 'auto';\n/**\n * Represents the available data types options.\n */\ntype DTypeType = 'fp32' | 'fp16' | 'auto';\n\n/**\n * Interface for platform configuration options.\n * @typedef {Object} PlatformConfig\n * @property {DeviceType} device - The type of device to use.\n * @property {DTypeType} dtype - The data type to use.\n * @property {boolean} useOnnx - Flag indicating whether to use ONNX for processing.\n */\ninterface PlatformConfig {\n device: DeviceType;\n dtype: DTypeType;\n useOnnx: boolean;\n}\n\n/**\n * Represents a model component with a name, type, and optionally a data type.\n * @interface ModelComponent\n * @property { string } name - The name of the model component.\n * @property { string } type - The type of the model component.\n * @property { DTypeType } [dtype] - The data type of the model component (optional).\n */\ninterface ModelComponent {\n name: string;\n type: string;\n dtype?: DTypeType;\n}\n\n/**\n * Class representing a VisionManager.\n * @property {VisionManager | null} instance - The static instance of VisionManager.\n * @property {Florence2ForConditionalGeneration | null} model - The model for conditional generation.\n * @property {Florence2Processor | null} processor - The processor for Florence2.\n * @property {PreTrainedTokenizer | null} tokenizer - The pre-trained tokenizer.\n * @property {string} modelsDir - The directory for models.\n * @property {string} cacheDir - The directory for caching.\n * @property {boolean} initialized - Flag indicating if the VisionManager has been initialized.\n * @property {DownloadManager} downloadManager - The manager for downloading.\n */\nexport class VisionManager {\n private static instance: VisionManager | null = null;\n private model: Florence2ForConditionalGeneration | null = null;\n private processor: Florence2Processor | null = null;\n private tokenizer: PreTrainedTokenizer | null = null;\n private modelsDir: string;\n private cacheDir: string;\n private initialized = false;\n private downloadManager: DownloadManager;\n private modelDownloaded = false;\n private tokenizerDownloaded = false;\n private processorDownloaded = false;\n private platformConfig: PlatformConfig;\n private modelComponents: ModelComponent[] = [\n { name: 'embed_tokens', type: 'embeddings' },\n { name: 'vision_encoder', type: 'encoder' },\n { name: 'decoder_model_merged', type: 'decoder' },\n { name: 'encoder_model', type: 'encoder' },\n ];\n\n /**\n * Constructor for VisionManager class.\n *\n * @param {string} cacheDir - The directory path for caching vision models.\n */\n private constructor(cacheDir: string) {\n this.modelsDir = path.join(path.dirname(cacheDir), 'models', 'vision');\n this.cacheDir = cacheDir;\n this.ensureModelsDirExists();\n this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);\n this.platformConfig = this.getPlatformConfig();\n logger.debug('VisionManager initialized');\n }\n\n /**\n * Retrieves the platform configuration based on the operating system and architecture.\n * @returns {PlatformConfig} The platform configuration object with device, dtype, and useOnnx properties.\n */\n private getPlatformConfig(): PlatformConfig {\n const platform = os.platform();\n const arch = os.arch();\n\n // Default configuration\n let config: PlatformConfig = {\n device: 'cpu',\n dtype: 'fp32',\n useOnnx: true,\n };\n\n if (platform === 'darwin' && (arch === 'arm64' || arch === 'aarch64')) {\n // Apple Silicon\n config = {\n device: 'gpu',\n dtype: 'fp16',\n useOnnx: true,\n };\n } else if (platform === 'win32' || platform === 'linux') {\n // Windows or Linux with CUDA\n const hasCuda = process.env.CUDA_VISIBLE_DEVICES !== undefined;\n if (hasCuda) {\n config = {\n device: 'gpu',\n dtype: 'fp16',\n useOnnx: true,\n };\n }\n }\n return config;\n }\n\n /**\n * Ensures that the models directory exists. If it does not exist, it creates the directory.\n */\n private ensureModelsDirExists(): void {\n if (!existsSync(this.modelsDir)) {\n logger.debug(`Creating models directory at: ${this.modelsDir}`);\n fs.mkdirSync(this.modelsDir, { recursive: true });\n }\n }\n\n /**\n * Returns the singleton instance of VisionManager.\n * If an instance does not already exist, a new instance is created with the specified cache directory.\n *\n * @param {string} cacheDir - The directory where cache files will be stored.\n *\n * @returns {VisionManager} The singleton instance of VisionManager.\n */\n public static getInstance(cacheDir: string): VisionManager {\n if (!VisionManager.instance) {\n VisionManager.instance = new VisionManager(cacheDir);\n }\n return VisionManager.instance;\n }\n\n /**\n * Check if the cache exists for the specified model or tokenizer or processor.\n * @param {string} modelId - The ID of the model.\n * @param {\"model\" | \"tokenizer\" | \"processor\"} type - The type of the cache (\"model\", \"tokenizer\", or \"processor\").\n * @returns {boolean} - Returns true if cache exists, otherwise returns false.\n */\n private checkCacheExists(modelId: string, type: 'model' | 'tokenizer' | 'processor'): boolean {\n const modelPath = path.join(this.modelsDir, modelId.replace('/', '--'), type);\n if (existsSync(modelPath)) {\n logger.info(`${type} found at: ${modelPath}`);\n return true;\n }\n return false;\n }\n\n /**\n * Configures the model components based on the platform and architecture.\n * Sets the default data type (dtype) for components based on platform capabilities.\n * Updates all component dtypes to match the default dtype.\n */\n private configureModelComponents(): void {\n const platform = os.platform();\n const arch = os.arch();\n\n // Set dtype based on platform capabilities\n let defaultDtype: DTypeType = 'fp32';\n\n if (platform === 'darwin' && (arch === 'arm64' || arch === 'aarch64')) {\n // Apple Silicon can handle fp16\n defaultDtype = 'fp16';\n } else if (\n (platform === 'win32' || platform === 'linux') &&\n process.env.CUDA_VISIBLE_DEVICES !== undefined\n ) {\n // CUDA-enabled systems can handle fp16\n defaultDtype = 'fp16';\n }\n\n // Update all component dtypes\n this.modelComponents = this.modelComponents.map((component) => ({\n ...component,\n dtype: defaultDtype,\n }));\n\n logger.info('Model components configured with dtype:', {\n platform,\n arch,\n defaultDtype,\n components: this.modelComponents.map((c) => `${c.name}: ${c.dtype}`),\n });\n }\n\n /**\n * Get the model configuration based on the input component name.\n * @param {string} componentName - The name of the component to retrieve the configuration for.\n * @returns {object} The model configuration object containing device, dtype, and cache_dir.\n */\n private getModelConfig(componentName: string) {\n const component = this.modelComponents.find((c) => c.name === componentName);\n return {\n device: this.platformConfig.device,\n dtype: component?.dtype || 'fp32',\n cache_dir: this.modelsDir,\n };\n }\n\n /**\n * Asynchronous method to initialize the vision model by loading Florence2 model, vision tokenizer, and vision processor.\n *\n * @returns {Promise<void>} - Promise that resolves once the initialization process is completed.\n * @throws {Error} - If there is an error during the initialization process.\n */\n private async initialize() {\n try {\n if (this.initialized) {\n logger.info('Vision model already initialized, skipping initialization');\n return;\n }\n\n logger.info('Starting vision model initialization...');\n const modelSpec = MODEL_SPECS.vision;\n\n // Configure environment\n logger.info('Configuring environment for vision model...');\n env.allowLocalModels = true;\n env.allowRemoteModels = true;\n\n // Configure ONNX backend\n if (this.platformConfig.useOnnx) {\n env.backends.onnx.enabled = true;\n env.backends.onnx.logLevel = 'info';\n }\n\n // logger.info(\"Vision model configuration:\", {\n // modelId: modelSpec.modelId,\n // modelsDir: this.modelsDir,\n // allowLocalModels: env.allowLocalModels,\n // allowRemoteModels: env.allowRemoteModels,\n // platform: this.platformConfig\n // });\n\n // Initialize model with detailed logging\n logger.info('Loading Florence2 model...');\n try {\n let lastProgress = -1;\n const modelCached = this.checkCacheExists(modelSpec.modelId, 'model');\n\n const model = await Florence2ForConditionalGeneration.from_pretrained(modelSpec.modelId, {\n device: 'cpu',\n cache_dir: this.modelsDir,\n local_files_only: modelCached,\n revision: 'main',\n progress_callback: ((progressInfo: ProgressInfo) => {\n if (modelCached || this.modelDownloaded) return;\n const progress =\n 'progress' in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;\n const currentProgress = Math.round(progress * 100);\n if (currentProgress > lastProgress + 9 || currentProgress === 100) {\n lastProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor((currentProgress / 100) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(`Downloading vision model: ${progressBar} ${currentProgress}%`);\n if (currentProgress === 100) this.modelDownloaded = true;\n }\n }) as ProgressCallback,\n });\n\n this.model = model as unknown as Florence2ForConditionalGeneration;\n logger.success('Florence2 model loaded successfully');\n } catch (error) {\n logger.error('Failed to load Florence2 model:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelId: modelSpec.modelId,\n });\n throw error;\n }\n\n // Initialize tokenizer with detailed logging\n logger.info('Loading vision tokenizer...');\n try {\n const tokenizerCached = this.checkCacheExists(modelSpec.modelId, 'tokenizer');\n let tokenizerProgress = -1;\n\n this.tokenizer = await AutoTokenizer.from_pretrained(modelSpec.modelId, {\n cache_dir: this.modelsDir,\n local_files_only: tokenizerCached,\n progress_callback: ((progressInfo: ProgressInfo) => {\n if (tokenizerCached || this.tokenizerDownloaded) return;\n const progress =\n 'progress' in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;\n const currentProgress = Math.round(progress * 100);\n if (currentProgress !== tokenizerProgress) {\n tokenizerProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor((currentProgress / 100) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(`Downloading vision tokenizer: ${progressBar} ${currentProgress}%`);\n if (currentProgress === 100) this.tokenizerDownloaded = true;\n }\n }) as ProgressCallback,\n });\n logger.success('Vision tokenizer loaded successfully');\n } catch (error) {\n logger.error('Failed to load tokenizer:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelId: modelSpec.modelId,\n });\n throw error;\n }\n\n // Initialize processor with detailed logging\n logger.info('Loading vision processor...');\n try {\n const processorCached = this.checkCacheExists(modelSpec.modelId, 'processor');\n let processorProgress = -1;\n\n this.processor = (await AutoProcessor.from_pretrained(modelSpec.modelId, {\n device: 'cpu',\n cache_dir: this.modelsDir,\n local_files_only: processorCached,\n progress_callback: ((progressInfo: ProgressInfo) => {\n if (processorCached || this.processorDownloaded) return;\n const progress =\n 'progress' in progressInfo ? Math.max(0, Math.min(1, progressInfo.progress)) : 0;\n const currentProgress = Math.round(progress * 100);\n if (currentProgress !== processorProgress) {\n processorProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor((currentProgress / 100) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(`Downloading vision processor: ${progressBar} ${currentProgress}%`);\n if (currentProgress === 100) this.processorDownloaded = true;\n }\n }) as ProgressCallback,\n })) as Florence2Processor;\n logger.success('Vision processor loaded successfully');\n } catch (error) {\n logger.error('Failed to load vision processor:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelId: modelSpec.modelId,\n });\n throw error;\n }\n\n this.initialized = true;\n logger.success('Vision model initialization complete');\n } catch (error) {\n logger.error('Vision model initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n\n /**\n * Fetches an image from a given URL and returns the image data as a Buffer along with its MIME type.\n *\n * @param {string} url - The URL of the image to fetch.\n * @returns {Promise<{ buffer: Buffer; mimeType: string }>} Object containing the image data as a Buffer and its MIME type.\n */\n private async fetchImage(url: string): Promise<{ buffer: Buffer; mimeType: string }> {\n try {\n logger.info(`Fetching image from URL: ${url.slice(0, 100)}...`);\n\n // Handle data URLs differently\n if (url.startsWith('data:')) {\n logger.info('Processing data URL...');\n const [header, base64Data] = url.split(',');\n const mimeType = header.split(';')[0].split(':')[1];\n const buffer = Buffer.from(base64Data, 'base64');\n logger.info('Data URL processed successfully');\n // logger.info(\"Data URL processed successfully:\", {\n // mimeType,\n // bufferSize: buffer.length\n // });\n return { buffer, mimeType };\n }\n\n // Handle regular URLs\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch image: ${response.statusText}`);\n }\n const buffer = Buffer.from(await response.arrayBuffer());\n const mimeType = response.headers.get('content-type') || 'image/jpeg';\n\n logger.info('Image fetched successfully:', {\n mimeType,\n bufferSize: buffer.length,\n status: response.status,\n });\n\n return { buffer, mimeType };\n } catch (error) {\n logger.error('Failed to fetch image:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n url,\n });\n throw error;\n }\n }\n\n /**\n * Processes the image from the provided URL using the initialized vision model components.\n * @param {string} imageUrl - The URL of the image to process.\n * @returns {Promise<{ title: string; description: string }>} An object containing the title and description of the processed image.\n */\n public async processImage(imageUrl: string): Promise<{ title: string; description: string }> {\n try {\n logger.info('Starting image processing...');\n\n // Ensure model is initialized\n if (!this.initialized) {\n logger.info('Vision model not initialized, initializing now...');\n await this.initialize();\n }\n\n if (!this.model || !this.processor || !this.tokenizer) {\n throw new Error('Vision model components not properly initialized');\n }\n\n // Fetch and process image\n logger.info('Fetching image...');\n const { buffer, mimeType } = await this.fetchImage(imageUrl);\n\n // Process image\n logger.info('Creating image blob...');\n const blob = new Blob([buffer], { type: mimeType });\n logger.info('Converting blob to RawImage...');\n // @ts-ignore - RawImage.fromBlob expects web Blob but works with node Blob\n const image = await RawImage.fromBlob(blob);\n\n logger.info('Processing image with vision processor...');\n const visionInputs = await this.processor(image);\n logger.info('Constructing prompts...');\n const prompts = this.processor.construct_prompts('<DETAILED_CAPTION>');\n logger.info('Tokenizing prompts...');\n const textInputs = this.tokenizer(prompts);\n\n // Generate description\n logger.info('Generating image description...');\n const generatedIds = (await this.model.generate({\n ...textInputs,\n ...visionInputs,\n max_new_tokens: MODEL_SPECS.vision.maxTokens,\n })) as Tensor;\n\n logger.info('Decoding generated text...');\n const generatedText = this.tokenizer.batch_decode(generatedIds, {\n skip_special_tokens: false,\n })[0];\n\n logger.info('Post-processing generation...');\n const result = this.processor.post_process_generation(\n generatedText,\n '<DETAILED_CAPTION>',\n image.size\n );\n\n const detailedCaption = result['<DETAILED_CAPTION>'] as string;\n const response = {\n title: `${detailedCaption.split('.')[0]}.`,\n description: detailedCaption,\n };\n\n logger.success('Image processing complete:', {\n titleLength: response.title.length,\n descriptionLength: response.description.length,\n });\n\n return response;\n } catch (error) {\n logger.error('Image processing failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n imageUrl,\n modelInitialized: this.initialized,\n hasModel: !!this.model,\n hasProcessor: !!this.processor,\n hasTokenizer: !!this.tokenizer,\n });\n throw error;\n }\n }\n}\n"],"mappings":"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","names":["fs","os","path","Readable","logger","logger","logger","logger","fs","exec","fs","path","promisify","logger","execAsync","logger","fs","path","fetch","path","logger","fs","fetch","fs","os","path","process","logger","AutoTokenizer","path","logger","os","process","fs","AutoTokenizer","mimeType","buffer","path","logger","os","fs","Readable"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/plugin-local-ai",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",