@elizaos/plugin-local-ai 1.0.0-beta.7 → 1.0.0-beta.72
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/LICENSE +1 -1
- package/README.md +45 -99
- package/dist/index.d.ts +9 -0
- package/dist/index.js +924 -1595
- package/dist/index.js.map +1 -1
- package/package.json +14 -28
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/ollamaManager.ts","../src/utils/platform.ts","../src/utils/studiolmManager.ts","../src/utils/tokenizerManager.ts","../src/utils/transcribeManager.ts","../src/utils/ttsManager.ts","../src/utils/audioUtils.ts","../src/utils/visionManager.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\nimport { fileURLToPath } from 'node:url';\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 { EmbeddingModel, FlagEmbedding } from 'fastembed';\nimport {\n type Llama,\n LlamaChatSession,\n type LlamaContext,\n type LlamaContextSequence,\n type LlamaModel,\n getLlama,\n} from 'node-llama-cpp';\nimport { validateConfig } from './environment';\nimport { MODEL_SPECS, type ModelSpec } from './types';\nimport { DownloadManager } from './utils/downloadManager';\nimport { OllamaManager } from './utils/ollamaManager';\nimport { getPlatformManager } from './utils/platform';\nimport { StudioLMManager } from './utils/studiolmManager';\nimport { TokenizerManager } from './utils/tokenizerManager';\nimport { TranscribeManager } from './utils/transcribeManager';\nimport { TTSManager } from './utils/ttsManager';\nimport { VisionManager } from './utils/visionManager';\n\n// const execAsync = promisify(exec);\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\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// Add type definitions for model source selection\n/**\n * Represents the available sources for a text model: \"local\", \"studiolm\", or \"ollama\".\n */\ntype TextModelSource = 'local' | 'studiolm' | 'ollama';\n\n/**\n * Interface representing the configuration for a text model.\n *\n * @property {TextModelSource} source - The source of the text model.\n * @property {ModelTypeName} modelType - The type of the model.\n */\ninterface TextModelConfig {\n source: TextModelSource;\n modelType: ModelTypeName;\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 ctx: LlamaContext | undefined;\n private sequence: LlamaContextSequence | undefined;\n private chatSession: LlamaChatSession | undefined;\n private modelPath: string;\n private mediumModelPath: string;\n private cacheDir: string;\n private embeddingModel: FlagEmbedding | null = null;\n private tokenizerManager: TokenizerManager;\n private downloadManager: DownloadManager;\n private visionManager: VisionManager;\n private activeModelConfig: ModelSpec;\n private transcribeManager: TranscribeManager;\n private ttsManager: TTSManager;\n private studioLMManager: StudioLMManager;\n private ollamaManager: OllamaManager;\n\n // Initialization state flags\n private ollamaInitialized = false;\n private studioLMInitialized = false;\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\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 ollamaInitializingPromise: Promise<void> | null = null;\n private studioLMInitializingPromise: Promise<void> | null = null;\n\n private modelsDir: string;\n\n /**\n * Private constructor function to initialize base managers and paths.\n * This now only sets up the basic infrastructure without loading any models.\n */\n private constructor() {\n // Set up models directory consistently, similar to cacheDir\n const modelsDir = path.join(process.cwd(), 'models');\n\n // Check if LLAMALOCAL_PATH is set\n if (process.env.LLAMALOCAL_PATH?.trim()) {\n this.modelsDir = path.resolve(process.env.LLAMALOCAL_PATH.trim());\n } else {\n // Ensure models directory exists\n if (!fs.existsSync(modelsDir)) {\n fs.mkdirSync(modelsDir, { recursive: true });\n logger.debug('Created models directory');\n }\n this.modelsDir = modelsDir;\n }\n\n // Set paths for models\n this.modelPath = path.join(this.modelsDir, 'DeepHermes-3-Llama-3-3B-Preview-q4.gguf');\n\n this.mediumModelPath = path.join(this.modelsDir, 'DeepHermes-3-Llama-3-8B-q4.gguf');\n\n // Set up cache directory\n const cacheDirEnv = process.env.CACHE_DIR?.trim();\n if (cacheDirEnv) {\n this.cacheDir = path.resolve(cacheDirEnv);\n } else {\n const cacheDir = path.join(process.cwd(), 'cache');\n // Ensure cache directory exists\n if (!fs.existsSync(cacheDir)) {\n fs.mkdirSync(cacheDir, { recursive: true });\n logger.debug('Ensuring cache directory exists:', cacheDir);\n }\n this.cacheDir = cacheDir;\n }\n\n // Initialize the download manager\n this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);\n\n // Initialize tokenizer manager\n this.tokenizerManager = TokenizerManager.getInstance(this.cacheDir, this.modelsDir);\n\n // Initialize vision manager\n this.visionManager = VisionManager.getInstance(this.cacheDir);\n\n // Initialize transcribe manager\n this.transcribeManager = TranscribeManager.getInstance(this.cacheDir);\n\n // Initialize TTS manager\n this.ttsManager = TTSManager.getInstance(this.cacheDir);\n\n // Initialize StudioLM manager if enabled\n if (process.env.USE_STUDIOLM_TEXT_MODELS === 'true') {\n this.studioLMManager = StudioLMManager.getInstance();\n }\n\n // Initialize Ollama manager if enabled\n if (process.env.USE_OLLAMA_TEXT_MODELS === 'true') {\n this.ollamaManager = OllamaManager.getInstance();\n }\n\n // Initialize active model config\n this.activeModelConfig = MODEL_SPECS.small;\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 the environment variables with the validated values.\n *\n * @returns {Promise<void>} A Promise that resolves once the environment has been successfully initialized.\n */\n private async initializeEnvironment(): Promise<void> {\n try {\n logger.info('Validating environment configuration...');\n\n // Create initial config from current env vars\n const config = {\n USE_LOCAL_AI: process.env.USE_LOCAL_AI,\n USE_STUDIOLM_TEXT_MODELS: process.env.USE_STUDIOLM_TEXT_MODELS,\n USE_OLLAMA_TEXT_MODELS: process.env.USE_OLLAMA_TEXT_MODELS,\n };\n\n // Validate configuration\n const validatedConfig = await validateConfig(config);\n\n // Log the validated configuration\n // logger.info(\"Environment configuration validated:\", validatedConfig);\n logger.info('Environment configuration validated');\n\n // Ensure environment variables are set with validated values\n process.env.USE_LOCAL_AI = String(validatedConfig.USE_LOCAL_AI);\n process.env.USE_STUDIOLM_TEXT_MODELS = String(validatedConfig.USE_STUDIOLM_TEXT_MODELS);\n process.env.USE_OLLAMA_TEXT_MODELS = String(validatedConfig.USE_OLLAMA_TEXT_MODELS);\n\n // logger.info(\"Environment variables updated with validated values:\", {\n // USE_LOCAL_AI: process.env.USE_LOCAL_AI,\n // USE_STUDIOLM_TEXT_MODELS: process.env.USE_STUDIOLM_TEXT_MODELS,\n // USE_OLLAMA_TEXT_MODELS: process.env.USE_OLLAMA_TEXT_MODELS\n // });\n\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 throw error;\n }\n }\n\n /**\n * Asynchronously initializes the Ollama model.\n *\n * @returns {Promise<void>} A Promise that resolves when the initialization is complete.\n * @throws {Error} If the Ollama manager is not created, or if initialization of Ollama models fails.\n */\n private async initializeOllama(): Promise<void> {\n try {\n logger.info('Initializing Ollama models...');\n\n // Check if Ollama manager exists\n if (!this.ollamaManager) {\n throw new Error('Ollama manager not created - cannot initialize');\n }\n\n // Initialize and test models\n await this.ollamaManager.initialize();\n\n if (!this.ollamaManager.isInitialized()) {\n throw new Error('Ollama initialization failed - models not properly loaded');\n }\n\n logger.success('Ollama initialization complete');\n } catch (error) {\n logger.error('Ollama 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 throw error;\n }\n }\n\n /**\n * Initializes StudioLM model with error handling.\n * @returns A Promise that resolves when the initialization is complete.\n * @throws {Error} If StudioLM manager is not created, initialization fails, or models are not properly loaded.\n */\n private async initializeStudioLM(): Promise<void> {\n try {\n logger.info('Initializing StudioLM models...');\n\n // Check if StudioLM manager exists\n if (!this.studioLMManager) {\n throw new Error('StudioLM manager not created - cannot initialize');\n }\n\n // Initialize and test models\n await this.studioLMManager.initialize();\n\n if (!this.studioLMManager.isInitialized()) {\n throw new Error('StudioLM initialization failed - models not properly loaded');\n }\n\n this.studioLMInitialized = true;\n logger.success('StudioLM initialization complete');\n } catch (error) {\n logger.error('StudioLM 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 throw error;\n }\n }\n\n /**\n * Downloads the model based on the modelPath provided.\n * Determines whether to download a large or small model based on the current modelPath.\n *\n * @returns A Promise that resolves to a boolean indicating whether the model download was successful.\n */\n private async downloadModel(modelType: ModelTypeName): Promise<boolean> {\n const modelSpec = modelType === ModelType.TEXT_LARGE ? MODEL_SPECS.medium : MODEL_SPECS.small;\n const modelPath = modelType === ModelType.TEXT_LARGE ? this.mediumModelPath : this.modelPath;\n try {\n return await this.downloadManager.downloadModel(modelSpec, modelPath);\n } catch (error) {\n logger.error('Model download failed:', {\n error: error instanceof Error ? error.message : String(error),\n modelPath,\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 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 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 if (!this.embeddingModel) {\n logger.info('Creating new FlagEmbedding instance with BGESmallENV15 model');\n // logger.info(\"Embedding model download details:\", {\n // model: EmbeddingModel.BGESmallENV15,\n // modelsDir: this.modelsDir,\n // maxLength: 512,\n // timestamp: new Date().toISOString()\n // });\n\n // Display initial progress bar\n const barLength = 30;\n const emptyBar = '▱'.repeat(barLength);\n logger.info(`Downloading embedding model: ${emptyBar} 0%`);\n\n // Disable built-in progress bar and initialize the model\n this.embeddingModel = await FlagEmbedding.init({\n cacheDir: this.modelsDir,\n model: EmbeddingModel.BGESmallENV15,\n maxLength: 512,\n showDownloadProgress: false,\n });\n\n // Display completed progress bar\n const completedBar = '▰'.repeat(barLength);\n logger.info(`Downloading embedding model: ${completedBar} 100%`);\n logger.success('FlagEmbedding instance created 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 model: EmbeddingModel.BGESmallENV15,\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously generates text using either StudioLM or Ollama models based on the specified parameters.\n *\n * @param {GenerateTextParams} params - The parameters for generating the text.\n * @returns {Promise<string>} - A promise that resolves to the generated text.\n */\n async generateTextOllamaStudio(params: GenerateTextParams): Promise<string> {\n try {\n const modelConfig = this.getTextModelSource();\n logger.info('generateTextOllamaStudio called with:', {\n modelSource: modelConfig.source,\n modelType: params.modelType,\n studioLMInitialized: this.studioLMInitialized,\n ollamaInitialized: this.ollamaInitialized,\n studioLMEnabled: process.env.USE_STUDIOLM_TEXT_MODELS === 'true',\n ollamaEnabled: process.env.USE_OLLAMA_TEXT_MODELS === 'true',\n });\n\n if (modelConfig.source === 'studiolm') {\n // Check if StudioLM is enabled in environment\n if (process.env.USE_STUDIOLM_TEXT_MODELS !== 'true') {\n logger.warn(\n 'StudioLM requested but disabled in environment, falling back to local models'\n );\n return this.generateText(params);\n }\n\n // Check if StudioLM manager exists\n if (!this.studioLMManager) {\n logger.warn('StudioLM manager not initialized, falling back to local models');\n return this.generateText(params);\n }\n\n // Only initialize if not already initialized\n if (!this.studioLMInitialized) {\n logger.info('StudioLM not initialized, initializing now...');\n await this.initializeStudioLM();\n }\n\n // Pass initialization flag to generateText\n return await this.studioLMManager.generateText(params, this.studioLMInitialized);\n }\n\n if (modelConfig.source === 'ollama') {\n // Check if Ollama is enabled in environment\n if (process.env.USE_OLLAMA_TEXT_MODELS !== 'true') {\n logger.warn('Ollama requested but disabled in environment, falling back to local models');\n return this.generateText(params);\n }\n\n // Check if Ollama manager exists\n if (!this.ollamaManager) {\n logger.warn('Ollama manager not initialized, falling back to local models');\n return this.generateText(params);\n }\n\n // Only initialize if not already initialized\n if (!this.ollamaInitialized && !this.ollamaManager.isInitialized()) {\n logger.info('Initializing Ollama in generateTextOllamaStudio');\n await this.ollamaManager.initialize();\n this.ollamaInitialized = true;\n }\n\n // Pass initialization flag to generateText\n return await this.ollamaManager.generateText(params, this.ollamaInitialized);\n }\n\n // Fallback to local models if something goes wrong\n return this.generateText(params);\n } catch (error) {\n logger.error('Text generation with Ollama/StudioLM failed:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n modelSource: this.getTextModelSource().source,\n });\n // Fallback to local models\n return this.generateText(params);\n }\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 // 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: () => 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 * Generate embeddings - now with lazy initialization\n */\n async generateEmbedding(text: string): Promise<number[]> {\n try {\n // Lazy initialize embedding model\n await this.lazyInitEmbedding();\n\n if (!this.embeddingModel) {\n throw new Error('Failed to initialize embedding model');\n }\n\n logger.info('Generating query embedding...');\n const embedding = await this.embeddingModel.queryEmbed(text);\n const dimensions = embedding.length;\n logger.info('Embedding generation complete', { dimensions });\n\n return Array.from(embedding);\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 // Only access text.length if text exists\n textLength: text?.length ?? 'text is null',\n });\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 // Add public accessor methods\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 * Retrieves the source configuration for the text model based on environment variables and manager existence.\n * @returns {TextModelConfig} The configuration object containing the text model source and type.\n */\n public getTextModelSource(): TextModelConfig {\n try {\n // Default configuration\n const config: TextModelConfig = {\n source: 'local',\n modelType: ModelType.TEXT_SMALL,\n };\n\n // Check environment configuration and manager existence\n if (process.env.USE_STUDIOLM_TEXT_MODELS === 'true' && this.studioLMManager) {\n config.source = 'studiolm';\n } else if (process.env.USE_OLLAMA_TEXT_MODELS === 'true' && this.ollamaManager) {\n config.source = 'ollama';\n }\n\n logger.info('Selected text model source:', config);\n return config;\n } catch (error) {\n logger.error('Error determining text model source:', error);\n // Fallback to local models\n return { source: 'local', modelType: ModelType.TEXT_SMALL };\n }\n }\n\n /**\n * Generic lazy initialization handler for any model type\n */\n private async lazyInitialize<T>(\n modelType: string,\n isInitialized: boolean,\n initPromise: Promise<T> | null,\n initFunction: () => Promise<T>\n ): Promise<T> {\n // If already initialized, return immediately\n if (isInitialized) {\n return Promise.resolve(null) as Promise<T>;\n }\n\n // If currently initializing, wait for it to complete\n if (initPromise) {\n logger.info(`Waiting for ${modelType} initialization to complete...`);\n await initPromise;\n return Promise.resolve(null) as Promise<T>;\n }\n\n // Otherwise start initialization\n logger.info(`Lazy initializing ${modelType}...`);\n return initFunction();\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();\n await this.checkPlatformCapabilities();\n\n // Download model if needed\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,\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 // Make sure llama is initialized first\n if (!this.llama) {\n await this.lazyInitSmallModel();\n }\n\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,\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 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 await this.initializeEmbedding();\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 * 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 // Initialize transcription model directly\n // Use existing initialization code from the file\n // ...\n this.transcriptionInitialized = true;\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 // ...\n this.ttsInitialized = true;\n logger.info('TTS model initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize TTS model:', error);\n this.ttsInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.ttsInitializingPromise;\n }\n\n /**\n * Lazy initialize the Ollama integration\n */\n private async lazyInitOllama(): Promise<void> {\n if (this.ollamaInitialized) return;\n\n if (!this.ollamaInitializingPromise) {\n this.ollamaInitializingPromise = (async () => {\n try {\n await this.initializeOllama();\n this.ollamaInitialized = true;\n logger.info('Ollama initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize Ollama:', error);\n this.ollamaInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.ollamaInitializingPromise;\n }\n\n /**\n * Lazy initialize the StudioLM integration\n */\n private async lazyInitStudioLM(): Promise<void> {\n if (this.studioLMInitialized) return;\n\n if (!this.studioLMInitializingPromise) {\n this.studioLMInitializingPromise = (async () => {\n try {\n await this.initializeStudioLM();\n this.studioLMInitialized = true;\n logger.info('StudioLM initialized successfully');\n } catch (error) {\n logger.error('Failed to initialize StudioLM:', error);\n this.studioLMInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.studioLMInitializingPromise;\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() {\n try {\n logger.debug('Initializing local-ai plugin...');\n // Only validate config - actual models will be lazy-loaded when needed\n logger.success('Local AI plugin configuration validated and initialized');\n } catch (error) {\n logger.error('Plugin initialization 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 models: {\n [ModelType.TEXT_SMALL]: async (\n runtime: IAgentRuntime,\n { prompt, stopSequences = [] }: GenerateTextParams\n ) => {\n try {\n const modelConfig = localAIManager.getTextModelSource();\n\n if (modelConfig.source !== 'local') {\n return await localAIManager.generateTextOllamaStudio({\n prompt,\n stopSequences,\n runtime,\n modelType: ModelType.TEXT_SMALL,\n });\n }\n\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 const modelConfig = localAIManager.getTextModelSource();\n\n if (modelConfig.source !== 'local') {\n return await localAIManager.generateTextOllamaStudio({\n prompt,\n stopSequences,\n runtime,\n modelType: ModelType.TEXT_LARGE,\n });\n }\n\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 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 const modelConfig = localAIManager.getTextModelSource();\n\n // Generate text based on the configured model source\n let textResponse: string;\n if (modelConfig.source !== 'local') {\n textResponse = await localAIManager.generateTextOllamaStudio({\n prompt: jsonPrompt,\n stopSequences: params.stopSequences,\n runtime,\n modelType: ModelType.TEXT_SMALL,\n });\n } else {\n textResponse = await localAIManager.generateText({\n prompt: jsonPrompt,\n stopSequences: params.stopSequences,\n runtime,\n modelType: ModelType.TEXT_SMALL,\n });\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 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 const modelConfig = localAIManager.getTextModelSource();\n\n // Generate text based on the configured model source\n let textResponse: string;\n if (modelConfig.source !== 'local') {\n textResponse = await localAIManager.generateTextOllamaStudio({\n prompt: jsonPrompt,\n stopSequences: params.stopSequences,\n runtime,\n modelType: ModelType.TEXT_LARGE,\n });\n } else {\n textResponse = await localAIManager.generateText({\n prompt: jsonPrompt,\n stopSequences: params.stopSequences,\n runtime,\n modelType: ModelType.TEXT_LARGE,\n });\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 const imageUrl =\n 'https://raw.githubusercontent.com/microsoft/FLAML/main/website/static/img/flaml.png';\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 simple audio buffer for testing\n const audioData = new Uint8Array([\n 0x52,\n 0x49,\n 0x46,\n 0x46, // \"RIFF\"\n 0x24,\n 0x00,\n 0x00,\n 0x00, // Chunk size\n 0x57,\n 0x41,\n 0x56,\n 0x45, // \"WAVE\"\n 0x66,\n 0x6d,\n 0x74,\n 0x20, // \"fmt \"\n ]);\n const audioBuffer = Buffer.from(audioData);\n\n const transcription = await runtime.useModel(ModelType.TRANSCRIPTION, audioBuffer);\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 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 type { IAgentRuntime } from '@elizaos/core';\nimport { logger } from '@elizaos/core';\nimport { z } from 'zod';\n\n// Configuration schema with text model source flags\n/**\n * Configuration schema for different AI models and their settings.\n * This schema includes:\n * - Flags for enabling/disabling various AI models\n * - Ollama configurations including server URL, models, and embedding models\n * - StudioLM configurations including server URL, models, and embedding models\n */\nexport const configSchema = z.object({\n USE_LOCAL_AI: z.boolean().default(true),\n USE_STUDIOLM_TEXT_MODELS: z.boolean().default(false),\n USE_OLLAMA_TEXT_MODELS: z.boolean().default(false),\n\n // Ollama Configuration\n OLLAMA_SERVER_URL: z.string().default('http://localhost:11434'),\n OLLAMA_MODEL: z.string().default('deepseek-r1-distill-qwen-7b'),\n USE_OLLAMA_EMBEDDING: z.boolean().default(false),\n OLLAMA_EMBEDDING_MODEL: z.string().default(''),\n SMALL_OLLAMA_MODEL: z.string().default('deepseek-r1:1.5b'),\n MEDIUM_OLLAMA_MODEL: z.string().default('deepseek-r1:7b'),\n LARGE_OLLAMA_MODEL: z.string().default('deepseek-r1:7b'),\n\n // StudioLM Configuration\n STUDIOLM_SERVER_URL: z.string().default('http://localhost:1234'),\n STUDIOLM_SMALL_MODEL: z.string().default('lmstudio-community/deepseek-r1-distill-qwen-1.5b'),\n STUDIOLM_MEDIUM_MODEL: z.string().default('deepseek-r1-distill-qwen-7b'),\n STUDIOLM_EMBEDDING_MODEL: z.union([z.boolean(), z.string()]).default(false),\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 the model configuration object.\n *\n * @param {Record<string, boolean>} config - The model configuration object containing boolean values.\n * @returns {void}\n */\nfunction validateModelConfig(config: Record<string, boolean>): void {\n // Log raw values before validation\n logger.info('Validating model configuration with values:', {\n USE_LOCAL_AI: config.USE_LOCAL_AI,\n USE_STUDIOLM_TEXT_MODELS: config.USE_STUDIOLM_TEXT_MODELS,\n USE_OLLAMA_TEXT_MODELS: config.USE_OLLAMA_TEXT_MODELS,\n });\n\n // Ensure USE_LOCAL_AI is always true\n if (!config.USE_LOCAL_AI) {\n config.USE_LOCAL_AI = true;\n logger.info(\"Setting USE_LOCAL_AI to true as it's required\");\n }\n\n // Only validate that StudioLM and Ollama are not both enabled\n if (config.USE_STUDIOLM_TEXT_MODELS && config.USE_OLLAMA_TEXT_MODELS) {\n throw new Error('StudioLM and Ollama text models cannot be enabled simultaneously');\n }\n\n logger.info('Configuration is valid');\n}\n\n/**\n * Validates and parses the configuration provided as a record of string key-value pairs.\n * This function performs boolean conversion on specific configuration values and sets default values for missing keys.\n * @param {Record<string, string>} config - The configuration to validate and parse.\n * @returns {Promise<Config>} The validated and parsed configuration object.\n */\nexport async function validateConfig(config: Record<string, string>): Promise<Config> {\n try {\n // Log raw environment variables\n // logger.info(\"Raw environment variables:\", {\n // USE_LOCAL_AI: process.env.USE_LOCAL_AI,\n // USE_STUDIOLM_TEXT_MODELS: process.env.USE_STUDIOLM_TEXT_MODELS,\n // USE_OLLAMA_TEXT_MODELS: process.env.USE_OLLAMA_TEXT_MODELS,\n // OLLAMA_SERVER_URL: process.env.OLLAMA_SERVER_URL,\n // STUDIOLM_SERVER_URL: process.env.STUDIOLM_SERVER_URL\n // });\n\n // Parse environment variables with proper boolean conversion\n const booleanConfig = {\n USE_LOCAL_AI: true, // Always true\n USE_STUDIOLM_TEXT_MODELS: config.USE_STUDIOLM_TEXT_MODELS === 'true',\n USE_OLLAMA_TEXT_MODELS: config.USE_OLLAMA_TEXT_MODELS === 'true',\n USE_OLLAMA_EMBEDDING: config.USE_OLLAMA_EMBEDDING === 'true',\n };\n\n // logger.info(\"Parsed boolean configuration:\", booleanConfig);\n\n // Validate text model source configuration\n validateModelConfig(booleanConfig);\n\n // Create full config with all values\n const fullConfig = {\n ...booleanConfig,\n OLLAMA_SERVER_URL: config.OLLAMA_SERVER_URL || 'http://localhost:11434',\n OLLAMA_MODEL: config.OLLAMA_MODEL || 'deepseek-r1-distill-qwen-7b',\n OLLAMA_EMBEDDING_MODEL: config.OLLAMA_EMBEDDING_MODEL || '',\n SMALL_OLLAMA_MODEL: config.SMALL_OLLAMA_MODEL || 'deepseek-r1:1.5b',\n MEDIUM_OLLAMA_MODEL: config.MEDIUM_OLLAMA_MODEL || 'deepseek-r1:7b',\n LARGE_OLLAMA_MODEL: config.LARGE_OLLAMA_MODEL || 'deepseek-r1:7b',\n STUDIOLM_SERVER_URL: config.STUDIOLM_SERVER_URL || 'http://localhost:1234',\n STUDIOLM_SMALL_MODEL:\n config.STUDIOLM_SMALL_MODEL || 'lmstudio-community/deepseek-r1-distill-qwen-1.5b',\n STUDIOLM_MEDIUM_MODEL: config.STUDIOLM_MEDIUM_MODEL || 'deepseek-r1-distill-qwen-7b',\n STUDIOLM_EMBEDDING_MODEL: config.STUDIOLM_EMBEDDING_MODEL || false,\n };\n\n const validatedConfig = configSchema.parse(fullConfig);\n\n // logger.info(\"Final validated 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 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// 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 {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\n * @property {TTSModelSpec} tts.base - Specifications for the base text-to-speech model\n * @property {TTSModelSpec} tts.medium - Specifications for a medium text-to-speech model\n * @property {TTSModelSpec} tts.large - Specifications for a large text-to-speech model\n */\nexport interface ModelSpecs {\n small: ModelSpec;\n medium: ModelSpec;\n vision: VisionModelSpec;\n visionvl: VisionModelSpec;\n tts: {\n base: TTSModelSpec;\n medium: TTSModelSpec;\n large: TTSModelSpec;\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 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 base: {\n name: 'OuteTTS-0.2-500M-Q8_0.gguf',\n repo: 'OuteAI/OuteTTS-0.2-500M-GGUF',\n size: '500M',\n quantization: 'Q8_0',\n speakers: ['male_1', 'male_2', 'female_1', 'female_2'],\n languages: ['en'],\n features: ['MULTI_SPEAKER', 'VOICE_CLONING', 'EMOTION_CONTROL', 'SPEED_CONTROL'],\n maxInputLength: 4096,\n sampleRate: 24000,\n contextSize: 2048,\n tokenizer: {\n name: 'OuteAI/OuteTTS-0.2-500M',\n type: 'llama',\n },\n },\n medium: {\n name: 'OuteTTS-0.3-1B.gguf',\n repo: 'OuteAI/OuteTTS-0.3-1B-GGUF',\n size: '1B',\n quantization: 'Q8_0',\n speakers: ['male_1', 'male_2', 'male_3', 'female_1', 'female_2', 'female_3'],\n languages: ['en', 'es', 'fr', 'de', 'it'],\n features: [\n 'MULTI_SPEAKER',\n 'VOICE_CLONING',\n 'EMOTION_CONTROL',\n 'SPEED_CONTROL',\n 'MULTILINGUAL',\n 'ACCENT_CONTROL',\n ],\n maxInputLength: 8192,\n sampleRate: 32000,\n contextSize: 4096,\n tokenizer: {\n name: 'OuteAI/OuteTTS-0.3-1B',\n type: 'llama',\n },\n },\n large: {\n name: 'OuteTTS-0.3-3B.gguf',\n repo: 'OuteAI/OuteTTS-0.3-3B-GGUF',\n size: '3B',\n quantization: 'Q8_0',\n speakers: [\n 'male_1',\n 'male_2',\n 'male_3',\n 'male_4',\n 'female_1',\n 'female_2',\n 'female_3',\n 'female_4',\n ],\n languages: ['en', 'es', 'fr', 'de', 'it', 'pt', 'nl', 'pl', 'ru', 'ja', 'ko', 'zh'],\n features: [\n 'MULTI_SPEAKER',\n 'VOICE_CLONING',\n 'EMOTION_CONTROL',\n 'SPEED_CONTROL',\n 'MULTILINGUAL',\n 'ACCENT_CONTROL',\n 'STYLE_TRANSFER',\n 'PROSODY_CONTROL',\n ],\n maxInputLength: 16384,\n sampleRate: 48000,\n contextSize: 8192,\n tokenizer: {\n name: 'OuteAI/OuteTTS-0.3-3B',\n type: 'llama',\n },\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 { type GenerateTextParams, ModelType, logger } from '@elizaos/core';\n\n/**\n * Interface representing the structure of an Ollama model.\n * @typedef {Object} OllamaModel\n * @property {string} name - The name of the Ollama model.\n * @property {string} id - The unique identifier of the Ollama model.\n * @property {string} size - The size of the Ollama model.\n * @property {string} modified - The date when the Ollama model was last modified.\n */\ninterface OllamaModel {\n name: string;\n id: string;\n size: string;\n modified: string;\n}\n\n/**\n * Interface representing a response from the Ollama API.\n * @property {string} model - The model used for generating the response.\n * @property {string} response - The actual response generated by the model.\n * @property {boolean} done - Indicates whether the response generation is complete.\n * @property {number[]} [prompt] - Optional array of prompt values used in generating the response.\n * @property {number} [total_duration] - Optional total duration of the response generation process.\n * @property {number} [load_duration] - Optional load duration of the model used.\n * @property {number} [prompt_eval_duration] - Optional evaluation duration for the prompt values.\n * @property {number} [eval_duration] - Optional evaluation duration for the response generation.\n */\ninterface OllamaResponse {\n model: string;\n response: string;\n done: boolean;\n prompt?: number[];\n total_duration?: number;\n load_duration?: number;\n prompt_eval_duration?: number;\n eval_duration?: number;\n}\n\n/**\n * Manages interactions with the Ollama API, including server status checks, fetching available models,\n * testing models, initializing the manager, generating text, and more.\n */\nexport class OllamaManager {\n private static instance: OllamaManager | null = null;\n private serverUrl: string;\n private initialized = false;\n private availableModels: OllamaModel[] = [];\n private configuredModels = {\n small: process.env.SMALL_OLLAMA_MODEL || 'deepseek-r1:1.5b',\n medium: process.env.MEDIUM_OLLAMA_MODEL || 'deepseek-r1:7b',\n };\n\n /**\n * Private constructor for initializing OllamaManager.\n */\n private constructor() {\n this.serverUrl = process.env.OLLAMA_SERVER_URL || 'http://localhost:11434';\n logger.info('OllamaManager initialized with configuration:', {\n serverUrl: this.serverUrl,\n configuredModels: this.configuredModels,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Returns an instance of the OllamaManager class.\n * If an instance does not already exist, a new instance is created and returned.\n * @returns {OllamaManager} The instance of the OllamaManager class.\n */\n public static getInstance(): OllamaManager {\n if (!OllamaManager.instance) {\n OllamaManager.instance = new OllamaManager();\n }\n return OllamaManager.instance;\n }\n\n /**\n * Asynchronously checks the status of the server by attempting to fetch the \"/api/tags\" endpoint.\n * @returns A Promise that resolves to a boolean indicating if the server is reachable and responding with a successful status.\n */\n private async checkServerStatus(): Promise<boolean> {\n try {\n const response = await fetch(`${this.serverUrl}/api/tags`);\n if (!response.ok) {\n throw new Error(`Server responded with status: ${response.status}`);\n }\n return true;\n } catch (error) {\n logger.error('Ollama server check failed:', {\n error: error instanceof Error ? error.message : String(error),\n serverUrl: this.serverUrl,\n timestamp: new Date().toISOString(),\n });\n return false;\n }\n }\n\n /**\n * Fetches the available Ollama models from the specified server URL.\n *\n * @returns {Promise<void>} A Promise that resolves when the available models are successfully fetched.\n */\n private async fetchAvailableModels(): Promise<void> {\n try {\n const response = await fetch(`${this.serverUrl}/api/tags`);\n if (!response.ok) {\n throw new Error(`Failed to fetch models: ${response.status}`);\n }\n\n const data = (await response.json()) as { models: OllamaModel[] };\n this.availableModels = data.models;\n\n logger.info('Ollama available models:', {\n count: this.availableModels.length,\n models: this.availableModels.map((m) => m.name),\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error('Failed to fetch Ollama models:', {\n error: error instanceof Error ? error.message : String(error),\n serverUrl: this.serverUrl,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously tests a model specified by the given modelId.\n *\n * @param {string} modelId - The ID of the model to be tested.\n * @returns {Promise<boolean>} - A promise that resolves to true if the model test is successful, false otherwise.\n */\n private async testModel(modelId: string): Promise<boolean> {\n try {\n const testRequest = {\n model: modelId,\n prompt:\n \"Debug Mode: Test initialization. Respond with 'Initialization successful' if you can read this.\",\n stream: false,\n options: {\n temperature: 0.7,\n num_predict: 100,\n },\n };\n\n logger.info(`Testing model ${modelId}...`);\n\n const response = await fetch(`${this.serverUrl}/api/generate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(testRequest),\n });\n\n if (!response.ok) {\n throw new Error(`Model test failed with status: ${response.status}`);\n }\n\n const result = (await response.json()) as OllamaResponse;\n\n if (!result.response) {\n throw new Error('No valid response content received');\n }\n\n logger.info(`Model ${modelId} test response:`, {\n content: result.response,\n model: result.model,\n timestamp: new Date().toISOString(),\n });\n\n return true;\n } catch (error) {\n logger.error(`Model ${modelId} test 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\n /**\n * Asynchronously tests the configured text models to ensure they are working properly.\n * Logs the test results for each model and outputs a warning if any models fail the test.\n * @returns {Promise<void>} A Promise that resolves when all configured models have been tested.\n */\n private async testTextModels(): Promise<void> {\n logger.info('Testing configured text models...');\n\n const results = await Promise.all([\n this.testModel(this.configuredModels.small),\n this.testModel(this.configuredModels.medium),\n ]);\n\n const [smallWorking, mediumWorking] = results;\n\n if (!smallWorking || !mediumWorking) {\n const failedModels = [];\n if (!smallWorking) failedModels.push('small');\n if (!mediumWorking) failedModels.push('medium');\n\n logger.warn('Some models failed the test:', {\n failedModels,\n small: this.configuredModels.small,\n medium: this.configuredModels.medium,\n });\n } else {\n logger.success('All configured models passed the test');\n }\n }\n\n /**\n * Asynchronously initializes the Ollama service by checking server status,\n * fetching available models, and testing text models.\n *\n * @returns A Promise that resolves when initialization is complete\n */\n public async initialize(): Promise<void> {\n try {\n if (this.initialized) {\n logger.info('Ollama already initialized, skipping initialization');\n return;\n }\n\n logger.info('Starting Ollama initialization...');\n const serverAvailable = await this.checkServerStatus();\n\n if (!serverAvailable) {\n throw new Error('Ollama server is not available');\n }\n\n await this.fetchAvailableModels();\n await this.testTextModels();\n\n this.initialized = true;\n logger.success('Ollama initialization complete');\n } catch (error) {\n logger.error('Ollama initialization 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 * Retrieves the available Ollama models.\n *\n * @returns {OllamaModel[]} An array of OllamaModel objects representing the available models.\n */\n public getAvailableModels(): OllamaModel[] {\n return this.availableModels;\n }\n\n /**\n * Check if the object is initialized.\n * @returns {boolean} True if the object is initialized, false otherwise.\n */\n public isInitialized(): boolean {\n return this.initialized;\n }\n\n /**\n * Generates text using the Ollama AI model.\n *\n * @param {GenerateTextParams} params - The parameters for generating text.\n * @param {boolean} [isInitialized=false] - Flag indicating if Ollama is already initialized.\n * @returns {Promise<string>} - A promise that resolves with the generated text.\n */\n public async generateText(params: GenerateTextParams, isInitialized = false): Promise<string> {\n try {\n // Log entry point with all parameters\n logger.info('Ollama generateText entry:', {\n isInitialized,\n currentInitState: this.initialized,\n managerInitState: this.isInitialized(),\n modelType: params.modelType,\n contextLength: params.prompt?.length,\n timestamp: new Date().toISOString(),\n });\n\n // Only initialize if not already initialized and not marked as initialized\n if (!this.initialized && !isInitialized) {\n throw new Error('Ollama not initialized. Please initialize before generating text.');\n }\n\n logger.info('Ollama preparing request:', {\n model:\n params.modelType === ModelType.TEXT_LARGE\n ? this.configuredModels.medium\n : this.configuredModels.small,\n contextLength: params.prompt.length,\n timestamp: new Date().toISOString(),\n });\n\n const request = {\n model:\n params.modelType === ModelType.TEXT_LARGE\n ? this.configuredModels.medium\n : this.configuredModels.small,\n prompt: params.prompt,\n stream: false,\n options: {\n temperature: 0.7,\n top_p: 0.9,\n num_predict: 8192,\n repeat_penalty: 1.2,\n frequency_penalty: 0.7,\n presence_penalty: 0.7,\n },\n };\n\n const response = await fetch(`${this.serverUrl}/api/generate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`Ollama request failed: ${response.status}`);\n }\n\n const result = (await response.json()) as OllamaResponse;\n\n if (!result.response) {\n throw new Error('No valid response content received from Ollama');\n }\n\n let responseText = result.response;\n\n // Log raw response for debugging\n logger.info('Raw response structure:', {\n responseLength: responseText.length,\n hasAction: responseText.includes('action'),\n hasThinkTag: responseText.includes('<think>'),\n });\n\n // Clean think tags if present\n if (responseText.includes('<think>')) {\n logger.info('Cleaning think tags from response');\n responseText = responseText.replace(/<think>[\\s\\S]*?<\\/think>\\n?/g, '');\n logger.info('Think tags removed from response');\n }\n\n logger.info('Ollama request completed successfully:', {\n responseLength: responseText.length,\n hasThinkTags: responseText.includes('<think>'),\n timestamp: new Date().toISOString(),\n });\n\n return responseText;\n } catch (error) {\n logger.error('Ollama text generation error:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n phase: 'text generation',\n timestamp: new Date().toISOString(),\n });\n throw error;\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 { type GenerateTextParams, ModelType, logger } from '@elizaos/core';\n\n/**\n * Represents a StudioLMModel object with the following properties:\n * - id: string\n * - object: string\n * - created: number\n * - owned_by: string\n */\ninterface StudioLMModel {\n id: string;\n object: string;\n created: number;\n owned_by: string;\n}\n\n/**\n * Interface representing a chat message.\n * @property {string} role - The role of the sender, can be \"system\", \"user\", or \"assistant\".\n * @property {string} content - The content of the message.\n */\ninterface ChatMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\n/**\n * Interface representing a chat completion request.\n * @property {string} model - The model to be used for generating chat completions.\n * @property {ChatMessage[]} messages - An array of chat messages to provide context for the completion.\n * @property {number} [temperature] - The temperature parameter to control the randomness of the generated completions.\n * @property {number} [max_tokens] - The maximum number of tokens to generate in the completion.\n * @property {boolean} [stream] - Whether to generate completions in a streaming fashion.\n */\n\ninterface ChatCompletionRequest {\n model: string;\n messages: ChatMessage[];\n temperature?: number;\n max_tokens?: number;\n stream?: boolean;\n}\n\n/**\n * Represents a response object for completing a chat session.\n * @typedef {Object} ChatCompletionResponse\n * @property {string} id - The unique identifier for the completion response.\n * @property {string} object - The type of object being returned.\n * @property {number} created - The timestamp of when the completion response was created.\n * @property {string} model - The type of model associated with the completion response.\n * @property {Object[]} choices - An array of choices made during the chat session.\n * @property {number} choices.index - The index of the choice within the array.\n * @property {ChatMessage} choices.message - The message associated with the choice.\n * @property {string} choices.finish_reason - The reason for finishing the chat session.\n */\ninterface ChatCompletionResponse {\n id: string;\n object: string;\n created: number;\n model: string;\n choices: {\n index: number;\n message: ChatMessage;\n finish_reason: string;\n }[];\n}\n\n/**\n * Class representing a Studio Language Model Manager.\n */\n\nexport class StudioLMManager {\n private static instance: StudioLMManager | null = null;\n private serverUrl: string;\n private initialized = false;\n private availableModels: StudioLMModel[] = [];\n private configuredModels = {\n small: process.env.STUDIOLM_SMALL_MODEL || 'lmstudio-community/deepseek-r1-distill-qwen-1.5b',\n medium: process.env.STUDIOLM_MEDIUM_MODEL || 'deepseek-r1-distill-qwen-7b',\n };\n\n /**\n * Private constructor for StudioLMManager.\n * Initializes with default serverUrl if not provided in environment variables.\n * Logs initialization information including serverUrl, configuredModels, and timestamp.\n */\n private constructor() {\n this.serverUrl = process.env.STUDIOLM_SERVER_URL || 'http://localhost:1234';\n logger.info('StudioLMManager initialized with configuration:', {\n serverUrl: this.serverUrl,\n configuredModels: this.configuredModels,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Returns an instance of StudioLMManager. If an instance already exists, it returns the existing instance.\n * @returns {StudioLMManager} The instance of StudioLMManager\n */\n public static getInstance(): StudioLMManager {\n if (!StudioLMManager.instance) {\n StudioLMManager.instance = new StudioLMManager();\n }\n return StudioLMManager.instance;\n }\n\n /**\n * Check the status of the server by sending a request to the /v1/models endpoint.\n * @returns {Promise<boolean>} A Promise that resolves to true if the server responds with success status, false otherwise.\n */\n private async checkServerStatus(): Promise<boolean> {\n try {\n const response = await fetch(`${this.serverUrl}/v1/models`);\n if (!response.ok) {\n throw new Error(`Server responded with status: ${response.status}`);\n }\n return true;\n } catch (error) {\n logger.error('LM Studio server check failed:', {\n error: error instanceof Error ? error.message : String(error),\n serverUrl: this.serverUrl,\n timestamp: new Date().toISOString(),\n });\n return false;\n }\n }\n\n /**\n * Fetches the available models from the server and stores them in the 'availableModels' property.\n *\n * @returns {Promise<void>} A Promise that resolves when the models are fetched successfully or rejects with an error.\n */\n private async fetchAvailableModels(): Promise<void> {\n try {\n const response = await fetch(`${this.serverUrl}/v1/models`);\n if (!response.ok) {\n throw new Error(`Failed to fetch models: ${response.status}`);\n }\n\n const data = (await response.json()) as { data: StudioLMModel[] };\n this.availableModels = data.data;\n\n logger.info('LM Studio available models:', {\n count: this.availableModels.length,\n models: this.availableModels.map((m) => m.id),\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n logger.error('Failed to fetch LM Studio models:', {\n error: error instanceof Error ? error.message : String(error),\n serverUrl: this.serverUrl,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously tests the specified model with a chat completion request.\n * @param {string} modelId - The ID of the model to test.\n * @returns {Promise<boolean>} - A promise that resolves to true if the model test was successful, false otherwise.\n */\n private async testModel(modelId: string): Promise<boolean> {\n try {\n const testRequest: ChatCompletionRequest = {\n model: modelId,\n messages: [\n {\n role: 'system',\n content: 'Always answer in rhymes. Today is Thursday',\n },\n { role: 'user', content: 'What day is it today?' },\n ],\n temperature: 0.7,\n max_tokens: -1,\n stream: false,\n };\n\n logger.info(`Testing model ${modelId}...`);\n\n const response = await fetch(`${this.serverUrl}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(testRequest),\n });\n\n if (!response.ok) {\n throw new Error(`Model test failed with status: ${response.status}`);\n }\n\n const result = (await response.json()) as ChatCompletionResponse;\n\n if (!result.choices?.[0]?.message?.content) {\n throw new Error('No valid response content received');\n }\n\n logger.info(`Model ${modelId} test response:`, {\n content: result.choices[0].message.content,\n model: result.model,\n timestamp: new Date().toISOString(),\n });\n\n return true;\n } catch (error) {\n logger.error(`Model ${modelId} test 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\n /**\n * Tests the configured text models to ensure they are working properly.\n * Logs the results of the test and any failed models.\n * @returns {Promise<void>} A promise that resolves when the test is complete.\n */\n private async testTextModels(): Promise<void> {\n logger.info('Testing configured text models...');\n\n const results = await Promise.all([\n this.testModel(this.configuredModels.small),\n this.testModel(this.configuredModels.medium),\n ]);\n\n const [smallWorking, mediumWorking] = results;\n\n if (!smallWorking || !mediumWorking) {\n const failedModels = [];\n if (!smallWorking) failedModels.push('small');\n if (!mediumWorking) failedModels.push('medium');\n\n logger.warn('Some models failed the test:', {\n failedModels,\n small: this.configuredModels.small,\n medium: this.configuredModels.medium,\n });\n } else {\n logger.success('All configured models passed the test');\n }\n }\n\n /**\n * Initializes StudioLM by checking server status, fetching available models,\n * and testing text models.\n *\n * @returns {Promise<void>} A Promise that resolves when initialization is complete\n */\n public async initialize(): Promise<void> {\n try {\n if (this.initialized) {\n logger.info('StudioLM already initialized, skipping initialization');\n return;\n }\n\n logger.info('Starting StudioLM initialization...');\n const serverAvailable = await this.checkServerStatus();\n\n if (!serverAvailable) {\n throw new Error('LM Studio server is not available');\n }\n\n await this.fetchAvailableModels();\n await this.testTextModels();\n\n this.initialized = true;\n logger.success('StudioLM initialization complete');\n } catch (error) {\n logger.error('StudioLM initialization 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 * Retrieves the available models in the studio.\n *\n * @returns {StudioLMModel[]} An array of StudioLMModel objects representing the available models.\n */\n public getAvailableModels(): StudioLMModel[] {\n return this.availableModels;\n }\n\n /**\n * Check if the object is initialized.\n *\n * @returns {boolean} Returns true if the object is initialized, otherwise false.\n */\n public isInitialized(): boolean {\n return this.initialized;\n }\n\n /**\n * Asynchronously generates text using StudioLM based on provided parameters.\n *\n * @param {GenerateTextParams} params - The parameters for generating text.\n * @param {boolean} [isInitialized=false] - Flag to indicate if the model is already initialized.\n * @returns {Promise<string>} The generated text as a Promise.\n */\n public async generateText(params: GenerateTextParams, isInitialized = false): Promise<string> {\n try {\n // Log entry point with all parameters\n logger.info('StudioLM generateText entry:', {\n isInitialized,\n currentInitState: this.initialized,\n managerInitState: this.isInitialized(),\n modelType: params.modelType,\n contextLength: params.prompt?.length,\n timestamp: new Date().toISOString(),\n });\n\n // Only initialize if not already initialized and not marked as initialized\n if (!this.initialized && !isInitialized) {\n throw new Error('StudioLM not initialized. Please initialize before generating text.');\n }\n\n const messages: ChatMessage[] = [\n {\n role: 'system',\n content: 'You are a helpful AI assistant. Respond to the current request only.',\n },\n { role: 'user', content: params.prompt },\n ];\n\n logger.info('StudioLM preparing request:', {\n model:\n params.modelType === ModelType.TEXT_LARGE\n ? this.configuredModels.medium\n : this.configuredModels.small,\n messageCount: messages.length,\n timestamp: new Date().toISOString(),\n });\n\n logger.info('Incoming context structure:', {\n contextLength: params.prompt.length,\n hasAction: params.prompt.includes('action'),\n runtime: !!params.runtime,\n stopSequences: params.stopSequences,\n });\n\n const request: ChatCompletionRequest = {\n model:\n params.modelType === ModelType.TEXT_LARGE\n ? this.configuredModels.medium\n : this.configuredModels.small,\n messages,\n temperature: 0.7,\n max_tokens: 8192,\n stream: false,\n };\n\n const response = await fetch(`${this.serverUrl}/v1/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n throw new Error(`StudioLM request failed: ${response.status}`);\n }\n\n const result = (await response.json()) as ChatCompletionResponse;\n\n if (!result.choices?.[0]?.message?.content) {\n throw new Error('No valid response content received from StudioLM');\n }\n\n let responseText = result.choices[0].message.content;\n\n // Log raw response for debugging\n logger.info('Raw response structure:', {\n responseLength: responseText.length,\n hasAction: responseText.includes('action'),\n hasThinkTag: responseText.includes('<think>'),\n });\n\n // Clean think tags if present\n if (responseText.includes('<think>')) {\n logger.info('Cleaning think tags from response');\n responseText = responseText.replace(/<think>[\\s\\S]*?<\\/think>\\n?/g, '');\n logger.info('Think tags removed from response');\n }\n\n logger.info('StudioLM request completed successfully:', {\n responseLength: responseText.length,\n hasThinkTags: responseText.includes('<think>'),\n timestamp: new Date().toISOString(),\n });\n\n return responseText;\n } catch (error) {\n logger.error('StudioLM text generation error:', {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n phase: 'text generation',\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n }\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';\nimport { nodewhisper } from 'nodejs-whisper';\n\nconst execAsync = promisify(exec);\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 const tempInputFile = path.join(this.cacheDir, `temp_input_${Date.now()}`);\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 // 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 // Save original stdout and stderr write functions\n const originalStdoutWrite = process.stdout.write;\n const originalStderrWrite = process.stderr.write;\n\n // Create a no-op function to suppress output\n const noopWrite = () => true;\n\n // Redirect stdout and stderr to suppress whisper output\n process.stdout.write = noopWrite;\n process.stderr.write = noopWrite;\n\n let output: string;\n try {\n // Transcribe using whisper with output suppressed\n output = await nodewhisper(wavFile, {\n modelName: 'base.en',\n autoDownloadModelName: 'base.en',\n verbose: false,\n whisperOptions: {\n outputInText: true,\n language: 'en',\n },\n });\n } finally {\n // Restore original stdout and stderr\n process.stdout.write = originalStdoutWrite;\n process.stderr.write = originalStderrWrite;\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 // Extract just the text content without timestamps\n const cleanText = output\n .split('\\n')\n .map((line) => {\n // Remove timestamps if present [00:00:00.000 --> 00:00:00.000]\n const textMatch = line.match(/](.+)$/);\n return textMatch ? textMatch[1].trim() : line.trim();\n })\n .filter((line) => line) // Remove empty lines\n .join(' ');\n\n logger.success('Transcription complete:', {\n textLength: cleanText.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 fs from 'node:fs';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\nimport { logger } from '@elizaos/core';\nimport {\n type LlamaContext,\n type LlamaContextSequence,\n type LlamaModel,\n type Token,\n getLlama,\n} from 'node-llama-cpp';\nimport { MODEL_SPECS } from '../types';\nimport { prependWavHeader } from './audioUtils';\nimport { DownloadManager } from './downloadManager';\n\n/**\n * Interface representing the response from a Text-to-Speech (TTS) service.\n * @typedef { Object } TTSResponse\n * @property {number[]} tokens - The array of token ids representing the text to be converted to speech.\n * @property { Float32Array } [audio] - Optional Float32Array representing the audio data output from the TTS service.\n */\ninterface TTSResponse {\n tokens: number[];\n audio?: Float32Array;\n}\n\n/**\n * Class representing a Text-to-Speech Manager\n */\nexport class TTSManager {\n private static instance: TTSManager | null = null;\n private cacheDir: string;\n private model: LlamaModel | null = null;\n private ctx: LlamaContext | null = null;\n private sequence: LlamaContextSequence | null = null;\n private initialized = false;\n private downloadManager: DownloadManager;\n private modelsDir: string;\n\n /**\n * Creates a new instance of TTSManager with the provided cache directory.\n *\n * @param {string} cacheDir - The directory where cached data will be stored.\n */\n private constructor(cacheDir: string) {\n this.cacheDir = path.join(cacheDir, 'tts');\n this.modelsDir = process.env.LLAMALOCAL_PATH?.trim()\n ? path.resolve(process.env.LLAMALOCAL_PATH.trim())\n : path.join(process.cwd(), 'models');\n this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);\n this.ensureCacheDirectory();\n logger.debug('TTSManager initialized');\n }\n\n /**\n * Returns an instance of TTSManager, creating a new one if none exist.\n *\n * @param {string} cacheDir - The directory path to store cached audio files.\n * @returns {TTSManager} An instance of TTSManager.\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 /**\n * Ensures that the cache directory exists. If it does not exist, the directory will be created.\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 /**\n * Asynchronously initializes the TTS module with GGUF backend.\n * If already initialized or missing necessary components (model and context), it returns early.\n * Handles model download using different URL patterns as fallback if model not found locally.\n * Initializes the TTS model, creates context, and sets the sequence for TTS generation.\n * Logs detailed steps and final output of initialization.\n *\n * @returns {Promise<void>} A promise that resolves once the TTS module is fully initialized.\n */\n private async initialize(): Promise<void> {\n try {\n if (this.initialized && this.model && this.ctx) {\n return;\n }\n\n logger.info('Initializing TTS with GGUF backend...');\n\n const modelSpec = MODEL_SPECS.tts.base;\n const modelPath = path.join(this.modelsDir, modelSpec.name);\n\n // Log detailed model configuration and paths\n // logger.info(\"TTS model configuration:\", {\n // name: modelSpec.name,\n // repo: modelSpec.repo,\n // modelPath,\n // timestamp: new Date().toISOString()\n // });\n\n if (!fs.existsSync(modelPath)) {\n // Try different URL patterns in sequence\n const attempts = [\n {\n spec: { ...modelSpec },\n description: 'Standard URL with GGUF',\n url: `https://huggingface.co/${modelSpec.repo}/resolve/main/${modelSpec.name}?download=true`,\n },\n {\n spec: { ...modelSpec, repo: modelSpec.repo.replace('-GGUF', '') },\n description: 'URL without GGUF suffix',\n url: `https://huggingface.co/${modelSpec.repo.replace('-GGUF', '')}/resolve/main/${modelSpec.name}?download=true`,\n },\n {\n spec: { ...modelSpec, name: modelSpec.name.replace('-Q8_0', '') },\n description: 'URL without quantization suffix',\n url: `https://huggingface.co/${modelSpec.repo}/resolve/main/${modelSpec.name.replace('-Q8_0', '')}.gguf?download=true`,\n },\n ];\n\n let lastError = null;\n for (const attempt of attempts) {\n try {\n logger.info('Attempting TTS model download:', {\n description: attempt.description,\n repo: attempt.spec.repo,\n name: attempt.spec.name,\n url: attempt.url,\n timestamp: new Date().toISOString(),\n });\n\n const barLength = 30;\n const emptyBar = '▱'.repeat(barLength);\n logger.info(`Downloading TTS model: ${emptyBar} 0%`);\n\n await this.downloadManager.downloadFromUrl(attempt.url, modelPath);\n\n const completedBar = '▰'.repeat(barLength);\n logger.info(`Downloading TTS model: ${completedBar} 100%`);\n logger.success('TTS model download successful with:', attempt.description);\n break;\n } catch (error) {\n lastError = error;\n logger.warn('TTS 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 (!fs.existsSync(modelPath)) {\n throw lastError || new Error('All download attempts failed');\n }\n }\n\n logger.info('Loading TTS model...');\n const llama = await getLlama();\n this.model = await llama.loadModel({\n modelPath,\n gpuLayers: 0, // Force CPU for now until we add GPU support\n });\n\n this.ctx = await this.model.createContext({\n contextSize: modelSpec.contextSize,\n });\n\n this.sequence = this.ctx.getSequence();\n\n logger.success('TTS initialization complete', {\n modelPath,\n contextSize: modelSpec.contextSize,\n timestamp: new Date().toISOString(),\n });\n this.initialized = true;\n } catch (error) {\n logger.error('TTS initialization failed:', {\n error: error instanceof Error ? error.message : String(error),\n model: MODEL_SPECS.tts.base.name,\n timestamp: new Date().toISOString(),\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously generates speech from a given text using the initialized TTS model.\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 audio data.\n * @throws {Error} If the TTS model is not initialized or if no audio tokens are generated.\n */\n public async generateSpeech(text: string): Promise<Readable> {\n try {\n await this.initialize();\n\n if (!this.model || !this.ctx || !this.sequence) {\n throw new Error('TTS model not initialized');\n }\n\n logger.info('Starting speech generation for text:', { text });\n\n // Format prompt for TTS generation\n const prompt = `[SPEAKER=female_1][LANGUAGE=en]${text}`;\n logger.info('Formatted prompt:', { prompt });\n\n // Tokenize input\n logger.info('Tokenizing input...');\n const inputTokens = this.model.tokenize(prompt);\n logger.info('Input tokenized:', { tokenCount: inputTokens.length });\n\n // Generate audio tokens with optimized limit (2x input)\n const maxTokens = inputTokens.length * 2;\n logger.info('Starting token generation with optimized limit:', {\n maxTokens,\n });\n const responseTokens: Token[] = [];\n const _startTime = Date.now();\n\n try {\n for await (const token of this.sequence.evaluate(inputTokens, {\n temperature: 0.1,\n })) {\n responseTokens.push(token);\n\n // Update progress bar\n const percent = Math.round((responseTokens.length / maxTokens) * 100);\n const barLength = 30;\n const filledLength = Math.floor((responseTokens.length / maxTokens) * barLength);\n const progressBar = '▰'.repeat(filledLength) + '▱'.repeat(barLength - filledLength);\n logger.info(\n `Token generation: ${progressBar} ${percent}% (${responseTokens.length}/${maxTokens})`\n );\n\n // Stop if we hit our token limit\n if (responseTokens.length >= maxTokens) {\n logger.info('Token generation complete');\n break;\n }\n }\n } catch (error) {\n logger.error('Token generation error:', error);\n throw error;\n }\n\n // logger.info(\"Token generation stats:\", {\n // inputTokens: inputTokens.length,\n // outputTokens: responseTokens.length,\n // timeMs: Date.now() - startTime\n // });\n\n if (responseTokens.length === 0) {\n throw new Error('No audio tokens generated');\n }\n\n // Convert tokens to audio data\n logger.info('Converting tokens to audio data...');\n const audioData = this.processAudioResponse({\n tokens: responseTokens.map((t) => Number.parseInt(this.model.detokenize([t]), 10)),\n });\n\n logger.info('Audio data generated:', {\n byteLength: audioData.length,\n sampleRate: MODEL_SPECS.tts.base.sampleRate,\n });\n\n // Create WAV format\n const audioStream = prependWavHeader(\n Readable.from(audioData),\n audioData.length,\n MODEL_SPECS.tts.base.sampleRate,\n 1,\n 16\n );\n\n logger.success('Speech generation complete');\n return audioStream;\n } catch (error) {\n logger.error('Speech generation failed:', {\n error: error instanceof Error ? error.message : String(error),\n text,\n });\n throw error;\n }\n }\n\n /**\n * Processes the audio response from the TTS service by converting\n * the data to 16-bit PCM format.\n * If the response contains direct audio data, it converts Float32Array\n * to 16-bit PCM. If the response only contains tokens, it converts\n * them to PCM data. The actual conversion process may vary depending\n * on the model used.\n *\n * @param {TTSResponse} response - The response object from the TTS service\n * @returns {Buffer} The processed audio data in 16-bit PCM format\n */\n private processAudioResponse(response: TTSResponse): Buffer {\n if (response.audio) {\n // If we have direct audio data, convert Float32Array to 16-bit PCM\n const pcmData = new Int16Array(response.audio.length);\n for (let i = 0; i < response.audio.length; i++) {\n // Convert float to 16-bit PCM\n const s = Math.max(-1, Math.min(1, response.audio[i]));\n pcmData[i] = s < 0 ? s * 0x8000 : s * 0x7fff;\n }\n return Buffer.from(pcmData.buffer);\n }\n\n // If we only have tokens, convert them to PCM data\n // This is a placeholder implementation - actual conversion depends on model\n const pcmData = new Int16Array(response.tokens.length * 2);\n for (let i = 0; i < response.tokens.length; i++) {\n // Simple conversion for testing - replace with actual model-specific conversion\n pcmData[i * 2] = response.tokens[i] & 0xffff;\n pcmData[i * 2 + 1] = (response.tokens[i] >> 16) & 0xffff;\n }\n return Buffer.from(pcmData.buffer);\n }\n}\n","import { PassThrough, type Readable } from 'node:stream';\n\n/**\n * Generates a WAV header for audio data based on the input parameters.\n *\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 audio channels (default is 1).\n * @param {number} [bitsPerSample=16] - The number of bits per audio sample (default is 16).\n * @returns {Buffer} - The WAV header as a Buffer.\n */\nexport function 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\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 an audio stream.\n *\n * @param {Readable} readable - The readable stream of audio data.\n * @param {number} audioLength - The length of the audio in seconds.\n * @param {number} sampleRate - The sample rate of the audio.\n * @param {number} [channelCount=1] - The number of audio channels. Default is 1.\n * @param {number} [bitsPerSample=16] - The number of bits per sample. Default is 16.\n * @returns {Readable} - A readable stream with the WAV header prepended to the audio data.\n */\nexport function prependWavHeader(\n readable: Readable,\n audioLength: number,\n sampleRate: number,\n channelCount = 1,\n bitsPerSample = 16\n): Readable {\n const wavHeader = getWavHeader(audioLength, sampleRate, channelCount, bitsPerSample);\n let pushedHeader = false;\n const passThrough = new PassThrough();\n readable.on('data', (data) => {\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","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 PreTrainedModel,\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","path","Readable","ModelType","logger","getLlama","logger","logger","logger","ModelType","logger","logger","fs","exec","fs","path","promisify","logger","execAsync","fs","path","logger","path","logger","fs","pcmData","fs","os","path","process","logger","AutoTokenizer","path","logger","os","process","fs","AutoTokenizer","mimeType","buffer","path","fs","logger","ModelType","getLlama","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 {\n type IAgentRuntime,\n ModelType,\n type Plugin,\n logger,\n} 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(\n this.cacheDir,\n this.modelsDir\n );\n this.tokenizerManager = TokenizerManager.getInstance(\n this.cacheDir,\n this.modelsDir\n );\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 =\n this.config?.MODELS_DIR?.trim() || process.env.MODELS_DIR?.trim();\n if (modelsDirEnv) {\n this.modelsDir = path.resolve(modelsDirEnv);\n logger.info(\n \"Using models directory from MODELS_DIR environment variable:\",\n this.modelsDir\n );\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(\n \"Ensured models directory exists (created):\",\n this.modelsDir\n );\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 =\n this.config?.CACHE_DIR?.trim() || process.env.CACHE_DIR?.trim();\n if (cacheDirEnv) {\n this.cacheDir = path.resolve(cacheDirEnv);\n logger.info(\n \"Using cache directory from CACHE_DIR environment variable:\",\n this.cacheDir\n );\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(\n this.modelsDir,\n this.config.LOCAL_SMALL_MODEL\n );\n this.mediumModelPath = path.join(\n this.modelsDir,\n this.config.LOCAL_LARGE_MODEL\n );\n this.embeddingModelPath = path.join(\n this.modelsDir,\n this.config.LOCAL_EMBEDDING_MODEL\n ); // 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(\n \"Using embedding model path:\",\n basename(this.embeddingModelPath)\n );\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 =\n modelType === ModelType.TEXT_LARGE\n ? MODEL_SPECS.medium\n : MODEL_SPECS.small;\n modelPathToDownload =\n modelType === ModelType.TEXT_LARGE\n ? this.mediumModelPath\n : this.modelPath; // Use configured path\n }\n\n try {\n // Pass the determined path to the download manager\n return await this.downloadManager.downloadModel(\n modelSpec,\n modelPathToDownload\n );\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(\n modelType: ModelTypeName = ModelType.TEXT_SMALL\n ): 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(\n \"Models directory does not exist, creating it:\",\n this.modelsDir\n );\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 =\n 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 =\n 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(\n params.prompt,\n this.activeModelConfig\n );\n logger.info(\"Input tokens:\", { count: tokens.length });\n\n // QUICK TEST FIX: Add system message to reset prompt\n const systemMessage =\n \"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\n ? this.smallModel.tokenize(wordsToPunish.join(\" \"))\n : [],\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(\n this.cacheDir\n );\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(\n \"Transcription prerequisites (FFmpeg) checked and ready.\"\n );\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() {\n try {\n logger.debug(\"Initializing local-ai plugin environment...\");\n // Call initializeEnvironment (now public)\n await localAIManager.initializeEnvironment();\n logger.success(\"Local AI plugin configuration validated and initialized\");\n } catch (error) {\n logger.error(\"Plugin initialization 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 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 (\n _runtime: IAgentRuntime,\n params: TextEmbeddingParams\n ) => {\n const text = params?.text;\n try {\n // Handle null/undefined/empty text\n if (!text) {\n logger.debug(\n \"Null or empty text input for embedding, returning zero vector\"\n );\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 (\n runtime: IAgentRuntime,\n params: ObjectGenerationParams\n ) => {\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 (\n !jsonPrompt.includes(\"```json\") &&\n !jsonPrompt.includes(\"respond with valid JSON\")\n ) {\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(\n \"Initial JSON parse failed, attempting to fix common issues\"\n );\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(\n /\"([^\"]*?)[^a-zA-Z0-9\\s\\.,;:\\-_\\(\\)\"'\\[\\]{}]([^\"]*?)\"/g,\n '\"$1$2\"'\n )\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 (\n runtime: IAgentRuntime,\n params: ObjectGenerationParams\n ) => {\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 (\n !jsonPrompt.includes(\"```json\") &&\n !jsonPrompt.includes(\"respond with valid JSON\")\n ) {\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(\n \"Initial JSON parse failed, attempting to fix common issues\"\n );\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(\n /\"([^\"]*?)[^a-zA-Z0-9\\s\\.,;:\\-_\\(\\)\"'\\[\\]{}]([^\"]*?)\"/g,\n '\"$1$2\"'\n )\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 (\n _runtime: IAgentRuntime,\n imageUrl: string\n ) => {\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 (\n _runtime: IAgentRuntime,\n audioBuffer: Buffer\n ) => {\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 (\n _runtime: IAgentRuntime,\n text: string\n ) => {\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(\n ModelType.TEXT_EMBEDDING,\n {\n text: \"This is a test of the text embedding model.\",\n }\n );\n\n logger.info(\n \"Embedding generated with dimensions:\",\n embedding.length\n );\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(\n ModelType.TEXT_EMBEDDING,\n null\n );\n if (\n !Array.isArray(nullEmbedding) ||\n nullEmbedding.some((val) => val !== 0)\n ) {\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(\n ModelType.TEXT_TOKENIZER_ENCODE,\n { text }\n );\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(\n \"TEXT_TOKENIZER_ENCODE test completed successfully\"\n );\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(\n ModelType.TEXT_TOKENIZER_ENCODE,\n {\n text: originalText,\n }\n );\n\n // Then decode it back\n const decodedText = await runtime.useModel(\n ModelType.TEXT_TOKENIZER_DECODE,\n {\n tokens,\n }\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(\n \"TEXT_TOKENIZER_DECODE test completed successfully\"\n );\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 const imageUrl =\n \"https://raw.githubusercontent.com/microsoft/FLAML/main/website/static/img/flaml.png\";\n const result = await runtime.useModel(\n ModelType.IMAGE_DESCRIPTION,\n imageUrl\n );\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 (\n typeof result.title !== \"string\" ||\n typeof result.description !== \"string\"\n ) {\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 simple audio buffer for testing\n const audioData = new Uint8Array([\n 0x52,\n 0x49,\n 0x46,\n 0x46, // \"RIFF\"\n 0x24,\n 0x00,\n 0x00,\n 0x00, // Chunk size\n 0x57,\n 0x41,\n 0x56,\n 0x45, // \"WAVE\"\n 0x66,\n 0x6d,\n 0x74,\n 0x20, // \"fmt \"\n ]);\n const audioBuffer = Buffer.from(audioData);\n\n const transcription = await runtime.useModel(\n ModelType.TRANSCRIPTION,\n audioBuffer\n );\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 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(\n ModelType.TEXT_TO_SPEECH,\n testText\n );\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(\n cacheDir: string,\n modelsDir: string\n ): 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(\n url: string,\n destPath: string\n ): 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\":\n \"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)\n .then(resolve)\n .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(\n response.headers[\"content-length\"] || \"0\",\n 10\n );\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(\n (downloadedSize / totalSize) * barLength\n );\n const progressBar =\n \"▰\".repeat(filledLength) + \"▱\".repeat(barLength - filledLength);\n logger.info(\n `Downloading ${fileName}: ${progressBar} ${percent}%`\n );\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(\n new Error(`Temporary file ${tempPath} does not exist`)\n );\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(\n `Created backup of existing file: ${backupPath}`\n );\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(\n `Removed backup file after successful update: ${backupPath}`\n );\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(\n `Restored from backup after failed update: ${backupPath}`\n );\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(\n `Download of ${fileName} completed successfully`\n );\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(\n `File write error: ${err instanceof Error ? err.message : String(err)}`\n );\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(\n `Request error: ${err instanceof Error ? err.message : String(err)}`\n );\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(\n `Download for ${destPath} already in progress, waiting for it to complete...`\n );\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(\n modelSpec: ModelSpec,\n modelPath: string\n ): 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(\n \"system_profiler SPDisplaysDataType\"\n );\n return {\n name:\n gpuInfo.split(\"Chipset Model:\")[1]?.split(\"\\n\")[0]?.trim() ||\n \"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(\n \"wmic path win32_VideoController get name\"\n );\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 {\n AutoTokenizer,\n type PreTrainedTokenizer,\n} 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(\n `Tokenizer ${tokenizerKey} exists in map but returned undefined`\n );\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(\n \"Models directory does not exist, creating it:\",\n this.modelsDir\n );\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(\n modelConfig.tokenizer.name,\n {\n cache_dir: this.modelsDir,\n local_files_only: false,\n }\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:\n tokenizeError instanceof Error\n ? tokenizeError.message\n : String(tokenizeError),\n stack:\n 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(\n modelConfig.tokenizer.name,\n {\n cache_dir: this.modelsDir,\n local_files_only: false,\n }\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\";\nimport { nodewhisper } from \"nodejs-whisper\";\n\nconst execAsync = promisify(exec);\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(\n \"which ffmpeg || where ffmpeg\"\n );\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:\n error instanceof Error && \"stderr\" in error\n ? error.stderr\n : 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 =\n stdout.includes(\"pcm_s16le\") && stdout.includes(\"wav\");\n\n if (!hasRequiredCodecs) {\n throw new Error(\n \"FFmpeg installation missing required codecs (pcm_s16le, wav)\"\n );\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(\n \"FFmpeg is required but not properly installed. Please install FFmpeg:\",\n {\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 /**\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(\n inputPath: string,\n outputPath: string\n ): 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(\n \"FFmpeg is not installed. Please install FFmpeg to use audio transcription.\"\n );\n }\n\n try {\n const tempInputFile = path.join(\n this.cacheDir,\n `temp_input_${Date.now()}`\n );\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 // 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 // Save original stdout and stderr write functions\n const originalStdoutWrite = process.stdout.write;\n const originalStderrWrite = process.stderr.write;\n\n // Create a no-op function to suppress output\n const noopWrite = () => true;\n\n // Redirect stdout and stderr to suppress whisper output\n process.stdout.write = noopWrite;\n process.stderr.write = noopWrite;\n\n let output: string;\n try {\n // Transcribe using whisper with output suppressed\n output = await nodewhisper(wavFile, {\n modelName: \"base.en\",\n autoDownloadModelName: \"base.en\",\n verbose: false,\n whisperOptions: {\n outputInText: true,\n language: \"en\",\n },\n });\n } finally {\n // Restore original stdout and stderr\n process.stdout.write = originalStdoutWrite;\n process.stderr.write = originalStderrWrite;\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 // Extract just the text content without timestamps\n const cleanText = output\n .split(\"\\n\")\n .map((line) => {\n // Remove timestamps if present [00:00:00.000 --> 00:00:00.000]\n const textMatch = line.match(/](.+)$/);\n return textMatch ? textMatch[1].trim() : line.trim();\n })\n .filter((line) => line) // Remove empty lines\n .join(\" \");\n\n logger.success(\"Transcription complete:\", {\n textLength: cleanText.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 fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { logger, prependWavHeader } from \"@elizaos/core\";\nimport { pipeline, type TextToAudioPipeline } from \"@huggingface/transformers\";\nimport { fetch } from \"undici\";\nimport { MODEL_SPECS } from \"../types\";\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(\n \"TTS initialization already in progress, awaiting existing promise.\"\n );\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(\n \"Default TTS model specification not found in MODEL_SPECS.\"\n );\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(\n `TTS pipeline loaded successfully for model: ${modelName}`\n );\n\n // 2. Load Default Speaker Embedding (if specified)\n if (speakerEmbeddingUrl) {\n const embeddingFilename = path.basename(\n new URL(speakerEmbeddingUrl).pathname\n );\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(\n `Downloading default speaker embedding from: ${speakerEmbeddingUrl}`\n );\n const response = await fetch(speakerEmbeddingUrl);\n if (!response.ok) {\n throw new Error(\n `Failed to download speaker embedding: ${response.statusText}`\n );\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(\n \"TTS initializingPromise cleared after completion/failure.\"\n );\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(\n this.cacheDir,\n this.modelsDir\n );\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(\n modelId: string,\n type: \"model\" | \"tokenizer\" | \"processor\"\n ): boolean {\n const modelPath = path.join(\n this.modelsDir,\n modelId.replace(\"/\", \"--\"),\n type\n );\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(\n (c) => c.name === componentName\n );\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(\n \"Vision model already initialized, skipping initialization\"\n );\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(\n modelSpec.modelId,\n {\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\n ? Math.max(0, Math.min(1, progressInfo.progress))\n : 0;\n const currentProgress = Math.round(progress * 100);\n if (\n currentProgress > lastProgress + 9 ||\n currentProgress === 100\n ) {\n lastProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor(\n (currentProgress / 100) * barLength\n );\n const progressBar =\n \"▰\".repeat(filledLength) +\n \"▱\".repeat(barLength - filledLength);\n logger.info(\n `Downloading vision model: ${progressBar} ${currentProgress}%`\n );\n if (currentProgress === 100) this.modelDownloaded = true;\n }\n }) as ProgressCallback,\n }\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(\n modelSpec.modelId,\n \"tokenizer\"\n );\n let tokenizerProgress = -1;\n\n this.tokenizer = await AutoTokenizer.from_pretrained(\n modelSpec.modelId,\n {\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\n ? Math.max(0, Math.min(1, progressInfo.progress))\n : 0;\n const currentProgress = Math.round(progress * 100);\n if (currentProgress !== tokenizerProgress) {\n tokenizerProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor(\n (currentProgress / 100) * barLength\n );\n const progressBar =\n \"▰\".repeat(filledLength) +\n \"▱\".repeat(barLength - filledLength);\n logger.info(\n `Downloading vision tokenizer: ${progressBar} ${currentProgress}%`\n );\n if (currentProgress === 100) this.tokenizerDownloaded = true;\n }\n }) as ProgressCallback,\n }\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(\n modelSpec.modelId,\n \"processor\"\n );\n let processorProgress = -1;\n\n this.processor = (await AutoProcessor.from_pretrained(\n modelSpec.modelId,\n {\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\n ? Math.max(0, Math.min(1, progressInfo.progress))\n : 0;\n const currentProgress = Math.round(progress * 100);\n if (currentProgress !== processorProgress) {\n processorProgress = currentProgress;\n const barLength = 30;\n const filledLength = Math.floor(\n (currentProgress / 100) * barLength\n );\n const progressBar =\n \"▰\".repeat(filledLength) +\n \"▱\".repeat(barLength - filledLength);\n logger.info(\n `Downloading vision processor: ${progressBar} ${currentProgress}%`\n );\n if (currentProgress === 100) this.processorDownloaded = true;\n }\n }) as ProgressCallback,\n }\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(\n url: string\n ): 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(\n imageUrl: string\n ): 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","fs","path","logger","fetch","path","logger","fs","fetch","fs","os","path","process","logger","AutoTokenizer","path","logger","os","process","fs","AutoTokenizer","mimeType","buffer","path","logger","os","fs","Readable"]}
|