UNPKG

il2cpp-dump-analyzer-mcp

Version:

Agentic RAG system for analyzing IL2CPP dump.cs files from Unity games

309 lines 12.4 kB
"use strict"; /** * Real dump.cs Test Setup Utility * Provides infrastructure for testing MCP tools with actual dump.cs content * Uses existing Enhanced IL2CPP Parser, IL2CPP Code Chunker, and Vector Store */ 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.setupRealDataTest = setupRealDataTest; exports.clearTestCache = clearTestCache; exports.getTestDataStatistics = getTestDataStatistics; exports.findClassByName = findClassByName; exports.findEnumByName = findEnumByName; exports.findMonoBehavioursByPattern = findMonoBehavioursByPattern; exports.findClassesByNamespace = findClassesByNamespace; exports.getSampleEntities = getSampleEntities; exports.createRealDataVectorStore = createRealDataVectorStore; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const documents_1 = require("@langchain/core/documents"); const enhanced_il2cpp_parser_1 = require("../../parser/enhanced-il2cpp-parser"); const chunker_1 = require("../../embeddings/chunker"); const memory_1 = require("langchain/vectorstores/memory"); /** * Mock embeddings for testing that doesn't require actual model loading */ class MockEmbeddings { async initialize() { // Mock initialization - no actual model loading } async embedDocuments(texts) { // Return mock embeddings - simple hash-based vectors for testing return texts.map(text => this.createMockEmbedding(text)); } async embedQuery(text) { return this.createMockEmbedding(text); } createMockEmbedding(text) { // Create a simple deterministic embedding based on text content const embedding = new Array(384).fill(0); for (let i = 0; i < text.length && i < 384; i++) { embedding[i] = (text.charCodeAt(i) % 256) / 256; } return embedding; } } /** * Cache for parsed dump.cs data to avoid re-parsing in every test */ let cachedTestContext = null; let cacheKey = null; /** * Setup real data test environment using actual dump.cs file */ async function setupRealDataTest(config = {}) { const { dumpFilePath = path.join(process.cwd(), 'dump.cs'), useCache = true, chunkSize = 1000, chunkOverlap = 200, maxDocuments = 1000, useDirectContent = false, dumpContent = '' } = config; // Generate cache key based on configuration const currentCacheKey = useDirectContent ? `direct-content-${chunkSize}-${chunkOverlap}-${maxDocuments}-${dumpContent.length}` : `${dumpFilePath}-${chunkSize}-${chunkOverlap}-${maxDocuments}`; // Return cached context if available and cache is enabled if (useCache && cachedTestContext && cacheKey === currentCacheKey) { return cachedTestContext; } console.log('Setting up real data test environment...'); // Initialize components const parser = new enhanced_il2cpp_parser_1.EnhancedIL2CPPParser(); const chunker = new chunker_1.IL2CPPCodeChunker(chunkSize, chunkOverlap); // Use mock embeddings for testing to avoid Xenova loading issues const embeddings = new MockEmbeddings(); await embeddings.initialize(); // Load and parse dump.cs console.log('Loading and parsing dump.cs...'); let parseResult; try { if (useDirectContent && dumpContent) { console.log('Using direct content, length:', dumpContent.length); parser.loadContent(dumpContent); console.log('Content loaded successfully'); } else { // Verify dump.cs file exists if (!fs.existsSync(dumpFilePath)) { throw new Error(`dump.cs file not found at: ${dumpFilePath}`); } console.log('Dump file path:', dumpFilePath); console.log('File exists:', fs.existsSync(dumpFilePath)); await parser.loadFile(dumpFilePath); console.log('File loaded successfully'); } parseResult = parser.extractAllConstructs(); console.log('Parsing completed successfully'); } catch (error) { console.error('Error during parsing:', error); throw error; } console.log(`Parsed ${parseResult.statistics.totalConstructs} constructs from dump.cs`); console.log(`Classes: ${parseResult.classes.length}, Enums: ${parseResult.enums.length}, Interfaces: ${parseResult.interfaces.length}`); // Create chunks from parsed entities console.log('Creating semantic chunks...'); const allChunks = []; // Chunk classes (limit to maxDocuments to avoid overwhelming tests) const classesToProcess = parseResult.classes.slice(0, Math.floor(maxDocuments * 0.7)); for (const classEntity of classesToProcess) { const chunks = await chunker.chunkClass(classEntity); for (const chunk of chunks) { allChunks.push(new documents_1.Document({ pageContent: chunk.text, metadata: chunk.metadata })); } } // Chunk enums const enumsToProcess = parseResult.enums.slice(0, Math.floor(maxDocuments * 0.2)); for (const enumEntity of enumsToProcess) { const chunks = await chunker.chunkEnum(enumEntity); for (const chunk of chunks) { allChunks.push(new documents_1.Document({ pageContent: chunk.text, metadata: chunk.metadata })); } } // Chunk interfaces const interfacesToProcess = parseResult.interfaces.slice(0, Math.floor(maxDocuments * 0.1)); for (const interfaceEntity of interfacesToProcess) { const chunks = await chunker.chunkInterface(interfaceEntity); for (const chunk of chunks) { allChunks.push(new documents_1.Document({ pageContent: chunk.text, metadata: chunk.metadata })); } } console.log(`Created ${allChunks.length} semantic chunks`); // Create vector store and add documents console.log('Creating vector store and adding documents...'); // @ts-ignore - Type compatibility issue between different versions of LangChain const vectorStore = new memory_1.MemoryVectorStore(embeddings); // Add documents in batches to avoid memory issues const batchSize = 50; for (let i = 0; i < allChunks.length; i += batchSize) { const batch = allChunks.slice(i, i + batchSize); await vectorStore.addDocuments(batch); console.log(`Added batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(allChunks.length / batchSize)}`); } // Filter MonoBehaviours const monoBehaviours = parseResult.classes.filter(cls => cls.isMonoBehaviour); console.log(`Found ${monoBehaviours.length} MonoBehaviour classes`); // Create test context const testContext = { vectorStore, parser, chunker, embeddings, documents: allChunks, classes: parseResult.classes, enums: parseResult.enums, interfaces: parseResult.interfaces, monoBehaviours }; // Cache the context if caching is enabled if (useCache) { cachedTestContext = testContext; cacheKey = currentCacheKey; } console.log('Real data test environment setup complete!'); return testContext; } /** * Clear cached test context (useful for testing different configurations) */ function clearTestCache() { cachedTestContext = null; cacheKey = null; } /** * Get statistics about the real data test environment */ function getTestDataStatistics(context) { return { totalDocuments: context.documents.length, totalClasses: context.classes.length, totalEnums: context.enums.length, totalInterfaces: context.interfaces.length, totalMonoBehaviours: context.monoBehaviours.length, namespaces: [...new Set(context.classes.map(cls => cls.namespace).filter(Boolean))], classTypes: context.classes.reduce((acc, cls) => { const type = cls.isMonoBehaviour ? 'MonoBehaviour' : cls.isStruct ? 'Struct' : 'Class'; acc[type] = (acc[type] || 0) + 1; return acc; }, {}) }; } /** * Helper functions for finding specific entities in real data */ /** * Find a class by name in the real data */ function findClassByName(context, className) { return context.classes.find(cls => cls.name === className || cls.fullName === className || cls.name.toLowerCase() === className.toLowerCase()); } /** * Find an enum by name in the real data */ function findEnumByName(context, enumName) { return context.enums.find(enm => enm.name === enumName || enm.fullName === enumName || enm.name.toLowerCase() === enumName.toLowerCase()); } /** * Find MonoBehaviours by name pattern */ function findMonoBehavioursByPattern(context, pattern) { const lowerPattern = pattern.toLowerCase(); return context.monoBehaviours.filter(mb => mb.name.toLowerCase().includes(lowerPattern) || mb.fullName.toLowerCase().includes(lowerPattern)); } /** * Find classes by namespace */ function findClassesByNamespace(context, namespace) { return context.classes.filter(cls => cls.namespace === namespace); } /** * Get sample entities for testing (returns a few real entities for test validation) */ function getSampleEntities(context) { return { sampleClass: context.classes[0], sampleEnum: context.enums[0], sampleMonoBehaviour: context.monoBehaviours[0], sampleInterface: context.interfaces[0] }; } /** * Create a mock vector store interface that uses the real data * This allows existing tests to work with real data without major changes */ function createRealDataVectorStore(context) { return { similaritySearch: async (query, k = 5) => { return await context.vectorStore.similaritySearch(query, k); }, searchWithFilter: async (query, filter, k = 5) => { // Perform similarity search first const results = await context.vectorStore.similaritySearch(query, k * 2); // Get more results to filter // Apply filters const filteredResults = results.filter(doc => { const metadata = doc.metadata; // Apply type filter if (filter.type && metadata.type !== filter.type) { return false; } // Apply namespace filter if (filter.namespace && metadata.namespace !== filter.namespace) { return false; } // Apply MonoBehaviour filter if (filter.isMonoBehaviour && !metadata.isMonoBehaviour) { return false; } return true; }); // Return limited results return filteredResults.slice(0, k); }, addDocuments: async (documents) => { await context.vectorStore.addDocuments(documents); } }; } //# sourceMappingURL=dump-cs-test-setup.js.map