il2cpp-dump-analyzer-mcp
Version:
Agentic RAG system for analyzing IL2CPP dump.cs files from Unity games
182 lines • 7.58 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.XenovaEmbeddings = void 0;
const embeddings_1 = require("@langchain/core/embeddings");
const path = __importStar(require("path"));
// We'll use dynamic import for the Xenova transformers package since it's an ESM module
let pipeline;
let env;
let transformers;
// This will be initialized in the constructor
async function loadTransformers() {
try {
transformers = await import('@xenova/transformers');
pipeline = transformers.pipeline;
env = transformers.env;
// Set environment variables for Xenova with proper Docker support
env.allowLocalModels = false;
env.useBrowserCache = false;
// Use absolute path with environment variable for Docker compatibility
env.cacheDir = path.resolve(process.env.MODEL_CACHE_PATH || '/app/models');
// Ensure cache directory exists and is writable
const fs = await import('fs');
try {
await fs.promises.mkdir(env.cacheDir, { recursive: true });
console.log(`✓ Xenova model cache directory ready: ${env.cacheDir}`);
}
catch (error) {
console.warn(`Warning: Could not create model cache directory: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
return { pipeline, env, transformers };
}
catch (error) {
console.error('Failed to load @xenova/transformers:', error);
throw error;
}
}
/**
* Embeddings implementation using Xenova's Transformers.js with the all-MiniLM-L6-v2 model
*/
class XenovaEmbeddings extends embeddings_1.Embeddings {
/**
* Initialize the Xenova embeddings model
* @param model Model name to use, defaults to 'Xenova/all-MiniLM-L6-v2'
*/
constructor(model = 'Xenova/all-MiniLM-L6-v2') {
super({});
this.model = model;
this.dimensions = 384; // all-MiniLM-L6-v2 produces 384-dimensional embeddings
this.ready = this.initialize();
}
/**
* Initialize the embedding pipeline with Docker-friendly error handling
*/
async initialize() {
const maxRetries = 3;
const retryDelay = 5000; // 5 seconds
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
console.log(`Initializing Xenova embeddings model: ${this.model} (attempt ${attempt}/${maxRetries})`);
// Load the transformers library
await loadTransformers();
// Initialize the pipeline with timeout for Docker environments
console.log('Loading embedding model... This may take a few minutes on first run.');
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Model loading timeout')), 300000); // 5 minutes
});
const modelPromise = pipeline('feature-extraction', this.model);
this.embeddingPipeline = await Promise.race([modelPromise, timeoutPromise]);
console.log('✓ Xenova embeddings model initialized successfully');
return; // Success, exit retry loop
}
catch (error) {
console.error(`Failed to initialize Xenova embeddings model (attempt ${attempt}/${maxRetries}):`, error);
if (attempt === maxRetries) {
throw new Error(`Failed to initialize Xenova embeddings after ${maxRetries} attempts: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
console.log(`Retrying in ${retryDelay / 1000} seconds...`);
await new Promise(resolve => setTimeout(resolve, retryDelay));
}
}
}
/**
* Create embeddings for an array of texts
* @param texts Array of texts to embed
* @returns Promise resolving to a 2D array of embeddings
*/
async embedDocuments(texts) {
await this.ready;
const embeddings = [];
// Process in batches to improve performance
const batchSize = 10;
for (let i = 0; i < texts.length; i += batchSize) {
const batch = texts.slice(i, i + batchSize);
const batchPromises = batch.map(text => this.embedQuery(text));
const batchEmbeddings = await Promise.all(batchPromises);
embeddings.push(...batchEmbeddings);
}
return embeddings;
}
/**
* Create an embedding for a single query text
* @param text Text to embed
* @returns Promise resolving to an embedding vector
*/
async embedQuery(text) {
await this.ready;
try {
// Preprocess text for better embeddings
const processedText = this.preprocessText(text);
// Generate embedding using the Xenova model
const result = await this.embeddingPipeline(processedText, {
pooling: 'mean',
normalize: true,
});
// Extract the embedding vector and ensure it's an array of numbers
// Explicitly cast to number[] to fix type issues
const embedding = Array.from(result.data).map(val => Number(val));
return embedding;
}
catch (error) {
console.error('Error generating embedding with Xenova model:', error);
throw error;
}
}
/**
* Preprocess text before embedding to improve quality
* @param text Text to preprocess
* @returns Processed text
*/
preprocessText(text) {
// Remove excessive whitespace
let processed = text.replace(/\s+/g, ' ').trim();
// Limit text length to avoid token limits
const maxLength = 512;
if (processed.length > maxLength) {
processed = processed.substring(0, maxLength);
}
return processed;
}
/**
* Get the dimensionality of the embeddings
* @returns The number of dimensions in the embedding vectors
*/
getDimension() {
return this.dimensions;
}
}
exports.XenovaEmbeddings = XenovaEmbeddings;
//# sourceMappingURL=xenova-embeddings.js.map