@elizaos/plugin-local-embedding 2.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1886 -0
- package/dist/index.js.map +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/environment.ts","../src/types.ts","../src/utils/downloadManager.ts","../src/utils/platform.ts","../src/utils/tokenizerManager.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path, { basename } from \"node:path\";\nimport type {\n DetokenizeTextParams,\n ModelTypeName,\n TextEmbeddingParams,\n TokenizeTextParams,\n} from \"@elizaos/core\";\nimport { type IAgentRuntime, logger, ModelType, type Plugin } from \"@elizaos/core\";\nimport {\n getLlama,\n type Llama,\n type LlamaEmbeddingContext,\n LlamaLogLevel,\n type LlamaModel,\n} from \"node-llama-cpp\";\nimport { type Config, validateConfig } from \"./environment\";\nimport { type EmbeddingModelSpec, MODEL_SPECS, type ModelSpec } from \"./types\";\nimport { DownloadManager } from \"./utils/downloadManager\";\nimport { getPlatformManager } from \"./utils/platform\";\nimport { TokenizerManager } from \"./utils/tokenizerManager\";\n\nconst CORRUPTED_MODEL_ERROR_SIGNATURES = [\n \"data is not within the file bounds\",\n \"failed to load model\",\n \"model is corrupted\",\n \"data of tensor\",\n \"is out of bounds\",\n];\nconst CONTEXT_LIMIT_ERROR_SIGNATURES = [\n \"input is longer than the context size\",\n \"context size\",\n \"too many tokens\",\n \"exceeds context\",\n];\nconst NODE_LLAMA_NOISY_LOAD_ERROR_PATTERNS = [\n \"llama_model_load:\",\n \"llama_model_load_from_file_impl: failed to load model\",\n];\nconst MIN_EMBEDDING_RETRY_TEXT_LENGTH = 1;\n\ntype EmbeddingModelHint = {\n pattern: RegExp;\n repo: string;\n dimensions: number;\n contextSize: number;\n};\n\nconst EMBEDDING_MODEL_HINTS: EmbeddingModelHint[] = [\n {\n pattern: /nomic-embed-text-v1\\.5/i,\n repo: \"nomic-ai/nomic-embed-text-v1.5-GGUF\",\n dimensions: 768,\n contextSize: 8192,\n },\n {\n pattern: /bge-small-en-v1\\.5/i,\n repo: \"ChristianAzinn/bge-small-en-v1.5-gguf\",\n dimensions: 384,\n contextSize: 512,\n },\n {\n pattern: /e5-mistral-7b/i,\n repo: \"dranger003/e5-mistral-7b-instruct-GGUF\",\n dimensions: 4096,\n contextSize: 32768,\n },\n];\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return String(error);\n}\n\nfunction isCorruptedModelLoadError(error: unknown): boolean {\n const message = getErrorMessage(error).toLowerCase();\n return CORRUPTED_MODEL_ERROR_SIGNATURES.some((signature) => message.includes(signature));\n}\n\nfunction isContextLimitError(error: unknown): boolean {\n const message = getErrorMessage(error).toLowerCase();\n return CONTEXT_LIMIT_ERROR_SIGNATURES.some((signature) => message.includes(signature));\n}\n\nfunction shouldSuppressNodeLlamaLoadError(message: string): boolean {\n const lower = message.toLowerCase();\n return NODE_LLAMA_NOISY_LOAD_ERROR_PATTERNS.some((pattern) => lower.includes(pattern));\n}\n\nfunction shrinkEmbeddingInput(text: string): string {\n if (text.length <= MIN_EMBEDDING_RETRY_TEXT_LENGTH) return text;\n const nextLength = Math.max(MIN_EMBEDDING_RETRY_TEXT_LENGTH, Math.floor(text.length / 2));\n return text.slice(0, nextLength);\n}\n\nfunction inferEmbeddingModelHint(modelName: string): EmbeddingModelHint | null {\n const match = EMBEDDING_MODEL_HINTS.find((hint) => hint.pattern.test(modelName));\n return match ?? null;\n}\n\nfunction resolveEmbeddingModelSpec(\n config: Config,\n fallback: EmbeddingModelSpec\n): EmbeddingModelSpec {\n const modelName = config.LOCAL_EMBEDDING_MODEL || fallback.name;\n const hint = inferEmbeddingModelHint(modelName);\n\n return {\n ...fallback,\n name: modelName,\n repo: config.LOCAL_EMBEDDING_MODEL_REPO?.trim() || hint?.repo || fallback.repo,\n dimensions: config.LOCAL_EMBEDDING_DIMENSIONS ?? hint?.dimensions ?? fallback.dimensions,\n contextSize: config.LOCAL_EMBEDDING_CONTEXT_SIZE ?? hint?.contextSize ?? fallback.contextSize,\n };\n}\n\nfunction readMagicHeader(filePath: string): { bytesRead: number; magic: string } {\n try {\n const fd = fs.openSync(filePath, \"r\");\n try {\n const header = Buffer.alloc(4);\n const bytesRead = fs.readSync(fd, header, 0, header.length, 0);\n return { bytesRead, magic: header.toString(\"ascii\", 0, 4) };\n } finally {\n fs.closeSync(fd);\n }\n } catch {\n return { bytesRead: 0, magic: \"\" };\n }\n}\n\nfunction isValidGgufFile(filePath: string): boolean {\n const { bytesRead, magic } = readMagicHeader(filePath);\n return bytesRead === 4 && magic === \"GGUF\";\n}\n\nfunction safeUnlink(filePath: string): void {\n if (!filePath || !fs.existsSync(filePath)) return;\n try {\n fs.unlinkSync(filePath);\n } catch (err) {\n logger.warn(\n `Failed to remove model file ${filePath}: ${err instanceof Error ? err.message : String(err)}`\n );\n }\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 embeddingModel: LlamaModel | undefined;\n private embeddingContext: LlamaEmbeddingContext | 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 activeModelConfig: ModelSpec;\n private embeddingModelConfig: EmbeddingModelSpec;\n private config: Config | null = null; // Store validated config\n\n // Initialization state flag\n private embeddingInitialized = false;\n private environmentInitialized = false; // Add flag for environment initialization\n\n // Initialization promises to prevent duplicate initialization\n private embeddingInitializingPromise: Promise<void> | null = null;\n private environmentInitializingPromise: Promise<void> | null = null; // Add promise for environment\n\n private modelsDir!: string;\n\n /**\n * Private constructor function to initialize base managers and paths.\n * Model paths are set after environment initialization.\n */\n private constructor() {\n this.config = validateConfig();\n\n this._setupCacheDir();\n\n // Initialize active model config (default)\n this.activeModelConfig = MODEL_SPECS.small;\n // Initialize embedding model config (spec details)\n this.embeddingModelConfig = MODEL_SPECS.embedding;\n }\n\n /**\n * Post-validation initialization steps that require config to be set.\n * Called after config validation in initializeEnvironment.\n */\n private _postValidateInit(): void {\n this._setupModelsDir();\n\n // Initialize managers that depend on modelsDir\n this.downloadManager = DownloadManager.getInstance(this.cacheDir, this.modelsDir);\n this.tokenizerManager = TokenizerManager.getInstance(this.cacheDir, this.modelsDir);\n }\n\n /**\n * Sets up the models directory, reading from config or environment variables,\n * and ensures the directory exists.\n */\n private _setupModelsDir(): void {\n // Set up models directory consistently, similar to cacheDir\n const modelsDirEnv = this.config?.MODELS_DIR?.trim() || process.env.MODELS_DIR?.trim();\n if (modelsDirEnv) {\n this.modelsDir = path.resolve(modelsDirEnv);\n logger.info(\"Using models directory from MODELS_DIR environment variable:\", this.modelsDir);\n } else {\n this.modelsDir = path.join(os.homedir(), \".eliza\", \"models\");\n logger.info(\n \"MODELS_DIR environment variable not set, using default models directory:\",\n this.modelsDir\n );\n }\n\n // Ensure models directory exists\n if (!fs.existsSync(this.modelsDir)) {\n fs.mkdirSync(this.modelsDir, { recursive: true });\n logger.debug(\"Ensured models directory exists (created):\", this.modelsDir);\n } else {\n logger.debug(\"Models directory already exists:\", this.modelsDir);\n }\n }\n\n /**\n * Sets up the cache directory, reading from config or environment variables,\n * and ensures the directory exists.\n */\n private _setupCacheDir(): void {\n // Set up cache directory\n const cacheDirEnv = this.config?.CACHE_DIR?.trim() || process.env.CACHE_DIR?.trim();\n if (cacheDirEnv) {\n this.cacheDir = path.resolve(cacheDirEnv);\n logger.info(\"Using cache directory from CACHE_DIR environment variable:\", this.cacheDir);\n } else {\n const cacheDir = path.join(os.homedir(), \".eliza\", \"cache\");\n // Ensure cache directory exists\n if (!fs.existsSync(cacheDir)) {\n fs.mkdirSync(cacheDir, { recursive: true });\n logger.debug(\"Ensuring cache directory exists (created):\", cacheDir);\n }\n this.cacheDir = cacheDir;\n logger.info(\n \"CACHE_DIR environment variable not set, using default cache directory:\",\n this.cacheDir\n );\n }\n // Ensure cache directory exists if specified via env var but not yet created\n if (!fs.existsSync(this.cacheDir)) {\n fs.mkdirSync(this.cacheDir, { recursive: true });\n logger.debug(\"Ensured cache directory exists (created):\", this.cacheDir);\n } else {\n logger.debug(\"Cache directory already exists:\", this.cacheDir);\n }\n }\n\n /**\n * Retrieves the singleton instance of LocalAIManager. If an instance does not already exist, a new one is created and returned.\n * @returns {LocalAIManager} The singleton instance of LocalAIManager\n */\n public static getInstance(): LocalAIManager {\n if (!LocalAIManager.instance) {\n LocalAIManager.instance = new LocalAIManager();\n }\n return LocalAIManager.instance;\n }\n\n /**\n * Initializes the environment by validating the configuration and setting model paths.\n * Now public to be callable from plugin init and model handlers.\n *\n * @returns {Promise<void>} A Promise that resolves once the environment has been successfully initialized.\n */\n public async initializeEnvironment(): Promise<void> {\n // Prevent duplicate initialization\n if (this.environmentInitialized) return;\n if (this.environmentInitializingPromise) {\n await this.environmentInitializingPromise;\n return;\n }\n\n this.environmentInitializingPromise = (async () => {\n try {\n logger.info(\"Initializing environment configuration...\");\n\n // Re-validate config to ensure it's up to date\n this.config = await validateConfig();\n this.embeddingModelConfig = resolveEmbeddingModelSpec(this.config, MODEL_SPECS.embedding);\n\n // Initialize components that depend on validated config\n this._postValidateInit();\n\n // Set model paths based on validated config\n this.embeddingModelPath = path.join(this.modelsDir, this.embeddingModelConfig.name); // Set embedding path\n\n logger.info(\"Using embedding model path:\", basename(this.embeddingModelPath));\n logger.info(\n {\n model: this.embeddingModelConfig.name,\n repo: this.embeddingModelConfig.repo,\n dimensions: this.embeddingModelConfig.dimensions,\n contextSize: this.embeddingModelConfig.contextSize,\n },\n \"Resolved embedding model spec\"\n );\n\n this.ensureEmbeddingModelFileIsValid();\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(\n {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n \"Environment validation failed\"\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 forceDownload = false\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 = this.embeddingModelConfig;\n modelPathToDownload = this.embeddingModelPath; // Use configured path\n this.ensureEmbeddingModelFileIsValid();\n } else {\n modelSpec = modelType === ModelType.TEXT_LARGE ? MODEL_SPECS.medium : MODEL_SPECS.small;\n modelPathToDownload =\n modelType === ModelType.TEXT_LARGE ? this.mediumModelPath : this.modelPath; // Use configured path\n }\n\n try {\n // Pass the determined path to the download manager\n return await this.downloadManager.downloadModel(\n modelSpec,\n modelPathToDownload,\n forceDownload\n );\n } catch (error) {\n logger.error(\n {\n error: error instanceof Error ? error.message : String(error),\n modelType,\n modelPath: modelPathToDownload,\n },\n \"Model download failed\"\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(\n {\n platform: capabilities.platform,\n gpu: capabilities.gpu?.type || \"none\",\n recommendedModel: capabilities.recommendedModelSize,\n supportedBackends: capabilities.supportedBackends,\n },\n \"Platform capabilities detected\"\n );\n } catch (error) {\n logger.warn(error instanceof Error ? error : String(error), \"Platform detection failed\");\n }\n }\n\n /**\n * Initializes the LocalAI Manager for a given model type.\n *\n * @param {ModelTypeName} modelType - The type of model to initialize (default: ModelType.TEXT_SMALL)\n * @returns {Promise<void>} A promise that resolves when initialization is complete or rejects if an error occurs\n */\n async initialize(_modelType: ModelTypeName = ModelType.TEXT_SMALL): Promise<void> {\n await this.initializeEnvironment(); // Ensure environment is initialized first\n }\n\n public getEmbeddingDimensions(): number {\n return this.embeddingModelConfig.dimensions;\n }\n\n private ensureEmbeddingModelFileIsValid(): void {\n if (!this.embeddingModelPath || !fs.existsSync(this.embeddingModelPath)) return;\n if (isValidGgufFile(this.embeddingModelPath)) return;\n\n const { bytesRead, magic } = readMagicHeader(this.embeddingModelPath);\n logger.warn(\n {\n embeddingModelPath: this.embeddingModelPath,\n bytesRead,\n magic,\n },\n \"Invalid embedding model file detected; removing corrupt file before download/retry\"\n );\n safeUnlink(this.embeddingModelPath);\n }\n\n private async ensureLlama(): Promise<void> {\n if (this.llama) return;\n this.llama = await getLlama({\n logLevel: LlamaLogLevel.error,\n logger: (level, message) => {\n if (level !== \"error\" && level !== \"fatal\") return;\n const text = message.trim();\n if (!text) return;\n if (shouldSuppressNodeLlamaLoadError(text)) return;\n logger.error(`[node-llama-cpp] ${text}`);\n },\n });\n }\n\n private async loadEmbeddingModel(): Promise<void> {\n this.ensureEmbeddingModelFileIsValid();\n const gpuLayers =\n this.config?.LOCAL_EMBEDDING_GPU_LAYERS === -1\n ? \"auto\"\n : (this.config?.LOCAL_EMBEDDING_GPU_LAYERS ?? 0);\n const useMmap = this.config?.LOCAL_EMBEDDING_USE_MMAP ?? true;\n\n this.embeddingModel = await this.llama!.loadModel({\n modelPath: this.embeddingModelPath,\n gpuLayers: gpuLayers as number | \"auto\" | undefined,\n vocabOnly: false,\n useMmap,\n });\n\n this.embeddingContext = await this.embeddingModel.createEmbeddingContext({\n contextSize: this.embeddingModelConfig.contextSize,\n batchSize: 512,\n });\n }\n\n private async initializeEmbeddingWithRecovery(): Promise<void> {\n logger.info(\"Loading embedding model:\", this.embeddingModelPath);\n try {\n await this.loadEmbeddingModel();\n logger.success(\"Embedding model initialized successfully\");\n return;\n } catch (error) {\n if (!isCorruptedModelLoadError(error)) {\n throw error;\n }\n logger.warn(\n {\n error: getErrorMessage(error),\n embeddingModelPath: this.embeddingModelPath,\n },\n \"Embedding model appears corrupted/incomplete; deleting and re-downloading\"\n );\n\n this.embeddingModel = undefined;\n this.embeddingContext = undefined;\n safeUnlink(this.embeddingModelPath);\n\n await this.downloadModel(ModelType.TEXT_EMBEDDING, undefined, true);\n this.ensureEmbeddingModelFileIsValid();\n await this.loadEmbeddingModel();\n logger.success(\"Embedding model recovered after re-download\");\n }\n }\n\n /**\n * Asynchronously initializes the embedding model.\n *\n * @returns {Promise<void>} A promise that resolves once the initialization is complete.\n */\n public async initializeEmbedding(): Promise<void> {\n try {\n await this.initializeEnvironment(); // Ensure environment/paths are ready\n logger.info(\"Initializing embedding model...\");\n logger.info(\"Models directory:\", this.modelsDir);\n\n // Ensure models directory exists\n if (!fs.existsSync(this.modelsDir)) {\n logger.warn(\"Models directory does not exist, creating it:\", this.modelsDir);\n fs.mkdirSync(this.modelsDir, { recursive: true });\n }\n\n // Download the embedding model using the common downloadModel function\n // This will now use the correct embeddingModelPath\n await this.downloadModel(ModelType.TEXT_EMBEDDING);\n this.ensureEmbeddingModelFileIsValid();\n\n // Initialize the llama instance if not already done\n await this.ensureLlama();\n\n // Load the embedding model\n if (!this.embeddingModel) {\n await this.initializeEmbeddingWithRecovery();\n }\n } catch (error) {\n if (isCorruptedModelLoadError(error)) {\n logger.warn(\n {\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,\n },\n \"Embedding initialization failed due to model corruption\"\n );\n safeUnlink(this.embeddingModelPath);\n } else {\n logger.error(\n {\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 \"Embedding initialization failed with details\"\n );\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({ textLength: text.length }, \"Generating embedding for text\");\n let candidateText = text;\n let attempt = 0;\n while (true) {\n try {\n const embeddingResult = await this.embeddingContext.getEmbeddingFor(candidateText);\n const mutableEmbedding = [...embeddingResult.vector];\n const sizedEmbedding = this.alignEmbeddingDimensions(mutableEmbedding);\n const normalizedEmbedding = this.normalizeEmbedding(sizedEmbedding);\n logger.info({ dimensions: normalizedEmbedding.length }, \"Embedding generation complete\");\n return normalizedEmbedding;\n } catch (error) {\n if (!isContextLimitError(error)) {\n throw error;\n }\n const nextCandidate = shrinkEmbeddingInput(candidateText);\n if (nextCandidate === candidateText) {\n throw error;\n }\n attempt += 1;\n logger.warn(\n {\n attempt,\n currentChars: candidateText.length,\n nextChars: nextCandidate.length,\n },\n \"Embedding input exceeded context window; retrying with truncated text\"\n );\n candidateText = nextCandidate;\n }\n }\n } catch (error) {\n if (isCorruptedModelLoadError(error)) {\n logger.warn(\n {\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 embeddingModelPath: this.embeddingModelPath,\n },\n \"Embedding generation failed due to model corruption; model file removed\"\n );\n safeUnlink(this.embeddingModelPath);\n this.embeddingModel = undefined;\n this.embeddingContext = undefined;\n this.embeddingInitialized = false;\n } else {\n logger.error(\n {\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 \"Embedding generation failed\"\n );\n }\n\n // Return zero vector with correct dimensions as fallback\n const zeroDimensions = this.getEmbeddingDimensions();\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 alignEmbeddingDimensions(embedding: number[]): number[] {\n const targetDimensions = this.getEmbeddingDimensions();\n if (targetDimensions <= 0 || embedding.length === targetDimensions) {\n return embedding;\n }\n\n logger.warn(\n {\n observedDimensions: embedding.length,\n targetDimensions,\n },\n \"Embedding dimensions mismatch; adjusting output dimensions\"\n );\n\n if (embedding.length > targetDimensions) {\n return embedding.slice(0, targetDimensions);\n }\n\n return [...embedding, ...new Array(targetDimensions - embedding.length).fill(0)];\n }\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 this.ensureEmbeddingModelFileIsValid();\n\n // Initialize the llama instance if not already done\n await this.ensureLlama();\n\n await this.initializeEmbeddingWithRecovery();\n\n this.embeddingInitialized = true;\n logger.info(\"Embedding model initialized successfully\");\n } catch (error) {\n if (isCorruptedModelLoadError(error)) {\n logger.warn(\n error instanceof Error ? error : String(error),\n \"Failed to initialize embedding model due to corruption\"\n );\n safeUnlink(this.embeddingModelPath);\n } else {\n logger.error(\n error instanceof Error ? error : String(error),\n \"Failed to initialize embedding model\"\n );\n }\n this.embeddingInitializingPromise = null;\n throw error;\n }\n })();\n }\n\n await this.embeddingInitializingPromise;\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// 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 // Higher priority ensures local embeddings are used instead of remote\n // providers (e.g. ElizaCloud, OpenAI) even when plugins register in\n // parallel and the registration order is non-deterministic.\n priority: 10,\n\n async init(_config: any, _runtime: IAgentRuntime) {\n logger.info(\"Initializing local embedding plugin...\");\n\n try {\n await localAIManager.initializeEnvironment();\n await localAIManager.checkPlatformCapabilities();\n\n const config = validateConfig();\n const modelsDir = config.MODELS_DIR || path.join(os.homedir(), \".eliza\", \"models\");\n const embeddingModelPath = path.join(modelsDir, config.LOCAL_EMBEDDING_MODEL);\n\n if (fs.existsSync(embeddingModelPath)) {\n logger.info(\n { embeddingModelPath: basename(embeddingModelPath) },\n \"Embedding model file is present\"\n );\n } else {\n logger.info(\n { embeddingModelPath: basename(embeddingModelPath) },\n \"Embedding model file not present yet; it will be downloaded on first use\"\n );\n }\n\n logger.success(\"Local embedding plugin initialized\");\n } catch (error) {\n logger.error(\n {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n \"Failed to initialize local embedding plugin\"\n );\n logger.warn(\"Local embedding plugin may be unavailable\");\n }\n },\n models: {\n [ModelType.TEXT_EMBEDDING]: async (\n _runtime: IAgentRuntime,\n params: TextEmbeddingParams | string | null\n ): Promise<number[]> => {\n // Extract text from params - can be string, object with text, or null\n let text: string | undefined;\n if (typeof params === \"string\") {\n text = params;\n } else if (params && typeof params === \"object\" && \"text\" in params) {\n text = params.text;\n }\n\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(localAIManager.getEmbeddingDimensions()).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(\n {\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 \"Error in TEXT_EMBEDDING handler\"\n );\n return new Array(localAIManager.getEmbeddingDimensions()).fill(0);\n }\n },\n\n [ModelType.TEXT_TOKENIZER_ENCODE]: async (\n _runtime: IAgentRuntime,\n params: TokenizeTextParams\n ): Promise<number[]> => {\n try {\n const manager = localAIManager.getTokenizerManager();\n const config = localAIManager.getActiveModelConfig();\n return await manager.encode(params.prompt, config);\n } catch (error) {\n logger.error(\n error instanceof Error ? error : String(error),\n \"Error in TEXT_TOKENIZER_ENCODE handler\"\n );\n throw error;\n }\n },\n\n [ModelType.TEXT_TOKENIZER_DECODE]: async (\n _runtime: IAgentRuntime,\n params: DetokenizeTextParams\n ): Promise<string> => {\n try {\n const manager = localAIManager.getTokenizerManager();\n const config = localAIManager.getActiveModelConfig();\n return await manager.decode(params.tokens, config);\n } catch (error) {\n logger.error(\n error instanceof Error ? error : String(error),\n \"Error in TEXT_TOKENIZER_DECODE handler\"\n );\n throw error;\n }\n },\n },\n tests: [\n {\n name: \"local_ai_plugin_tests\",\n tests: [\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({ count: embedding.length }, \"Embedding generated with dimensions\");\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(\n {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n \"TEXT_EMBEDDING test failed\"\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 prompt = \"Hello tokenizer test!\";\n\n const tokens = await runtime.useModel(ModelType.TEXT_TOKENIZER_ENCODE, {\n prompt,\n modelType: ModelType.TEXT_TOKENIZER_ENCODE,\n });\n logger.info({ count: tokens.length }, \"Encoded tokens\");\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(\n {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n \"TEXT_TOKENIZER_ENCODE test failed\"\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 prompt: originalText,\n modelType: ModelType.TEXT_TOKENIZER_ENCODE,\n });\n\n // Then decode it back\n const decodedText = await runtime.useModel(ModelType.TEXT_TOKENIZER_DECODE, {\n tokens,\n modelType: ModelType.TEXT_TOKENIZER_DECODE,\n });\n logger.info(\n { original: originalText, decoded: decodedText },\n \"Round trip tokenization\"\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(\n {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n \"TEXT_TOKENIZER_DECODE test failed\"\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_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_EMBEDDING_MODEL: z.string().optional().default(DEFAULT_EMBEDDING_MODEL),\n LOCAL_EMBEDDING_MODEL_REPO: z.string().optional(),\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 .transform((val) => {\n if (!val || !val.trim()) return undefined;\n const parsed = Number.parseInt(val, 10);\n return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;\n }),\n LOCAL_EMBEDDING_CONTEXT_SIZE: z\n .string()\n .optional()\n .transform((val) => {\n if (!val || !val.trim()) return undefined;\n const parsed = Number.parseInt(val, 10);\n return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;\n }),\n LOCAL_EMBEDDING_GPU_LAYERS: z\n .string()\n .optional()\n .default(\"0\")\n .transform((val) => {\n if (val === \"auto\") return -1; // -1 signals \"auto\" to our logic\n const num = parseInt(val, 10);\n return Number.isNaN(num) ? 0 : num;\n }),\n LOCAL_EMBEDDING_USE_MMAP: z\n .string()\n .optional()\n .default(\"true\")\n .transform((val) => val === \"true\"),\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 LOCAL_EMBEDDING_MODEL: process.env.LOCAL_EMBEDDING_MODEL,\n LOCAL_EMBEDDING_MODEL_REPO: process.env.LOCAL_EMBEDDING_MODEL_REPO,\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 LOCAL_EMBEDDING_CONTEXT_SIZE: process.env.LOCAL_EMBEDDING_CONTEXT_SIZE,\n LOCAL_EMBEDDING_GPU_LAYERS: process.env.LOCAL_EMBEDDING_GPU_LAYERS,\n LOCAL_EMBEDDING_USE_MMAP: process.env.LOCAL_EMBEDDING_USE_MMAP,\n };\n\n logger.debug(\n {\n LOCAL_EMBEDDING_MODEL: configToParse.LOCAL_EMBEDDING_MODEL,\n LOCAL_EMBEDDING_MODEL_REPO: configToParse.LOCAL_EMBEDDING_MODEL_REPO,\n MODELS_DIR: configToParse.MODELS_DIR,\n CACHE_DIR: configToParse.CACHE_DIR,\n LOCAL_EMBEDDING_DIMENSIONS: configToParse.LOCAL_EMBEDDING_DIMENSIONS,\n LOCAL_EMBEDDING_CONTEXT_SIZE: configToParse.LOCAL_EMBEDDING_CONTEXT_SIZE,\n LOCAL_EMBEDDING_GPU_LAYERS: configToParse.LOCAL_EMBEDDING_GPU_LAYERS,\n LOCAL_EMBEDDING_USE_MMAP: configToParse.LOCAL_EMBEDDING_USE_MMAP,\n },\n \"Validating configuration for local AI plugin from env:\"\n );\n\n const validatedConfig = configSchema.parse(configToParse);\n\n logger.info(validatedConfig, \"Using local AI configuration:\");\n\n return validatedConfig;\n } catch (error) {\n if (error instanceof z.ZodError) {\n const errorMessages = error.issues\n .map((err) => `${err.path.join(\".\")}: ${err.message}`)\n .join(\"\\n\");\n logger.error(errorMessages, \"Zod validation failed:\");\n throw new Error(`Configuration validation failed:\\n${errorMessages}`);\n }\n logger.error(\n {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n },\n \"Configuration validation failed:\"\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\nfunction parseContentLength(contentLength: string | string[] | undefined): number | null {\n if (!contentLength || Array.isArray(contentLength)) return null;\n const parsed = Number.parseInt(contentLength, 10);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;\n}\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 expectedBytes = parseContentLength(response.headers[\"content-length\"]);\n const totalSize = expectedBytes ?? 0;\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 if (!totalSize) return;\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 if (expectedBytes !== null && downloadedSize !== expectedBytes) {\n try {\n fs.unlinkSync(tempPath);\n } catch {\n // best-effort cleanup\n }\n reject(\n new Error(\n `Downloaded file size mismatch for ${destPath}: expected ${expectedBytes} bytes, got ${downloadedSize}`\n )\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(`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(\n modelSpec: ModelSpec,\n modelPath: string,\n forceDownload = false\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) || forceDownload) {\n if (forceDownload && fs.existsSync(modelPath)) {\n logger.warn(\"Force re-download requested; removing existing model file:\", modelPath);\n this.activeDownloads.delete(modelPath);\n try {\n fs.unlinkSync(modelPath);\n } catch (err) {\n logger.warn(\n `Failed to remove existing model file before re-download: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n // Try different URL patterns in sequence, similar to TTS manager approach\n const attempts = [\n {\n description: \"LFS URL with GGUF suffix\",\n url: `https://huggingface.co/${modelSpec.repo}/resolve/main/${modelSpec.name}?download=true`,\n },\n {\n description: \"LFS URL without GGUF suffix\",\n url: `https://huggingface.co/${modelSpec.repo.replace(\"-GGUF\", \"\")}/resolve/main/${modelSpec.name}?download=true`,\n },\n {\n description: \"Standard URL with GGUF suffix\",\n url: `https://huggingface.co/${modelSpec.repo}/resolve/main/${modelSpec.name}`,\n },\n {\n description: \"Standard URL without GGUF suffix\",\n url: `https://huggingface.co/${modelSpec.repo.replace(\"-GGUF\", \"\")}/resolve/main/${modelSpec.name}`,\n },\n ];\n\n // logger.info(\"Model download details:\", {\n // modelName: modelSpec.name,\n // repo: modelSpec.repo,\n // modelPath: modelPath,\n // attemptUrls: attempts.map(a => ({ description: a.description, url: a.url })),\n // timestamp: new Date().toISOString()\n // });\n\n let lastError = null;\n let downloadSuccess = false;\n\n for (const attempt of attempts) {\n try {\n logger.info(\"Attempting model download:\", {\n description: attempt.description,\n url: attempt.url,\n timestamp: new Date().toISOString(),\n });\n\n // The downloadFile method now handles the progress bar display\n await this.downloadFile(attempt.url, modelPath);\n\n logger.success(\n `Model download complete: ${modelSpec.name} using ${attempt.description}`\n );\n downloadSuccess = true;\n break;\n } catch (error) {\n lastError = error;\n logger.warn(\"Model download attempt failed:\", {\n description: attempt.description,\n error: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n if (!downloadSuccess) {\n throw lastError || new Error(\"All download attempts failed\");\n }\n\n // Return true to indicate the model was newly downloaded\n return true;\n }\n\n // Model already exists\n logger.info(\"Model already exists at:\", modelPath);\n // Return false to indicate the model already existed\n return false;\n } catch (error) {\n logger.error(\"Model download failed:\", {\n error: error instanceof Error ? error.message : String(error),\n modelPath: modelPath,\n model: modelSpec.name,\n });\n throw error;\n }\n }\n\n /**\n * Returns the cache directory path.\n *\n * @returns {string} The path of the cache directory.\n */\n\n public getCacheDir(): string {\n return this.cacheDir;\n }\n\n /**\n * Downloads a file from a given URL to a specified destination path.\n *\n * @param {string} url - The URL of the file to download.\n * @param {string} destPath - The destination path where the file should be saved.\n * @returns {Promise<void>} A Promise that resolves once the file has been downloaded.\n */\n public async downloadFromUrl(url: string, destPath: string): Promise<void> {\n return this.downloadFile(url, destPath);\n }\n\n /**\n * Ensures that the specified directory exists. If it does not exist, it will be created.\n * @param {string} dirPath - The path of the directory to ensure existence of.\n * @returns {void}\n */\n public ensureDirectoryExists(dirPath: string): void {\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n logger.info(`Created directory: ${dirPath}`);\n }\n }\n}\n","import { exec } from \"node:child_process\";\nimport os from \"node:os\";\nimport { promisify } from \"node:util\";\nimport { logger } from \"@elizaos/core\";\n\nconst execAsync = promisify(exec);\n\n/**\n * Represents the configuration of a system GPU.\n * @typedef {Object} SystemGPU\n * @property {string} name - The name of the GPU.\n * @property {number} [memory] - The memory size of the GPU. (Optional)\n * @property {\"cuda\" | \"metal\" | \"directml\" | \"none\"} type - The type of GPU.\n * @property {string} [version] - The version of the GPU. (Optional)\n * @property {boolean} [isAppleSilicon] - Indicates if the GPU is Apple Silicon. (Optional)\n */\nexport interface SystemGPU {\n name: string;\n memory?: number;\n type: \"cuda\" | \"metal\" | \"directml\" | \"none\";\n version?: string;\n isAppleSilicon?: boolean;\n}\n\n/**\n * Interface representing the system CPU information.\n * @typedef {Object} SystemCPU\n * @property {string} model - The model of the CPU.\n * @property {number} cores - The number of cores in the CPU.\n * @property {number} speed - The speed of the CPU.\n * @property {string} architecture - The architecture of the CPU.\n * @property {Object} memory - Object containing memory information.\n * @property {number} memory.total - The total memory available.\n * @property {number} memory.free - The free memory available.\n */\nexport interface SystemCPU {\n model: string;\n cores: number;\n speed: number;\n architecture: string;\n memory: {\n total: number;\n free: number;\n };\n}\n\n/**\n * Interface representing the capabilities of a system.\n *\n * @typedef {Object} SystemCapabilities\n * @property {NodeJS.Platform} platform - The platform of the system.\n * @property {SystemCPU} cpu - The CPU information of the system.\n * @property {SystemGPU | null} gpu - The GPU information of the system, can be null if no GPU is present.\n * @property {\"small\" | \"medium\" | \"large\"} recommendedModelSize - The recommended model size for the system.\n * @property {Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\">} supportedBackends - An array of supported backends for the system.\n */\nexport interface SystemCapabilities {\n platform: NodeJS.Platform;\n cpu: SystemCPU;\n gpu: SystemGPU | null;\n recommendedModelSize: \"small\" | \"medium\" | \"large\";\n supportedBackends: Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\">;\n}\n\n/**\n * Class representing a Platform Manager.\n *\n * @class\n */\n\nexport class PlatformManager {\n private static instance: PlatformManager;\n private capabilities: SystemCapabilities | null = null;\n\n /**\n * Private constructor method.\n */\n private constructor() {}\n\n /**\n * Get the singleton instance of the PlatformManager class\n * @returns {PlatformManager} The instance of PlatformManager\n */\n static getInstance(): PlatformManager {\n if (!PlatformManager.instance) {\n PlatformManager.instance = new PlatformManager();\n }\n return PlatformManager.instance;\n }\n\n /**\n * Asynchronous method to initialize platform detection.\n *\n * @returns {Promise<void>} Promise that resolves once platform detection is completed.\n */\n async initialize(): Promise<void> {\n try {\n logger.info(\"Initializing platform detection...\");\n this.capabilities = await this.detectSystemCapabilities();\n // logger.info(\"Platform detection completed\", {\n // platform: this.capabilities.platform,\n // gpu: this.capabilities.gpu?.type || \"none\",\n // recommendedModel: this.capabilities.recommendedModelSize,\n // });\n } catch (error) {\n logger.error(\"Platform detection failed\", { error });\n throw error;\n }\n }\n\n /**\n * Detects the system capabilities including platform, CPU information, GPU information,\n * supported backends, and recommended model size.\n *\n * @returns {Promise<SystemCapabilities>} Details of the system capabilities including platform, CPU info, GPU info,\n * recommended model size, and supported backends.\n */\n private async detectSystemCapabilities(): Promise<SystemCapabilities> {\n const platform = process.platform;\n const cpuInfo = this.getCPUInfo();\n const gpu = await this.detectGPU();\n const supportedBackends = await this.getSupportedBackends(platform, gpu);\n const recommendedModelSize = this.getRecommendedModelSize(cpuInfo, gpu);\n\n return {\n platform,\n cpu: cpuInfo,\n gpu,\n recommendedModelSize,\n supportedBackends,\n };\n }\n\n /**\n * Returns information about the CPU and memory of the system.\n * @returns {SystemCPU} The CPU information including model, number of cores, speed, architecture, and memory details.\n */\n private getCPUInfo(): SystemCPU {\n const cpus = os.cpus();\n const totalMemory = os.totalmem();\n const freeMemory = os.freemem();\n\n return {\n model: cpus[0].model,\n cores: cpus.length,\n speed: cpus[0].speed,\n architecture: process.arch,\n memory: {\n total: totalMemory,\n free: freeMemory,\n },\n };\n }\n\n /**\n * Asynchronously detects the GPU information based on the current platform.\n * @returns A promise that resolves with the GPU information if detection is successful, otherwise null.\n */\n private async detectGPU(): Promise<SystemGPU | null> {\n const platform = process.platform;\n\n try {\n switch (platform) {\n case \"darwin\":\n return await this.detectMacGPU();\n case \"win32\":\n return await this.detectWindowsGPU();\n case \"linux\":\n return await this.detectLinuxGPU();\n default:\n return null;\n }\n } catch (error) {\n logger.error(\"GPU detection failed\", { error });\n return null;\n }\n }\n\n /**\n * Asynchronously detects the GPU of a Mac system.\n * @returns {Promise<SystemGPU>} A promise that resolves to an object representing the detected GPU.\n */\n private async detectMacGPU(): Promise<SystemGPU> {\n try {\n const { stdout } = await execAsync(\"sysctl -n machdep.cpu.brand_string\");\n const isAppleSilicon = stdout.toLowerCase().includes(\"apple\");\n\n if (isAppleSilicon) {\n return {\n name: \"Apple Silicon\",\n type: \"metal\",\n isAppleSilicon: true,\n };\n }\n\n // For Intel Macs with discrete GPU\n const { stdout: gpuInfo } = await execAsync(\"system_profiler SPDisplaysDataType\");\n return {\n name: gpuInfo.split(\"Chipset Model:\")[1]?.split(\"\\n\")[0]?.trim() || \"Unknown GPU\",\n type: \"metal\",\n isAppleSilicon: false,\n };\n } catch (error) {\n logger.error(\"Mac GPU detection failed\", { error });\n return {\n name: \"Unknown Mac GPU\",\n type: \"metal\",\n isAppleSilicon: false,\n };\n }\n }\n\n /**\n * Detects the GPU in a Windows system and returns information about it.\n *\n * @returns {Promise<SystemGPU | null>} A promise that resolves with the detected GPU information or null if detection fails.\n */\n private async detectWindowsGPU(): Promise<SystemGPU | null> {\n try {\n const { stdout } = await execAsync(\"wmic path win32_VideoController get name\");\n const gpuName = stdout.split(\"\\n\")[1].trim();\n\n // Check for NVIDIA GPU\n if (gpuName.toLowerCase().includes(\"nvidia\")) {\n const { stdout: nvidiaInfo } = await execAsync(\n \"nvidia-smi --query-gpu=name,memory.total --format=csv,noheader\"\n );\n const [name, memoryStr] = nvidiaInfo.split(\",\").map((s) => s.trim());\n const memory = Number.parseInt(memoryStr, 10);\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, 10);\n\n return {\n name,\n memory,\n type: \"cuda\",\n version: await this.getNvidiaDriverVersion(),\n };\n }\n } catch {\n // If nvidia-smi fails, check for other GPUs\n try {\n const { stdout } = await execAsync(\"lspci | grep -i vga\");\n return {\n name: stdout.split(\":\").pop()?.trim() || \"Unknown GPU\",\n type: \"none\",\n };\n } catch (error) {\n logger.error(\"Linux GPU detection failed\", { error });\n return null;\n }\n }\n return null;\n }\n\n /**\n * Asynchronously retrieves the driver version of the Nvidia GPU using the 'nvidia-smi' command.\n *\n * @returns A promise that resolves with the driver version as a string, or 'unknown' if an error occurs.\n */\n private async getNvidiaDriverVersion(): Promise<string> {\n try {\n const { stdout } = await execAsync(\n \"nvidia-smi --query-gpu=driver_version --format=csv,noheader\"\n );\n return stdout.trim();\n } catch {\n return \"unknown\";\n }\n }\n\n /**\n * Retrieves the supported backends based on the platform and GPU type.\n * @param {NodeJS.Platform} platform - The platform on which the code is running.\n * @param {SystemGPU | null} gpu - The GPU information, if available.\n * @returns {Promise<Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\">>} - An array of supported backends including 'cuda', 'metal', 'directml', and 'cpu'.\n */\n private async getSupportedBackends(\n platform: NodeJS.Platform,\n gpu: SystemGPU | null\n ): Promise<Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\">> {\n const backends: Array<\"cuda\" | \"metal\" | \"directml\" | \"cpu\"> = [\"cpu\"];\n\n if (gpu) {\n switch (platform) {\n case \"darwin\":\n backends.push(\"metal\");\n break;\n case \"win32\":\n if (gpu.type === \"cuda\") {\n backends.push(\"cuda\");\n }\n backends.push(\"directml\");\n break;\n case \"linux\":\n if (gpu.type === \"cuda\") {\n backends.push(\"cuda\");\n }\n break;\n }\n }\n\n return backends;\n }\n\n /**\n * Determines the recommended model size based on the system's CPU and GPU.\n * @param {SystemCPU} cpu - The system's CPU.\n * @param {SystemGPU | null} gpu - The system's GPU, if available.\n * @returns {\"small\" | \"medium\" | \"large\"} - The recommended model size (\"small\", \"medium\", or \"large\").\n */\n private getRecommendedModelSize(\n cpu: SystemCPU,\n gpu: SystemGPU | null\n ): \"small\" | \"medium\" | \"large\" {\n // For Apple Silicon\n if (gpu?.isAppleSilicon) {\n return cpu.memory.total > 16 * 1024 * 1024 * 1024 ? \"medium\" : \"small\";\n }\n\n // For NVIDIA GPUs\n if (gpu?.type === \"cuda\") {\n const gpuMemGB = (gpu.memory || 0) / 1024;\n if (gpuMemGB >= 16) return \"large\";\n if (gpuMemGB >= 8) return \"medium\";\n }\n\n // For systems with significant RAM but no powerful GPU\n if (cpu.memory.total > 32 * 1024 * 1024 * 1024) return \"medium\";\n\n // Default to small model\n return \"small\";\n }\n\n /**\n * Returns the SystemCapabilities of the PlatformManager.\n *\n * @returns {SystemCapabilities} The SystemCapabilities of the PlatformManager.\n * @throws {Error} if PlatformManager is not initialized.\n */\n getCapabilities(): SystemCapabilities {\n if (!this.capabilities) {\n throw new Error(\"PlatformManager not initialized\");\n }\n return this.capabilities;\n }\n\n /**\n * Checks if the device's GPU is Apple Silicon.\n * @returns {boolean} True if the GPU is Apple Silicon, false otherwise.\n */\n isAppleSilicon(): boolean {\n return !!this.capabilities?.gpu?.isAppleSilicon;\n }\n\n /**\n * Checks if the current device has GPU support.\n * @returns {boolean} - Returns true if the device has GPU support, false otherwise.\n */\n hasGPUSupport(): boolean {\n return !!this.capabilities?.gpu;\n }\n\n /**\n * Checks if the system supports CUDA GPU for processing.\n *\n * @returns {boolean} True if the system supports CUDA, false otherwise.\n */\n supportsCUDA(): boolean {\n return this.capabilities?.gpu?.type === \"cuda\";\n }\n\n /**\n * Check if the device supports Metal API for rendering graphics.\n * @returns {boolean} True if the device supports Metal, false otherwise.\n */\n supportsMetal(): boolean {\n return this.capabilities?.gpu?.type === \"metal\";\n }\n\n /**\n * Check if the device supports DirectML for GPU acceleration.\n *\n * @returns {boolean} True if the device supports DirectML, false otherwise.\n */\n supportsDirectML(): boolean {\n return this.capabilities?.gpu?.type === \"directml\";\n }\n\n /**\n * Get the recommended backend for computation based on the available capabilities.\n * @returns {\"cuda\" | \"metal\" | \"directml\" | \"cpu\"} The recommended backend for computation.\n * @throws {Error} Throws an error if PlatformManager is not initialized.\n */\n getRecommendedBackend(): \"cuda\" | \"metal\" | \"directml\" | \"cpu\" {\n if (!this.capabilities) {\n throw new Error(\"PlatformManager not initialized\");\n }\n\n const { gpu, supportedBackends } = this.capabilities;\n\n if (gpu?.type === \"cuda\") return \"cuda\";\n if (gpu?.type === \"metal\") return \"metal\";\n if (supportedBackends.includes(\"directml\")) return \"directml\";\n return \"cpu\";\n }\n}\n\n// Export a helper function to get the singleton instance\nexport const getPlatformManager = (): PlatformManager => {\n return PlatformManager.getInstance();\n};\n","import { logger } from \"@elizaos/core\";\nimport { AutoTokenizer, type PreTrainedTokenizer } from \"@huggingface/transformers\";\n\n// Import the MODEL_SPECS type from a new types file we'll create later\nimport type { ModelSpec } from \"../types\";\n\n/**\n * Represents a Tokenizer Manager which manages tokenizers for different models.\n * * @class TokenizerManager\n */\nexport class TokenizerManager {\n private static instance: TokenizerManager | null = null;\n private tokenizers: Map<string, PreTrainedTokenizer>;\n private cacheDir: string;\n private modelsDir: string;\n\n /**\n * Constructor for creating a new instance of the class.\n *\n * @param {string} cacheDir - The directory for caching data.\n * @param {string} modelsDir - The directory for storing models.\n */\n private constructor(cacheDir: string, modelsDir: string) {\n this.tokenizers = new Map();\n this.cacheDir = cacheDir;\n this.modelsDir = modelsDir;\n }\n\n /**\n * Get the singleton instance of TokenizerManager class. If the instance does not exist, it will create a new one.\n *\n * @param {string} cacheDir - The directory to cache the tokenizer models.\n * @param {string} modelsDir - The directory where tokenizer models are stored.\n * @returns {TokenizerManager} The singleton instance of TokenizerManager.\n */\n static getInstance(cacheDir: string, modelsDir: string): TokenizerManager {\n if (!TokenizerManager.instance) {\n TokenizerManager.instance = new TokenizerManager(cacheDir, modelsDir);\n }\n return TokenizerManager.instance;\n }\n\n /**\n * Asynchronously loads a tokenizer based on the provided ModelSpec configuration.\n *\n * @param {ModelSpec} modelConfig - The configuration object for the model to load the tokenizer for.\n * @returns {Promise<PreTrainedTokenizer>} - A promise that resolves to the loaded tokenizer.\n */\n async loadTokenizer(modelConfig: ModelSpec): Promise<PreTrainedTokenizer> {\n try {\n const tokenizerKey = `${modelConfig.tokenizer.type}-${modelConfig.tokenizer.name}`;\n logger.info(\"Loading tokenizer:\", {\n key: tokenizerKey,\n name: modelConfig.tokenizer.name,\n type: modelConfig.tokenizer.type,\n modelsDir: this.modelsDir,\n cacheDir: this.cacheDir,\n });\n\n if (this.tokenizers.has(tokenizerKey)) {\n logger.info(\"Using cached tokenizer:\", { key: tokenizerKey });\n const cachedTokenizer = this.tokenizers.get(tokenizerKey);\n if (!cachedTokenizer) {\n throw new Error(`Tokenizer ${tokenizerKey} exists in map but returned undefined`);\n }\n return cachedTokenizer;\n }\n\n // Check if models directory exists\n const fs = await import(\"node:fs\");\n if (!fs.existsSync(this.modelsDir)) {\n logger.warn(\"Models directory does not exist, creating it:\", this.modelsDir);\n fs.mkdirSync(this.modelsDir, { recursive: true });\n }\n\n logger.info(\n \"Initializing new tokenizer from HuggingFace with models directory:\",\n this.modelsDir\n );\n\n try {\n const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {\n cache_dir: this.modelsDir,\n local_files_only: false,\n });\n\n this.tokenizers.set(tokenizerKey, tokenizer);\n logger.success(\"Tokenizer loaded successfully:\", { key: tokenizerKey });\n return tokenizer;\n } catch (tokenizeError) {\n logger.error(\"Failed to load tokenizer from HuggingFace:\", {\n error: tokenizeError instanceof Error ? tokenizeError.message : String(tokenizeError),\n stack: tokenizeError instanceof Error ? tokenizeError.stack : undefined,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n\n // Try again with local_files_only set to false and a longer timeout\n logger.info(\"Retrying tokenizer loading...\");\n const tokenizer = await AutoTokenizer.from_pretrained(modelConfig.tokenizer.name, {\n cache_dir: this.modelsDir,\n local_files_only: false,\n });\n\n this.tokenizers.set(tokenizerKey, tokenizer);\n logger.success(\"Tokenizer loaded successfully on retry:\", {\n key: tokenizerKey,\n });\n return tokenizer;\n }\n } catch (error) {\n logger.error(\"Failed to load tokenizer:\", {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n model: modelConfig.name,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n\n /**\n * Encodes the given text using the specified tokenizer model configuration.\n *\n * @param {string} text - The text to encode.\n * @param {ModelSpec} modelConfig - The configuration for the model tokenizer.\n * @returns {Promise<number[]>} - An array of integers representing the encoded text.\n * @throws {Error} - If the text encoding fails, an error is thrown.\n */\n async encode(text: string, modelConfig: ModelSpec): Promise<number[]> {\n try {\n logger.info(\"Encoding text with tokenizer:\", {\n length: text.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n\n const tokenizer = await this.loadTokenizer(modelConfig);\n\n logger.info(\"Tokenizer loaded, encoding text...\");\n const encoded = await tokenizer.encode(text, {\n add_special_tokens: true,\n return_token_type_ids: false,\n });\n\n logger.info(\"Text encoded successfully:\", {\n tokenCount: encoded.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n return encoded;\n } catch (error) {\n logger.error(\"Text encoding failed:\", {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n textLength: text.length,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n\n /**\n * Asynchronously decodes an array of tokens using a tokenizer based on the provided ModelSpec.\n *\n * @param {number[]} tokens - The array of tokens to be decoded.\n * @param {ModelSpec} modelConfig - The ModelSpec object containing information about the model and tokenizer to be used.\n * @returns {Promise<string>} - A Promise that resolves with the decoded text.\n * @throws {Error} - If an error occurs during token decoding.\n */\n async decode(tokens: number[], modelConfig: ModelSpec): Promise<string> {\n try {\n logger.info(\"Decoding tokens with tokenizer:\", {\n count: tokens.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n\n const tokenizer = await this.loadTokenizer(modelConfig);\n\n logger.info(\"Tokenizer loaded, decoding tokens...\");\n const decoded = await tokenizer.decode(tokens, {\n skip_special_tokens: true,\n clean_up_tokenization_spaces: true,\n });\n\n logger.info(\"Tokens decoded successfully:\", {\n textLength: decoded.length,\n tokenizer: modelConfig.tokenizer.name,\n });\n return decoded;\n } catch (error) {\n logger.error(\"Token decoding failed:\", {\n error: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n tokenCount: tokens.length,\n tokenizer: modelConfig.tokenizer.name,\n modelsDir: this.modelsDir,\n });\n throw error;\n }\n }\n}\n"],"mappings":"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","names":["fs","os","path","logger","logger","logger","logger","fs","fs","logger","path","os"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elizaos/plugin-local-embedding",
|
|
3
|
+
"version": "2.0.0-alpha.10",
|
|
4
|
+
"description": "Local AI model embedding and inference plugin for ElizaOS",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"test": "vitest run --passWithNoTests",
|
|
22
|
+
"clean": "rm -rf dist .turbo node_modules",
|
|
23
|
+
"lint": "bunx @biomejs/biome check --write --unsafe .",
|
|
24
|
+
"lint:check": "bunx @biomejs/biome check .",
|
|
25
|
+
"format": "bunx @biomejs/biome format --write .",
|
|
26
|
+
"format:check": "bunx @biomejs/biome format .",
|
|
27
|
+
"typecheck": "tsc --noEmit --noCheck"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@elizaos/core": "2.0.0-alpha.3",
|
|
31
|
+
"@huggingface/transformers": "^3.5.1",
|
|
32
|
+
"node-llama-cpp": "^3.15.1",
|
|
33
|
+
"nodejs-whisper": "0.2.9",
|
|
34
|
+
"stream-browserify": "^3.0.0",
|
|
35
|
+
"undici": "^7.10.0",
|
|
36
|
+
"uuid": "11.1.0",
|
|
37
|
+
"whisper-node": "^1.1.1",
|
|
38
|
+
"zod": "^4.3.6"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.0.3",
|
|
42
|
+
"@types/uuid": "10.0.0",
|
|
43
|
+
"tsup": "8.5.0",
|
|
44
|
+
"typescript": "^5.8.2",
|
|
45
|
+
"@biomejs/biome": "^2.3.11"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"agentConfig": {
|
|
51
|
+
"pluginType": "elizaos:plugin:1.0.0",
|
|
52
|
+
"pluginParameters": {
|
|
53
|
+
"MODELS_DIR": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "Filesystem path to the directory where AI models are stored; required for initializing the LocalAI plugin during tests.",
|
|
56
|
+
"required": true,
|
|
57
|
+
"sensitive": false
|
|
58
|
+
},
|
|
59
|
+
"CACHE_DIR": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "Filesystem path to the cache directory for model assets used by the LocalAI plugin during tests.",
|
|
62
|
+
"required": true,
|
|
63
|
+
"sensitive": false
|
|
64
|
+
},
|
|
65
|
+
"LOCAL_SMALL_MODEL": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"description": "Filename of the small local AI model; overrides the built-in default model if provided.",
|
|
68
|
+
"required": false,
|
|
69
|
+
"default": "DeepHermes-3-Llama-3-3B-Preview-q4.gguf",
|
|
70
|
+
"sensitive": false
|
|
71
|
+
},
|
|
72
|
+
"LOCAL_LARGE_MODEL": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"description": "Filename of the large local AI model; overrides the built-in default model if provided.",
|
|
75
|
+
"required": false,
|
|
76
|
+
"default": "DeepHermes-3-Llama-3-8B-q4.gguf",
|
|
77
|
+
"sensitive": false
|
|
78
|
+
},
|
|
79
|
+
"LOCAL_EMBEDDING_MODEL": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"description": "Filename of the embedding model used for vector embeddings; overrides the default if supplied.",
|
|
82
|
+
"required": false,
|
|
83
|
+
"default": "bge-small-en-v1.5.Q4_K_M.gguf",
|
|
84
|
+
"sensitive": false
|
|
85
|
+
},
|
|
86
|
+
"LOCAL_EMBEDDING_MODEL_REPO": {
|
|
87
|
+
"type": "string",
|
|
88
|
+
"description": "Optional HuggingFace repo used to resolve LOCAL_EMBEDDING_MODEL downloads.",
|
|
89
|
+
"required": false,
|
|
90
|
+
"sensitive": false
|
|
91
|
+
},
|
|
92
|
+
"LOCAL_EMBEDDING_DIMENSIONS": {
|
|
93
|
+
"type": "number",
|
|
94
|
+
"description": "Optional embedding dimension override; when omitted, dimensions are inferred from model defaults/hints.",
|
|
95
|
+
"required": false,
|
|
96
|
+
"sensitive": false
|
|
97
|
+
},
|
|
98
|
+
"LOCAL_EMBEDDING_CONTEXT_SIZE": {
|
|
99
|
+
"type": "number",
|
|
100
|
+
"description": "Optional embedding context size override; when omitted, context size is inferred from model defaults/hints.",
|
|
101
|
+
"required": false,
|
|
102
|
+
"sensitive": false
|
|
103
|
+
},
|
|
104
|
+
"CUDA_VISIBLE_DEVICES": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"description": "Used to detect if CUDA-enabled GPUs are available and configure device and data type settings for model components accordingly.",
|
|
107
|
+
"required": false,
|
|
108
|
+
"sensitive": false
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|